libfuse: fuse-3.2.4/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 #if defined(__FreeBSD__)
1252 #define CHECK_DIR_LOOP
1253 #endif
1254
1255 #if defined(CHECK_DIR_LOOP)
1256 static int check_dir_loop(struct fuse *f,
1257 fuse_ino_t nodeid1, const char *name1,
1258 fuse_ino_t nodeid2, const char *name2)
1259 {
1260 struct node *node, *node1, *node2;
1261 fuse_ino_t id1, id2;
1262
1263 node1 = lookup_node(f, nodeid1, name1);
1264 id1 = node1 ? node1->nodeid : nodeid1;
1265
1266 node2 = lookup_node(f, nodeid2, name2);
1267 id2 = node2 ? node2->nodeid : nodeid2;
1268
1269 for (node = get_node(f, id2); node->nodeid != FUSE_ROOT_ID;
1270 node = node->parent) {
1271 if (node->name == NULL || node->parent == NULL)
1272 break;
1273
1274 if (node->nodeid != id2 && node->nodeid == id1)
1275 return -EINVAL;
1276 }
1277
1278 if (node2)
1279 {
1280 for (node = get_node(f, id1); node->nodeid != FUSE_ROOT_ID;
1281 node = node->parent) {
1282 if (node->name == NULL || node->parent == NULL)
1283 break;
1284
1285 if (node->nodeid != id1 && node->nodeid == id2)
1286 return -ENOTEMPTY;
1287 }
1288 }
1289
1290 return 0;
1291 }
1292 #endif
1293
1294 static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1295 fuse_ino_t nodeid2, const char *name2,
1296 char **path1, char **path2,
1297 struct node **wnode1, struct node **wnode2)
1298 {
1299 int err;
1300
1301 /* FIXME: locking two paths needs deadlock checking */
1302 err = try_get_path(f, nodeid1, name1, path1, wnode1, true);
1303 if (!err) {
1304 err = try_get_path(f, nodeid2, name2, path2, wnode2, true);
1305 if (err) {
1306 struct node *wn1 = wnode1 ? *wnode1 : NULL;
1307
1308 unlock_path(f, nodeid1, wn1, NULL);
1309 free(*path1);
1310 }
1311 }
1312 return err;
1313 }
1314
1315 static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1316 fuse_ino_t nodeid2, const char *name2,
1317 char **path1, char **path2,
1318 struct node **wnode1, struct node **wnode2)
1319 {
1320 int err;
1321
1322 pthread_mutex_lock(&f->lock);
1323
1324 #if defined(CHECK_DIR_LOOP)
1325 if (name1)
1326 {
1327 // called during rename; perform dir loop check
1328 err = check_dir_loop(f, nodeid1, name1, nodeid2, name2);
1329 if (err)
1330 goto out_unlock;
1331 }
1332 #endif
1333
1334 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
1335 path1, path2, wnode1, wnode2);
1336 if (err == -EAGAIN) {
1337 struct lock_queue_element qe = {
1338 .nodeid1 = nodeid1,
1339 .name1 = name1,
1340 .path1 = path1,
1341 .wnode1 = wnode1,
1342 .nodeid2 = nodeid2,
1343 .name2 = name2,
1344 .path2 = path2,
1345 .wnode2 = wnode2,
1346 };
1347
1348 debug_path(f, "QUEUE PATH1", nodeid1, name1, !!wnode1);
1349 debug_path(f, " PATH2", nodeid2, name2, !!wnode2);
1350 err = wait_path(f, &qe);
1351 debug_path(f, "DEQUEUE PATH1", nodeid1, name1, !!wnode1);
1352 debug_path(f, " PATH2", nodeid2, name2, !!wnode2);
1353 }
1354
1355 #if defined(CHECK_DIR_LOOP)
1356 out_unlock:
1357 #endif
1358 pthread_mutex_unlock(&f->lock);
1359
1360 return err;
1361 }
1362
1363 static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid,
1364 struct node *wnode, char *path)
1365 {
1366 pthread_mutex_lock(&f->lock);
1367 unlock_path(f, nodeid, wnode, NULL);
1368 if (f->lockq)
1369 wake_up_queued(f);
1370 pthread_mutex_unlock(&f->lock);
1371 free(path);
1372 }
1373
1374 static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path)
1375 {
1376 if (path)
1377 free_path_wrlock(f, nodeid, NULL, path);
1378 }
1379
1380 static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2,
1381 struct node *wnode1, struct node *wnode2,
1382 char *path1, char *path2)
1383 {
1384 pthread_mutex_lock(&f->lock);
1385 unlock_path(f, nodeid1, wnode1, NULL);
1386 unlock_path(f, nodeid2, wnode2, NULL);
1387 wake_up_queued(f);
1388 pthread_mutex_unlock(&f->lock);
1389 free(path1);
1390 free(path2);
1391 }
1392
1393 static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
1394 {
1395 struct node *node;
1396 if (nodeid == FUSE_ROOT_ID)
1397 return;
1398 pthread_mutex_lock(&f->lock);
1399 node = get_node(f, nodeid);
1400
1401 /*
1402 * Node may still be locked due to interrupt idiocy in open,
1403 * create and opendir
1404 */
1405 while (node->nlookup == nlookup && node->treelock) {
1406 struct lock_queue_element qe = {
1407 .nodeid1 = nodeid,
1408 };
1409
1410 debug_path(f, "QUEUE PATH (forget)", nodeid, NULL, false);
1411 queue_path(f, &qe);
1412
1413 do {
1414 pthread_cond_wait(&qe.cond, &f->lock);
1415 } while (node->nlookup == nlookup && node->treelock);
1416
1417 dequeue_path(f, &qe);
1418 debug_path(f, "DEQUEUE_PATH (forget)", nodeid, NULL, false);
1419 }
1420
1421 assert(node->nlookup >= nlookup);
1422 node->nlookup -= nlookup;
1423 if (!node->nlookup) {
1424 unref_node(f, node);
1425 } else if (lru_enabled(f) && node->nlookup == 1) {
1426 set_forget_time(f, node);
1427 }
1428 pthread_mutex_unlock(&f->lock);
1429 }
1430
1431 static void unlink_node(struct fuse *f, struct node *node)
1432 {
1433 if (f->conf.remember) {
1434 assert(node->nlookup > 1);
1435 node->nlookup--;
1436 }
1437 unhash_name(f, node);
1438 }
1439
1440 static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
1441 {
1442 struct node *node;
1443
1444 pthread_mutex_lock(&f->lock);
1445 node = lookup_node(f, dir, name);
1446 if (node != NULL)
1447 unlink_node(f, node);
1448 pthread_mutex_unlock(&f->lock);
1449 }
1450
1451 static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
1452 fuse_ino_t newdir, const char *newname, int hide)
1453 {
1454 struct node *node;
1455 struct node *newnode;
1456 int err = 0;
1457
1458 pthread_mutex_lock(&f->lock);
1459 node = lookup_node(f, olddir, oldname);
1460 newnode = lookup_node(f, newdir, newname);
1461 if (node == NULL)
1462 goto out;
1463
1464 if (newnode != NULL) {
1465 if (hide) {
1466 fprintf(stderr, "fuse: hidden file got created during hiding\n");
1467 err = -EBUSY;
1468 goto out;
1469 }
1470 unlink_node(f, newnode);
1471 }
1472
1473 unhash_name(f, node);
1474 if (hash_name(f, node, newdir, newname) == -1) {
1475 err = -ENOMEM;
1476 goto out;
1477 }
1478
1479 if (hide)
1480 node->is_hidden = 1;
1481
1482 out:
1483 pthread_mutex_unlock(&f->lock);
1484 return err;
1485 }
1486
1487 static int exchange_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
1488 fuse_ino_t newdir, const char *newname)
1489 {
1490 struct node *oldnode;
1491 struct node *newnode;
1492 int err;
1493
1494 pthread_mutex_lock(&f->lock);
1495 oldnode = lookup_node(f, olddir, oldname);
1496 newnode = lookup_node(f, newdir, newname);
1497
1498 if (oldnode)
1499 unhash_name(f, oldnode);
1500 if (newnode)
1501 unhash_name(f, newnode);
1502
1503 err = -ENOMEM;
1504 if (oldnode) {
1505 if (hash_name(f, oldnode, newdir, newname) == -1)
1506 goto out;
1507 }
1508 if (newnode) {
1509 if (hash_name(f, newnode, olddir, oldname) == -1)
1510 goto out;
1511 }
1512 err = 0;
1513 out:
1514 pthread_mutex_unlock(&f->lock);
1515 return err;
1516 }
1517
1518 static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
1519 {
1520 if (!f->conf.use_ino)
1521 stbuf->st_ino = nodeid;
1522 if (f->conf.set_mode)
1523 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1524 (0777 & ~f->conf.umask);
1525 if (f->conf.set_uid)
1526 stbuf->st_uid = f->conf.uid;
1527 if (f->conf.set_gid)
1528 stbuf->st_gid = f->conf.gid;
1529 }
1530
1531 static struct fuse *req_fuse(fuse_req_t req)
1532 {
1533 return (struct fuse *) fuse_req_userdata(req);
1534 }
1535
1536 static void fuse_intr_sighandler(int sig)
1537 {
1538 (void) sig;
1539 /* Nothing to do */
1540 }
1541
1542 struct fuse_intr_data {
1543 pthread_t id;
1544 pthread_cond_t cond;
1545 int finished;
1546 };
1547
1548 static void fuse_interrupt(fuse_req_t req, void *d_)
1549 {
1550 struct fuse_intr_data *d = d_;
1551 struct fuse *f = req_fuse(req);
1552
1553 if (d->id == pthread_self())
1554 return;
1555
1556 pthread_mutex_lock(&f->lock);
1557 while (!d->finished) {
1558 struct timeval now;
1559 struct timespec timeout;
1560
1561 pthread_kill(d->id, f->conf.intr_signal);
1562 gettimeofday(&now, NULL);
1563 timeout.tv_sec = now.tv_sec + 1;
1564 timeout.tv_nsec = now.tv_usec * 1000;
1565 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
1566 }
1567 pthread_mutex_unlock(&f->lock);
1568 }
1569
1570 static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
1571 struct fuse_intr_data *d)
1572 {
1573 pthread_mutex_lock(&f->lock);
1574 d->finished = 1;
1575 pthread_cond_broadcast(&d->cond);
1576 pthread_mutex_unlock(&f->lock);
1577 fuse_req_interrupt_func(req, NULL, NULL);
1578 pthread_cond_destroy(&d->cond);
1579 }
1580
1581 static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
1582 {
1583 d->id = pthread_self();
1584 pthread_cond_init(&d->cond, NULL);
1585 d->finished = 0;
1586 fuse_req_interrupt_func(req, fuse_interrupt, d);
1587 }
1588
1589 static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
1590 struct fuse_intr_data *d)
1591 {
1592 if (f->conf.intr)
1593 fuse_do_finish_interrupt(f, req, d);
1594 }
1595
1596 static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
1597 struct fuse_intr_data *d)
1598 {
1599 if (f->conf.intr)
1600 fuse_do_prepare_interrupt(req, d);
1601 }
1602
1603 static const char* file_info_string(struct fuse_file_info *fi,
1604 char* buf, size_t len)
1605 {
1606 if(fi == NULL)
1607 return "NULL";
1608 snprintf(buf, len, "%llu", (unsigned long long) fi->fh);
1609 return buf;
1610 }
1611
1612 int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf,
1613 struct fuse_file_info *fi)
1614 {
1615 fuse_get_context()->private_data = fs->user_data;
1616 if (fs->op.getattr) {
1617 if (fs->debug) {
1618 char buf[10];
1619 fprintf(stderr, "getattr[%s] %s\n",
1620 file_info_string(fi, buf, sizeof(buf)),
1621 path);
1622 }
1623 return fs->op.getattr(path, buf, fi);
1624 } else {
1625 return -ENOSYS;
1626 }
1627 }
1628
1629 int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
1630 const char *newpath, unsigned int flags)
1631 {
1632 fuse_get_context()->private_data = fs->user_data;
1633 if (fs->op.rename) {
1634 if (fs->debug)
1635 fprintf(stderr, "rename %s %s 0x%x\n", oldpath, newpath,
1636 flags);
1637
1638 return fs->op.rename(oldpath, newpath, flags);
1639 } else {
1640 return -ENOSYS;
1641 }
1642 }
1643
1644 int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
1645 {
1646 fuse_get_context()->private_data = fs->user_data;
1647 if (fs->op.unlink) {
1648 if (fs->debug)
1649 fprintf(stderr, "unlink %s\n", path);
1650
1651 return fs->op.unlink(path);
1652 } else {
1653 return -ENOSYS;
1654 }
1655 }
1656
1657 int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
1658 {
1659 fuse_get_context()->private_data = fs->user_data;
1660 if (fs->op.rmdir) {
1661 if (fs->debug)
1662 fprintf(stderr, "rmdir %s\n", path);
1663
1664 return fs->op.rmdir(path);
1665 } else {
1666 return -ENOSYS;
1667 }
1668 }
1669
1670 int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
1671 {
1672 fuse_get_context()->private_data = fs->user_data;
1673 if (fs->op.symlink) {
1674 if (fs->debug)
1675 fprintf(stderr, "symlink %s %s\n", linkname, path);
1676
1677 return fs->op.symlink(linkname, path);
1678 } else {
1679 return -ENOSYS;
1680 }
1681 }
1682
1683 int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
1684 {
1685 fuse_get_context()->private_data = fs->user_data;
1686 if (fs->op.link) {
1687 if (fs->debug)
1688 fprintf(stderr, "link %s %s\n", oldpath, newpath);
1689
1690 return fs->op.link(oldpath, newpath);
1691 } else {
1692 return -ENOSYS;
1693 }
1694 }
1695
1696 int fuse_fs_release(struct fuse_fs *fs, const char *path,
1697 struct fuse_file_info *fi)
1698 {
1699 fuse_get_context()->private_data = fs->user_data;
1700 if (fs->op.release) {
1701 if (fs->debug)
1702 fprintf(stderr, "release%s[%llu] flags: 0x%x\n",
1703 fi->flush ? "+flush" : "",
1704 (unsigned long long) fi->fh, fi->flags);
1705
1706 return fs->op.release(path, fi);
1707 } else {
1708 return 0;
1709 }
1710 }
1711
1712 int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
1713 struct fuse_file_info *fi)
1714 {
1715 fuse_get_context()->private_data = fs->user_data;
1716 if (fs->op.opendir) {
1717 int err;
1718
1719 if (fs->debug)
1720 fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags,
1721 path);
1722
1723 err = fs->op.opendir(path, fi);
1724
1725 if (fs->debug && !err)
1726 fprintf(stderr, " opendir[%llu] flags: 0x%x %s\n",
1727 (unsigned long long) fi->fh, fi->flags, path);
1728
1729 return err;
1730 } else {
1731 return 0;
1732 }
1733 }
1734
1735 int fuse_fs_open(struct fuse_fs *fs, const char *path,
1736 struct fuse_file_info *fi)
1737 {
1738 fuse_get_context()->private_data = fs->user_data;
1739 if (fs->op.open) {
1740 int err;
1741
1742 if (fs->debug)
1743 fprintf(stderr, "open flags: 0x%x %s\n", fi->flags,
1744 path);
1745
1746 err = fs->op.open(path, fi);
1747
1748 if (fs->debug && !err)
1749 fprintf(stderr, " open[%llu] flags: 0x%x %s\n",
1750 (unsigned long long) fi->fh, fi->flags, path);
1751
1752 return err;
1753 } else {
1754 return 0;
1755 }
1756 }
1757
1758 static void fuse_free_buf(struct fuse_bufvec *buf)
1759 {
1760 if (buf != NULL) {
1761 size_t i;
1762
1763 for (i = 0; i < buf->count; i++)
1764 free(buf->buf[i].mem);
1765 free(buf);
1766 }
1767 }
1768
1769 int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
1770 struct fuse_bufvec **bufp, size_t size, off_t off,
1771 struct fuse_file_info *fi)
1772 {
1773 fuse_get_context()->private_data = fs->user_data;
1774 if (fs->op.read || fs->op.read_buf) {
1775 int res;
1776
1777 if (fs->debug)
1778 fprintf(stderr,
1779 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1780 (unsigned long long) fi->fh,
1781 size, (unsigned long long) off, fi->flags);
1782
1783 if (fs->op.read_buf) {
1784 res = fs->op.read_buf(path, bufp, size, off, fi);
1785 } else {
1786 struct fuse_bufvec *buf;
1787 void *mem;
1788
1789 buf = malloc(sizeof(struct fuse_bufvec));
1790 if (buf == NULL)
1791 return -ENOMEM;
1792
1793 mem = malloc(size);
1794 if (mem == NULL) {
1795 free(buf);
1796 return -ENOMEM;
1797 }
1798 *buf = FUSE_BUFVEC_INIT(size);
1799 buf->buf[0].mem = mem;
1800 *bufp = buf;
1801
1802 res = fs->op.read(path, mem, size, off, fi);
1803 if (res >= 0)
1804 buf->buf[0].size = res;
1805 }
1806
1807 if (fs->debug && res >= 0)
1808 fprintf(stderr, " read[%llu] %zu bytes from %llu\n",
1809 (unsigned long long) fi->fh,
1810 fuse_buf_size(*bufp),
1811 (unsigned long long) off);
1812 if (res >= 0 && fuse_buf_size(*bufp) > size)
1813 fprintf(stderr, "fuse: read too many bytes\n");
1814
1815 if (res < 0)
1816 return res;
1817
1818 return 0;
1819 } else {
1820 return -ENOSYS;
1821 }
1822 }
1823
1824 int fuse_fs_read(struct fuse_fs *fs, const char *path, char *mem, size_t size,
1825 off_t off, struct fuse_file_info *fi)
1826 {
1827 fuse_get_context()->private_data = fs->user_data;
1828 if (fs->op.read || fs->op.read_buf) {
1829 int res;
1830
1831 if (fs->debug)
1832 fprintf(stderr,
1833 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1834 (unsigned long long) fi->fh,
1835 size, (unsigned long long) off, fi->flags);
1836
1837 if (fs->op.read_buf) {
1838 struct fuse_bufvec *buf = NULL;
1839
1840 res = fs->op.read_buf(path, &buf, size, off, fi);
1841 if (res == 0) {
1842 struct fuse_bufvec dst = FUSE_BUFVEC_INIT(size);
1843
1844 dst.buf[0].mem = mem;
1845 res = fuse_buf_copy(&dst, buf, 0);
1846 }
1847 fuse_free_buf(buf);
1848 } else {
1849 res = fs->op.read(path, mem, size, off, fi);
1850 }
1851
1852 if (fs->debug && res >= 0)
1853 fprintf(stderr, " read[%llu] %u bytes from %llu\n",
1854 (unsigned long long) fi->fh,
1855 res,
1856 (unsigned long long) off);
1857 if (res >= 0 && res > (int) size)
1858 fprintf(stderr, "fuse: read too many bytes\n");
1859
1860 return res;
1861 } else {
1862 return -ENOSYS;
1863 }
1864 }
1865
1866 int fuse_fs_write_buf(struct fuse_fs *fs, const char *path,
1867 struct fuse_bufvec *buf, off_t off,
1868 struct fuse_file_info *fi)
1869 {
1870 fuse_get_context()->private_data = fs->user_data;
1871 if (fs->op.write_buf || fs->op.write) {
1872 int res;
1873 size_t size = fuse_buf_size(buf);
1874
1875 assert(buf->idx == 0 && buf->off == 0);
1876 if (fs->debug)
1877 fprintf(stderr,
1878 "write%s[%llu] %zu bytes to %llu flags: 0x%x\n",
1879 fi->writepage ? "page" : "",
1880 (unsigned long long) fi->fh,
1881 size,
1882 (unsigned long long) off,
1883 fi->flags);
1884
1885 if (fs->op.write_buf) {
1886 res = fs->op.write_buf(path, buf, off, fi);
1887 } else {
1888 void *mem = NULL;
1889 struct fuse_buf *flatbuf;
1890 struct fuse_bufvec tmp = FUSE_BUFVEC_INIT(size);
1891
1892 if (buf->count == 1 &&
1893 !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
1894 flatbuf = &buf->buf[0];
1895 } else {
1896 res = -ENOMEM;
1897 mem = malloc(size);
1898 if (mem == NULL)
1899 goto out;
1900
1901 tmp.buf[0].mem = mem;
1902 res = fuse_buf_copy(&tmp, buf, 0);
1903 if (res <= 0)
1904 goto out_free;
1905
1906 tmp.buf[0].size = res;
1907 flatbuf = &tmp.buf[0];
1908 }
1909
1910 res = fs->op.write(path, flatbuf->mem, flatbuf->size,
1911 off, fi);
1912 out_free:
1913 free(mem);
1914 }
1915 out:
1916 if (fs->debug && res >= 0)
1917 fprintf(stderr, " write%s[%llu] %u bytes to %llu\n",
1918 fi->writepage ? "page" : "",
1919 (unsigned long long) fi->fh, res,
1920 (unsigned long long) off);
1921 if (res > (int) size)
1922 fprintf(stderr, "fuse: wrote too many bytes\n");
1923
1924 return res;
1925 } else {
1926 return -ENOSYS;
1927 }
1928 }
1929
1930 int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *mem,
1931 size_t size, off_t off, struct fuse_file_info *fi)
1932 {
1933 struct fuse_bufvec bufv = FUSE_BUFVEC_INIT(size);
1934
1935 bufv.buf[0].mem = (void *) mem;
1936
1937 return fuse_fs_write_buf(fs, path, &bufv, off, fi);
1938 }
1939
1940 int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
1941 struct fuse_file_info *fi)
1942 {
1943 fuse_get_context()->private_data = fs->user_data;
1944 if (fs->op.fsync) {
1945 if (fs->debug)
1946 fprintf(stderr, "fsync[%llu] datasync: %i\n",
1947 (unsigned long long) fi->fh, datasync);
1948
1949 return fs->op.fsync(path, datasync, fi);
1950 } else {
1951 return -ENOSYS;
1952 }
1953 }
1954
1955 int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
1956 struct fuse_file_info *fi)
1957 {
1958 fuse_get_context()->private_data = fs->user_data;
1959 if (fs->op.fsyncdir) {
1960 if (fs->debug)
1961 fprintf(stderr, "fsyncdir[%llu] datasync: %i\n",
1962 (unsigned long long) fi->fh, datasync);
1963
1964 return fs->op.fsyncdir(path, datasync, fi);
1965 } else {
1966 return -ENOSYS;
1967 }
1968 }
1969
1970 int fuse_fs_flush(struct fuse_fs *fs, const char *path,
1971 struct fuse_file_info *fi)
1972 {
1973 fuse_get_context()->private_data = fs->user_data;
1974 if (fs->op.flush) {
1975 if (fs->debug)
1976 fprintf(stderr, "flush[%llu]\n",
1977 (unsigned long long) fi->fh);
1978
1979 return fs->op.flush(path, fi);
1980 } else {
1981 return -ENOSYS;
1982 }
1983 }
1984
1985 int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
1986 {
1987 fuse_get_context()->private_data = fs->user_data;
1988 if (fs->op.statfs) {
1989 if (fs->debug)
1990 fprintf(stderr, "statfs %s\n", path);
1991
1992 return fs->op.statfs(path, buf);
1993 } else {
1994 buf->f_namemax = 255;
1995 buf->f_bsize = 512;
1996 return 0;
1997 }
1998 }
1999
2000 int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
2001 struct fuse_file_info *fi)
2002 {
2003 fuse_get_context()->private_data = fs->user_data;
2004 if (fs->op.releasedir) {
2005 if (fs->debug)
2006 fprintf(stderr, "releasedir[%llu] flags: 0x%x\n",
2007 (unsigned long long) fi->fh, fi->flags);
2008
2009 return fs->op.releasedir(path, fi);
2010 } else {
2011 return 0;
2012 }
2013 }
2014
2015 int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
2016 fuse_fill_dir_t filler, off_t off,
2017 struct fuse_file_info *fi,
2018 enum fuse_readdir_flags flags)
2019 {
2020 fuse_get_context()->private_data = fs->user_data;
2021 if (fs->op.readdir) {
2022 if (fs->debug) {
2023 fprintf(stderr, "readdir%s[%llu] from %llu\n",
2024 (flags & FUSE_READDIR_PLUS) ? "plus" : "",
2025 (unsigned long long) fi->fh,
2026 (unsigned long long) off);
2027 }
2028
2029 return fs->op.readdir(path, buf, filler, off, fi, flags);
2030 } else {
2031 return -ENOSYS;
2032 }
2033 }
2034
2035 int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
2036 struct fuse_file_info *fi)
2037 {
2038 fuse_get_context()->private_data = fs->user_data;
2039 if (fs->op.create) {
2040 int err;
2041
2042 if (fs->debug)
2043 fprintf(stderr,
2044 "create flags: 0x%x %s 0%o umask=0%03o\n",
2045 fi->flags, path, mode,
2046 fuse_get_context()->umask);
2047
2048 err = fs->op.create(path, mode, fi);
2049
2050 if (fs->debug && !err)
2051 fprintf(stderr, " create[%llu] flags: 0x%x %s\n",
2052 (unsigned long long) fi->fh, fi->flags, path);
2053
2054 return err;
2055 } else {
2056 return -ENOSYS;
2057 }
2058 }
2059
2060 int fuse_fs_lock(struct fuse_fs *fs, const char *path,
2061 struct fuse_file_info *fi, int cmd, struct flock *lock)
2062 {
2063 fuse_get_context()->private_data = fs->user_data;
2064 if (fs->op.lock) {
2065 if (fs->debug)
2066 fprintf(stderr, "lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
2067 (unsigned long long) fi->fh,
2068 (cmd == F_GETLK ? "F_GETLK" :
2069 (cmd == F_SETLK ? "F_SETLK" :
2070 (cmd == F_SETLKW ? "F_SETLKW" : "???"))),
2071 (lock->l_type == F_RDLCK ? "F_RDLCK" :
2072 (lock->l_type == F_WRLCK ? "F_WRLCK" :
2073 (lock->l_type == F_UNLCK ? "F_UNLCK" :
2074 "???"))),
2075 (unsigned long long) lock->l_start,
2076 (unsigned long long) lock->l_len,
2077 (unsigned long long) lock->l_pid);
2078
2079 return fs->op.lock(path, fi, cmd, lock);
2080 } else {
2081 return -ENOSYS;
2082 }
2083 }
2084
2085 int fuse_fs_flock(struct fuse_fs *fs, const char *path,
2086 struct fuse_file_info *fi, int op)
2087 {
2088 fuse_get_context()->private_data = fs->user_data;
2089 if (fs->op.flock) {
2090 if (fs->debug) {
2091 int xop = op & ~LOCK_NB;
2092
2093 fprintf(stderr, "lock[%llu] %s%s\n",
2094 (unsigned long long) fi->fh,
2095 xop == LOCK_SH ? "LOCK_SH" :
2096 (xop == LOCK_EX ? "LOCK_EX" :
2097 (xop == LOCK_UN ? "LOCK_UN" : "???")),
2098 (op & LOCK_NB) ? "|LOCK_NB" : "");
2099 }
2100 return fs->op.flock(path, fi, op);
2101 } else {
2102 return -ENOSYS;
2103 }
2104 }
2105
2106 int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid,
2107 gid_t gid, struct fuse_file_info *fi)
2108 {
2109 fuse_get_context()->private_data = fs->user_data;
2110 if (fs->op.chown) {
2111 if (fs->debug) {
2112 char buf[10];
2113 fprintf(stderr, "chown[%s] %s %lu %lu\n",
2114 file_info_string(fi, buf, sizeof(buf)),
2115 path, (unsigned long) uid, (unsigned long) gid);
2116 }
2117 return fs->op.chown(path, uid, gid, fi);
2118 } else {
2119 return -ENOSYS;
2120 }
2121 }
2122
2123 int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size,
2124 struct fuse_file_info *fi)
2125 {
2126 fuse_get_context()->private_data = fs->user_data;
2127 if (fs->op.truncate) {
2128 if (fs->debug) {
2129 char buf[10];
2130 fprintf(stderr, "truncate[%s] %llu\n",
2131 file_info_string(fi, buf, sizeof(buf)),
2132 (unsigned long long) size);
2133 }
2134 return fs->op.truncate(path, size, fi);
2135 } else {
2136 return -ENOSYS;
2137 }
2138 }
2139
2140 int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
2141 const struct timespec tv[2], struct fuse_file_info *fi)
2142 {
2143 fuse_get_context()->private_data = fs->user_data;
2144 if (fs->op.utimens) {
2145 if (fs->debug) {
2146 char buf[10];
2147 fprintf(stderr, "utimens[%s] %s %li.%09lu %li.%09lu\n",
2148 file_info_string(fi, buf, sizeof(buf)),
2149 path, tv[0].tv_sec, tv[0].tv_nsec,
2150 tv[1].tv_sec, tv[1].tv_nsec);
2151 }
2152 return fs->op.utimens(path, tv, fi);
2153 } else {
2154 return -ENOSYS;
2155 }
2156 }
2157
2158 int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
2159 {
2160 fuse_get_context()->private_data = fs->user_data;
2161 if (fs->op.access) {
2162 if (fs->debug)
2163 fprintf(stderr, "access %s 0%o\n", path, mask);
2164
2165 return fs->op.access(path, mask);
2166 } else {
2167 return -ENOSYS;
2168 }
2169 }
2170
2171 int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
2172 size_t len)
2173 {
2174 fuse_get_context()->private_data = fs->user_data;
2175 if (fs->op.readlink) {
2176 if (fs->debug)
2177 fprintf(stderr, "readlink %s %lu\n", path,
2178 (unsigned long) len);
2179
2180 return fs->op.readlink(path, buf, len);
2181 } else {
2182 return -ENOSYS;
2183 }
2184 }
2185
2186 int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
2187 dev_t rdev)
2188 {
2189 fuse_get_context()->private_data = fs->user_data;
2190 if (fs->op.mknod) {
2191 if (fs->debug)
2192 fprintf(stderr, "mknod %s 0%o 0x%llx umask=0%03o\n",
2193 path, mode, (unsigned long long) rdev,
2194 fuse_get_context()->umask);
2195
2196 return fs->op.mknod(path, mode, rdev);
2197 } else {
2198 return -ENOSYS;
2199 }
2200 }
2201
2202 int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
2203 {
2204 fuse_get_context()->private_data = fs->user_data;
2205 if (fs->op.mkdir) {
2206 if (fs->debug)
2207 fprintf(stderr, "mkdir %s 0%o umask=0%03o\n",
2208 path, mode, fuse_get_context()->umask);
2209
2210 return fs->op.mkdir(path, mode);
2211 } else {
2212 return -ENOSYS;
2213 }
2214 }
2215
2216 int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
2217 const char *value, size_t size, int flags)
2218 {
2219 fuse_get_context()->private_data = fs->user_data;
2220 if (fs->op.setxattr) {
2221 if (fs->debug)
2222 fprintf(stderr, "setxattr %s %s %lu 0x%x\n",
2223 path, name, (unsigned long) size, flags);
2224
2225 return fs->op.setxattr(path, name, value, size, flags);
2226 } else {
2227 return -ENOSYS;
2228 }
2229 }
2230
2231 int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
2232 char *value, size_t size)
2233 {
2234 fuse_get_context()->private_data = fs->user_data;
2235 if (fs->op.getxattr) {
2236 if (fs->debug)
2237 fprintf(stderr, "getxattr %s %s %lu\n",
2238 path, name, (unsigned long) size);
2239
2240 return fs->op.getxattr(path, name, value, size);
2241 } else {
2242 return -ENOSYS;
2243 }
2244 }
2245
2246 int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
2247 size_t size)
2248 {
2249 fuse_get_context()->private_data = fs->user_data;
2250 if (fs->op.listxattr) {
2251 if (fs->debug)
2252 fprintf(stderr, "listxattr %s %lu\n",
2253 path, (unsigned long) size);
2254
2255 return fs->op.listxattr(path, list, size);
2256 } else {
2257 return -ENOSYS;
2258 }
2259 }
2260
2261 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
2262 uint64_t *idx)
2263 {
2264 fuse_get_context()->private_data = fs->user_data;
2265 if (fs->op.bmap) {
2266 if (fs->debug)
2267 fprintf(stderr, "bmap %s blocksize: %lu index: %llu\n",
2268 path, (unsigned long) blocksize,
2269 (unsigned long long) *idx);
2270
2271 return fs->op.bmap(path, blocksize, idx);
2272 } else {
2273 return -ENOSYS;
2274 }
2275 }
2276
2277 int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
2278 {
2279 fuse_get_context()->private_data = fs->user_data;
2280 if (fs->op.removexattr) {
2281 if (fs->debug)
2282 fprintf(stderr, "removexattr %s %s\n", path, name);
2283
2284 return fs->op.removexattr(path, name);
2285 } else {
2286 return -ENOSYS;
2287 }
2288 }
2289
2290 int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
2291 struct fuse_file_info *fi, unsigned int flags, void *data)
2292 {
2293 fuse_get_context()->private_data = fs->user_data;
2294 if (fs->op.ioctl) {
2295 if (fs->debug)
2296 fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
2297 (unsigned long long) fi->fh, cmd, flags);
2298
2299 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2300 } else
2301 return -ENOSYS;
2302 }
2303
2304 int fuse_fs_poll(struct fuse_fs *fs, const char *path,
2305 struct fuse_file_info *fi, struct fuse_pollhandle *ph,
2306 unsigned *reventsp)
2307 {
2308 fuse_get_context()->private_data = fs->user_data;
2309 if (fs->op.poll) {
2310 int res;
2311
2312 if (fs->debug)
2313 fprintf(stderr, "poll[%llu] ph: %p, events 0x%x\n",
2314 (unsigned long long) fi->fh, ph,
2315 fi->poll_events);
2316
2317 res = fs->op.poll(path, fi, ph, reventsp);
2318
2319 if (fs->debug && !res)
2320 fprintf(stderr, " poll[%llu] revents: 0x%x\n",
2321 (unsigned long long) fi->fh, *reventsp);
2322
2323 return res;
2324 } else
2325 return -ENOSYS;
2326 }
2327
2328 int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
2329 off_t offset, off_t length, struct fuse_file_info *fi)
2330 {
2331 fuse_get_context()->private_data = fs->user_data;
2332 if (fs->op.fallocate) {
2333 if (fs->debug)
2334 fprintf(stderr, "fallocate %s mode %x, offset: %llu, length: %llu\n",
2335 path,
2336 mode,
2337 (unsigned long long) offset,
2338 (unsigned long long) length);
2339
2340 return fs->op.fallocate(path, mode, offset, length, fi);
2341 } else
2342 return -ENOSYS;
2343 }
2344
2345 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
2346 {
2347 struct node *node;
2348 int isopen = 0;
2349 pthread_mutex_lock(&f->lock);
2350 node = lookup_node(f, dir, name);
2351 if (node && node->open_count > 0)
2352 isopen = 1;
2353 pthread_mutex_unlock(&f->lock);
2354 return isopen;
2355 }
2356
2357 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
2358 char *newname, size_t bufsize)
2359 {
2360 struct stat buf;
2361 struct node *node;
2362 struct node *newnode;
2363 char *newpath;
2364 int res;
2365 int failctr = 10;
2366
2367 do {
2368 pthread_mutex_lock(&f->lock);
2369 node = lookup_node(f, dir, oldname);
2370 if (node == NULL) {
2371 pthread_mutex_unlock(&f->lock);
2372 return NULL;
2373 }
2374 do {
2375 f->hidectr ++;
2376 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
2377 (unsigned int) node->nodeid, f->hidectr);
2378 newnode = lookup_node(f, dir, newname);
2379 } while(newnode);
2380
2381 res = try_get_path(f, dir, newname, &newpath, NULL, false);
2382 pthread_mutex_unlock(&f->lock);
2383 if (res)
2384 break;
2385
2386 memset(&buf, 0, sizeof(buf));
2387 res = fuse_fs_getattr(f->fs, newpath, &buf, NULL);
2388 if (res == -ENOENT)
2389 break;
2390 free(newpath);
2391 newpath = NULL;
2392 } while(res == 0 && --failctr);
2393
2394 return newpath;
2395 }
2396
2397 static int hide_node(struct fuse *f, const char *oldpath,
2398 fuse_ino_t dir, const char *oldname)
2399 {
2400 char newname[64];
2401 char *newpath;
2402 int err = -EBUSY;
2403
2404 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
2405 if (newpath) {
2406 err = fuse_fs_rename(f->fs, oldpath, newpath, 0);
2407 if (!err)
2408 err = rename_node(f, dir, oldname, dir, newname, 1);
2409 free(newpath);
2410 }
2411 return err;
2412 }
2413
2414 static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
2415 {
2416 return stbuf->st_mtime == ts->tv_sec &&
2417 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2418 }
2419
2420 #ifndef CLOCK_MONOTONIC
2421 #define CLOCK_MONOTONIC CLOCK_REALTIME
2422 #endif
2423
2424 static void curr_time(struct timespec *now)
2425 {
2426 static clockid_t clockid = CLOCK_MONOTONIC;
2427 int res = clock_gettime(clockid, now);
2428 if (res == -1 && errno == EINVAL) {
2429 clockid = CLOCK_REALTIME;
2430 res = clock_gettime(clockid, now);
2431 }
2432 if (res == -1) {
2433 perror("fuse: clock_gettime");
2434 abort();
2435 }
2436 }
2437
2438 static void update_stat(struct node *node, const struct stat *stbuf)
2439 {
2440 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2441 stbuf->st_size != node->size))
2442 node->cache_valid = 0;
2443 node->mtime.tv_sec = stbuf->st_mtime;
2444 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2445 node->size = stbuf->st_size;
2446 curr_time(&node->stat_updated);
2447 }
2448
2449 static int do_lookup(struct fuse *f, fuse_ino_t nodeid, const char *name,
2450 struct fuse_entry_param *e)
2451 {
2452 struct node *node;
2453
2454 node = find_node(f, nodeid, name);
2455 if (node == NULL)
2456 return -ENOMEM;
2457
2458 e->ino = node->nodeid;
2459 e->generation = node->generation;
2460 e->entry_timeout = f->conf.entry_timeout;
2461 e->attr_timeout = f->conf.attr_timeout;
2462 if (f->conf.auto_cache) {
2463 pthread_mutex_lock(&f->lock);
2464 update_stat(node, &e->attr);
2465 pthread_mutex_unlock(&f->lock);
2466 }
2467 set_stat(f, e->ino, &e->attr);
2468 return 0;
2469 }
2470
2471 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
2472 const char *name, const char *path,
2473 struct fuse_entry_param *e, struct fuse_file_info *fi)
2474 {
2475 int res;
2476
2477 memset(e, 0, sizeof(struct fuse_entry_param));
2478 res = fuse_fs_getattr(f->fs, path, &e->attr, fi);
2479 if (res == 0) {
2480 res = do_lookup(f, nodeid, name, e);
2481 if (res == 0 && f->conf.debug) {
2482 fprintf(stderr, " NODEID: %llu\n",
2483 (unsigned long long) e->ino);
2484 }
2485 }
2486 return res;
2487 }
2488
2489 static struct fuse_context_i *fuse_get_context_internal(void)
2490 {
2491 return (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2492 }
2493
2494 static struct fuse_context_i *fuse_create_context(struct fuse *f)
2495 {
2496 struct fuse_context_i *c = fuse_get_context_internal();
2497 if (c == NULL) {
2498 c = (struct fuse_context_i *)
2499 calloc(1, sizeof(struct fuse_context_i));
2500 if (c == NULL) {
2501 /* This is hard to deal with properly, so just
2502 abort. If memory is so low that the
2503 context cannot be allocated, there's not
2504 much hope for the filesystem anyway */
2505 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
2506 abort();
2507 }
2508 pthread_setspecific(fuse_context_key, c);
2509 } else {
2510 memset(c, 0, sizeof(*c));
2511 }
2512 c->ctx.fuse = f;
2513
2514 return c;
2515 }
2516
2517 static void fuse_freecontext(void *data)
2518 {
2519 free(data);
2520 }
2521
2522 static int fuse_create_context_key(void)
2523 {
2524 int err = 0;
2525 pthread_mutex_lock(&fuse_context_lock);
2526 if (!fuse_context_ref) {
2527 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2528 if (err) {
2529 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
2530 strerror(err));
2531 pthread_mutex_unlock(&fuse_context_lock);
2532 return -1;
2533 }
2534 }
2535 fuse_context_ref++;
2536 pthread_mutex_unlock(&fuse_context_lock);
2537 return 0;
2538 }
2539
2540 static void fuse_delete_context_key(void)
2541 {
2542 pthread_mutex_lock(&fuse_context_lock);
2543 fuse_context_ref--;
2544 if (!fuse_context_ref) {
2545 free(pthread_getspecific(fuse_context_key));
2546 pthread_key_delete(fuse_context_key);
2547 }
2548 pthread_mutex_unlock(&fuse_context_lock);
2549 }
2550
2551 static struct fuse *req_fuse_prepare(fuse_req_t req)
2552 {
2553 struct fuse_context_i *c = fuse_create_context(req_fuse(req));
2554 const struct fuse_ctx *ctx = fuse_req_ctx(req);
2555 c->req = req;
2556 c->ctx.uid = ctx->uid;
2557 c->ctx.gid = ctx->gid;
2558 c->ctx.pid = ctx->pid;
2559 c->ctx.umask = ctx->umask;
2560 return c->ctx.fuse;
2561 }
2562
2563 static inline void reply_err(fuse_req_t req, int err)
2564 {
2565 /* fuse_reply_err() uses non-negated errno values */
2566 fuse_reply_err(req, -err);
2567 }
2568
2569 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
2570 int err)
2571 {
2572 if (!err) {
2573 struct fuse *f = req_fuse(req);
2574 if (fuse_reply_entry(req, e) == -ENOENT) {
2575 /* Skip forget for negative result */
2576 if (e->ino != 0)
2577 forget_node(f, e->ino, 1);
2578 }
2579 } else
2580 reply_err(req, err);
2581 }
2582
2583 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn,
2584 struct fuse_config *cfg)
2585 {
2586 fuse_get_context()->private_data = fs->user_data;
2587 if (!fs->op.write_buf)
2588 conn->want &= ~FUSE_CAP_SPLICE_READ;
2589 if (!fs->op.lock)
2590 conn->want &= ~FUSE_CAP_POSIX_LOCKS;
2591 if (!fs->op.flock)
2592 conn->want &= ~FUSE_CAP_FLOCK_LOCKS;
2593 if (fs->op.init)
2594 fs->user_data = fs->op.init(conn, cfg);
2595 }
2596
2597 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
2598 {
2599 struct fuse *f = (struct fuse *) data;
2600
2601 fuse_create_context(f);
2602 if(conn->capable & FUSE_CAP_EXPORT_SUPPORT)
2603 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
2604 fuse_fs_init(f->fs, conn, &f->conf);
2605 }
2606
2607 void fuse_fs_destroy(struct fuse_fs *fs)
2608 {
2609 fuse_get_context()->private_data = fs->user_data;
2610 if (fs->op.destroy)
2611 fs->op.destroy(fs->user_data);
2612 if (fs->m)
2613 fuse_put_module(fs->m);
2614 free(fs);
2615 }
2616
2617 static void fuse_lib_destroy(void *data)
2618 {
2619 struct fuse *f = (struct fuse *) data;
2620
2621 fuse_create_context(f);
2622 fuse_fs_destroy(f->fs);
2623 f->fs = NULL;
2624 }
2625
2626 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
2627 const char *name)
2628 {
2629 struct fuse *f = req_fuse_prepare(req);
2630 struct fuse_entry_param e;
2631 char *path;
2632 int err;
2633 struct node *dot = NULL;
2634
2635 if (name[0] == '.') {
2636 int len = strlen(name);
2637
2638 if (len == 1 || (name[1] == '.' && len == 2)) {
2639 pthread_mutex_lock(&f->lock);
2640 if (len == 1) {
2641 if (f->conf.debug)
2642 fprintf(stderr, "LOOKUP-DOT\n");
2643 dot = get_node_nocheck(f, parent);
2644 if (dot == NULL) {
2645 pthread_mutex_unlock(&f->lock);
2646 reply_entry(req, &e, -ESTALE);
2647 return;
2648 }
2649 dot->refctr++;
2650 } else {
2651 if (f->conf.debug)
2652 fprintf(stderr, "LOOKUP-DOTDOT\n");
2653 parent = get_node(f, parent)->parent->nodeid;
2654 }
2655 pthread_mutex_unlock(&f->lock);
2656 name = NULL;
2657 }
2658 }
2659
2660 err = get_path_name(f, parent, name, &path);
2661 if (!err) {
2662 struct fuse_intr_data d;
2663 if (f->conf.debug)
2664 fprintf(stderr, "LOOKUP %s\n", path);
2665 fuse_prepare_interrupt(f, req, &d);
2666 err = lookup_path(f, parent, name, path, &e, NULL);
2667 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2668 e.ino = 0;
2669 e.entry_timeout = f->conf.negative_timeout;
2670 err = 0;
2671 }
2672 fuse_finish_interrupt(f, req, &d);
2673 free_path(f, parent, path);
2674 }
2675 if (dot) {
2676 pthread_mutex_lock(&f->lock);
2677 unref_node(f, dot);
2678 pthread_mutex_unlock(&f->lock);
2679 }
2680 reply_entry(req, &e, err);
2681 }
2682
2683 static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
2684 {
2685 if (f->conf.debug)
2686 fprintf(stderr, "FORGET %llu/%llu\n", (unsigned long long)ino,
2687 (unsigned long long) nlookup);
2688 forget_node(f, ino, nlookup);
2689 }
2690
2691 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
2692 {
2693 do_forget(req_fuse(req), ino, nlookup);
2694 fuse_reply_none(req);
2695 }
2696
2697 static void fuse_lib_forget_multi(fuse_req_t req, size_t count,
2698 struct fuse_forget_data *forgets)
2699 {
2700 struct fuse *f = req_fuse(req);
2701 size_t i;
2702
2703 for (i = 0; i < count; i++)
2704 do_forget(f, forgets[i].ino, forgets[i].nlookup);
2705
2706 fuse_reply_none(req);
2707 }
2708
2709
2710 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
2711 struct fuse_file_info *fi)
2712 {
2713 struct fuse *f = req_fuse_prepare(req);
2714 struct stat buf;
2715 char *path;
2716 int err;
2717
2718 memset(&buf, 0, sizeof(buf));
2719
2720 if (fi != NULL)
2721 err = get_path_nullok(f, ino, &path);
2722 else
2723 err = get_path(f, ino, &path);
2724 if (!err) {
2725 struct fuse_intr_data d;
2726 fuse_prepare_interrupt(f, req, &d);
2727 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2728 fuse_finish_interrupt(f, req, &d);
2729 free_path(f, ino, path);
2730 }
2731 if (!err) {
2732 struct node *node;
2733
2734 pthread_mutex_lock(&f->lock);
2735 node = get_node(f, ino);
2736 if (node->is_hidden && buf.st_nlink > 0)
2737 buf.st_nlink--;
2738 if (f->conf.auto_cache)
2739 update_stat(node, &buf);
2740 pthread_mutex_unlock(&f->lock);
2741 set_stat(f, ino, &buf);
2742 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2743 } else
2744 reply_err(req, err);
2745 }
2746
2747 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode,
2748 struct fuse_file_info *fi)
2749 {
2750 fuse_get_context()->private_data = fs->user_data;
2751 if (fs->op.chmod) {
2752 if (fs->debug) {
2753 char buf[10];
2754 fprintf(stderr, "chmod[%s] %s %llo\n",
2755 file_info_string(fi, buf, sizeof(buf)),
2756 path, (unsigned long long) mode);
2757 }
2758 return fs->op.chmod(path, mode, fi);
2759 }
2760 else
2761 return -ENOSYS;
2762 }
2763
2764 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2765 int valid, struct fuse_file_info *fi)
2766 {
2767 struct fuse *f = req_fuse_prepare(req);
2768 struct stat buf;
2769 char *path;
2770 int err;
2771
2772 memset(&buf, 0, sizeof(buf));
2773 if (fi != NULL)
2774 err = get_path_nullok(f, ino, &path);
2775 else
2776 err = get_path(f, ino, &path);
2777 if (!err) {
2778 struct fuse_intr_data d;
2779 fuse_prepare_interrupt(f, req, &d);
2780 err = 0;
2781 if (!err && (valid & FUSE_SET_ATTR_MODE))
2782 err = fuse_fs_chmod(f->fs, path, attr->st_mode, fi);
2783 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2784 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2785 attr->st_uid : (uid_t) -1;
2786 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2787 attr->st_gid : (gid_t) -1;
2788 err = fuse_fs_chown(f->fs, path, uid, gid, fi);
2789 }
2790 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2791 err = fuse_fs_truncate(f->fs, path,
2792 attr->st_size, fi);
2793 }
2794 #ifdef HAVE_UTIMENSAT
2795 if (!err &&
2796 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2797 struct timespec tv[2];
2798
2799 tv[0].tv_sec = 0;
2800 tv[1].tv_sec = 0;
2801 tv[0].tv_nsec = UTIME_OMIT;
2802 tv[1].tv_nsec = UTIME_OMIT;
2803
2804 if (valid & FUSE_SET_ATTR_ATIME_NOW)
2805 tv[0].tv_nsec = UTIME_NOW;
2806 else if (valid & FUSE_SET_ATTR_ATIME)
2807 tv[0] = attr->st_atim;
2808
2809 if (valid & FUSE_SET_ATTR_MTIME_NOW)
2810 tv[1].tv_nsec = UTIME_NOW;
2811 else if (valid & FUSE_SET_ATTR_MTIME)
2812 tv[1] = attr->st_mtim;
2813
2814 err = fuse_fs_utimens(f->fs, path, tv, fi);
2815 } else
2816 #endif
2817 if (!err &&
2818 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2819 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2820 struct timespec tv[2];
2821 tv[0].tv_sec = attr->st_atime;
2822 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2823 tv[1].tv_sec = attr->st_mtime;
2824 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2825 err = fuse_fs_utimens(f->fs, path, tv, fi);
2826 }
2827 if (!err) {
2828 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2829 }
2830 fuse_finish_interrupt(f, req, &d);
2831 free_path(f, ino, path);
2832 }
2833 if (!err) {
2834 if (f->conf.auto_cache) {
2835 pthread_mutex_lock(&f->lock);
2836 update_stat(get_node(f, ino), &buf);
2837 pthread_mutex_unlock(&f->lock);
2838 }
2839 set_stat(f, ino, &buf);
2840 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2841 } else
2842 reply_err(req, err);
2843 }
2844
2845 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
2846 {
2847 struct fuse *f = req_fuse_prepare(req);
2848 char *path;
2849 int err;
2850
2851 err = get_path(f, ino, &path);
2852 if (!err) {
2853 struct fuse_intr_data d;
2854
2855 fuse_prepare_interrupt(f, req, &d);
2856 err = fuse_fs_access(f->fs, path, mask);
2857 fuse_finish_interrupt(f, req, &d);
2858 free_path(f, ino, path);
2859 }
2860 reply_err(req, err);
2861 }
2862
2863 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
2864 {
2865 struct fuse *f = req_fuse_prepare(req);
2866 char linkname[PATH_MAX + 1];
2867 char *path;
2868 int err;
2869
2870 err = get_path(f, ino, &path);
2871 if (!err) {
2872 struct fuse_intr_data d;
2873 fuse_prepare_interrupt(f, req, &d);
2874 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
2875 fuse_finish_interrupt(f, req, &d);
2876 free_path(f, ino, path);
2877 }
2878 if (!err) {
2879 linkname[PATH_MAX] = '\0';
2880 fuse_reply_readlink(req, linkname);
2881 } else
2882 reply_err(req, err);
2883 }
2884
2885 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2886 mode_t mode, dev_t rdev)
2887 {
2888 struct fuse *f = req_fuse_prepare(req);
2889 struct fuse_entry_param e;
2890 char *path;
2891 int err;
2892
2893 err = get_path_name(f, parent, name, &path);
2894 if (!err) {
2895 struct fuse_intr_data d;
2896
2897 fuse_prepare_interrupt(f, req, &d);
2898 err = -ENOSYS;
2899 if (S_ISREG(mode)) {
2900 struct fuse_file_info fi;
2901
2902 memset(&fi, 0, sizeof(fi));
2903 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
2904 err = fuse_fs_create(f->fs, path, mode, &fi);
2905 if (!err) {
2906 err = lookup_path(f, parent, name, path, &e,
2907 &fi);
2908 fuse_fs_release(f->fs, path, &fi);
2909 }
2910 }
2911 if (err == -ENOSYS) {
2912 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2913 if (!err)
2914 err = lookup_path(f, parent, name, path, &e,
2915 NULL);
2916 }
2917 fuse_finish_interrupt(f, req, &d);
2918 free_path(f, parent, path);
2919 }
2920 reply_entry(req, &e, err);
2921 }
2922
2923 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
2924 mode_t mode)
2925 {
2926 struct fuse *f = req_fuse_prepare(req);
2927 struct fuse_entry_param e;
2928 char *path;
2929 int err;
2930
2931 err = get_path_name(f, parent, name, &path);
2932 if (!err) {
2933 struct fuse_intr_data d;
2934
2935 fuse_prepare_interrupt(f, req, &d);
2936 err = fuse_fs_mkdir(f->fs, path, mode);
2937 if (!err)
2938 err = lookup_path(f, parent, name, path, &e, NULL);
2939 fuse_finish_interrupt(f, req, &d);
2940 free_path(f, parent, path);
2941 }
2942 reply_entry(req, &e, err);
2943 }
2944
2945 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
2946 const char *name)
2947 {
2948 struct fuse *f = req_fuse_prepare(req);
2949 struct node *wnode;
2950 char *path;
2951 int err;
2952
2953 err = get_path_wrlock(f, parent, name, &path, &wnode);
2954 if (!err) {
2955 struct fuse_intr_data d;
2956
2957 fuse_prepare_interrupt(f, req, &d);
2958 if (!f->conf.hard_remove && is_open(f, parent, name)) {
2959 err = hide_node(f, path, parent, name);
2960 } else {
2961 err = fuse_fs_unlink(f->fs, path);
2962 if (!err)
2963 remove_node(f, parent, name);
2964 }
2965 fuse_finish_interrupt(f, req, &d);
2966 free_path_wrlock(f, parent, wnode, path);
2967 }
2968 reply_err(req, err);
2969 }
2970
2971 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
2972 {
2973 struct fuse *f = req_fuse_prepare(req);
2974 struct node *wnode;
2975 char *path;
2976 int err;
2977
2978 err = get_path_wrlock(f, parent, name, &path, &wnode);
2979 if (!err) {
2980 struct fuse_intr_data d;
2981
2982 fuse_prepare_interrupt(f, req, &d);
2983 err = fuse_fs_rmdir(f->fs, path);
2984 fuse_finish_interrupt(f, req, &d);
2985 if (!err)
2986 remove_node(f, parent, name);
2987 free_path_wrlock(f, parent, wnode, path);
2988 }
2989 reply_err(req, err);
2990 }
2991
2992 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
2993 fuse_ino_t parent, const char *name)
2994 {
2995 struct fuse *f = req_fuse_prepare(req);
2996 struct fuse_entry_param e;
2997 char *path;
2998 int err;
2999
3000 err = get_path_name(f, parent, name, &path);
3001 if (!err) {
3002 struct fuse_intr_data d;
3003
3004 fuse_prepare_interrupt(f, req, &d);
3005 err = fuse_fs_symlink(f->fs, linkname, path);
3006 if (!err)
3007 err = lookup_path(f, parent, name, path, &e, NULL);
3008 fuse_finish_interrupt(f, req, &d);
3009 free_path(f, parent, path);
3010 }
3011 reply_entry(req, &e, err);
3012 }
3013
3014 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
3015 const char *oldname, fuse_ino_t newdir,
3016 const char *newname, unsigned int flags)
3017 {
3018 struct fuse *f = req_fuse_prepare(req);
3019 char *oldpath;
3020 char *newpath;
3021 struct node *wnode1;
3022 struct node *wnode2;
3023 int err;
3024
3025 err = get_path2(f, olddir, oldname, newdir, newname,
3026 &oldpath, &newpath, &wnode1, &wnode2);
3027 if (!err) {
3028 struct fuse_intr_data d;
3029 err = 0;
3030 fuse_prepare_interrupt(f, req, &d);
3031 if (!f->conf.hard_remove && !(flags & RENAME_EXCHANGE) &&
3032 is_open(f, newdir, newname))
3033 err = hide_node(f, newpath, newdir, newname);
3034 if (!err) {
3035 err = fuse_fs_rename(f->fs, oldpath, newpath, flags);
3036 if (!err) {
3037 if (flags & RENAME_EXCHANGE) {
3038 err = exchange_node(f, olddir, oldname,
3039 newdir, newname);
3040 } else {
3041 err = rename_node(f, olddir, oldname,
3042 newdir, newname, 0);
3043 }
3044 }
3045 }
3046 fuse_finish_interrupt(f, req, &d);
3047 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
3048 }
3049 reply_err(req, err);
3050 }
3051
3052 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
3053 const char *newname)
3054 {
3055 struct fuse *f = req_fuse_prepare(req);
3056 struct fuse_entry_param e;
3057 char *oldpath;
3058 char *newpath;
3059 int err;
3060
3061 err = get_path2(f, ino, NULL, newparent, newname,
3062 &oldpath, &newpath, NULL, NULL);
3063 if (!err) {
3064 struct fuse_intr_data d;
3065
3066 fuse_prepare_interrupt(f, req, &d);
3067 err = fuse_fs_link(f->fs, oldpath, newpath);
3068 if (!err)
3069 err = lookup_path(f, newparent, newname, newpath,
3070 &e, NULL);
3071 fuse_finish_interrupt(f, req, &d);
3072 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3073 }
3074 reply_entry(req, &e, err);
3075 }
3076
3077 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
3078 struct fuse_file_info *fi)
3079 {
3080 struct node *node;
3081 int unlink_hidden = 0;
3082
3083 fuse_fs_release(f->fs, path, fi);
3084
3085 pthread_mutex_lock(&f->lock);
3086 node = get_node(f, ino);
3087 assert(node->open_count > 0);
3088 --node->open_count;
3089 if (node->is_hidden && !node->open_count) {
3090 unlink_hidden = 1;
3091 node->is_hidden = 0;
3092 }
3093 pthread_mutex_unlock(&f->lock);
3094
3095 if(unlink_hidden) {
3096 if (path) {
3097 fuse_fs_unlink(f->fs, path);
3098 } else if (f->conf.nullpath_ok) {
3099 char *unlinkpath;
3100
3101 if (get_path(f, ino, &unlinkpath) == 0)
3102 fuse_fs_unlink(f->fs, unlinkpath);
3103
3104 free_path(f, ino, unlinkpath);
3105 }
3106 }
3107 }
3108
3109 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
3110 const char *name, mode_t mode,
3111 struct fuse_file_info *fi)
3112 {
3113 struct fuse *f = req_fuse_prepare(req);
3114 struct fuse_intr_data d;
3115 struct fuse_entry_param e;
3116 char *path;
3117 int err;
3118
3119 err = get_path_name(f, parent, name, &path);
3120 if (!err) {
3121 fuse_prepare_interrupt(f, req, &d);
3122 err = fuse_fs_create(f->fs, path, mode, fi);
3123 if (!err) {
3124 err = lookup_path(f, parent, name, path, &e, fi);
3125 if (err)
3126 fuse_fs_release(f->fs, path, fi);
3127 else if (!S_ISREG(e.attr.st_mode)) {
3128 err = -EIO;
3129 fuse_fs_release(f->fs, path, fi);
3130 forget_node(f, e.ino, 1);
3131 } else {
3132 if (f->conf.direct_io)
3133 fi->direct_io = 1;
3134 if (f->conf.kernel_cache)
3135 fi->keep_cache = 1;
3136
3137 }
3138 }
3139 fuse_finish_interrupt(f, req, &d);
3140 }
3141 if (!err) {
3142 pthread_mutex_lock(&f->lock);
3143 get_node(f, e.ino)->open_count++;
3144 pthread_mutex_unlock(&f->lock);
3145 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
3146 /* The open syscall was interrupted, so it
3147 must be cancelled */
3148 fuse_do_release(f, e.ino, path, fi);
3149 forget_node(f, e.ino, 1);
3150 }
3151 } else {
3152 reply_err(req, err);
3153 }
3154
3155 free_path(f, parent, path);
3156 }
3157
3158 static double diff_timespec(const struct timespec *t1,
3159 const struct timespec *t2)
3160 {
3161 return (t1->tv_sec - t2->tv_sec) +
3162 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
3163 }
3164
3165 static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
3166 struct fuse_file_info *fi)
3167 {
3168 struct node *node;
3169
3170 pthread_mutex_lock(&f->lock);
3171 node = get_node(f, ino);
3172 if (node->cache_valid) {
3173 struct timespec now;
3174
3175 curr_time(&now);
3176 if (diff_timespec(&now, &node->stat_updated) >
3177 f->conf.ac_attr_timeout) {
3178 struct stat stbuf;
3179 int err;
3180 pthread_mutex_unlock(&f->lock);
3181 err = fuse_fs_getattr(f->fs, path, &stbuf, fi);
3182 pthread_mutex_lock(&f->lock);
3183 if (!err)
3184 update_stat(node, &stbuf);
3185 else
3186 node->cache_valid = 0;
3187 }
3188 }
3189 if (node->cache_valid)
3190 fi->keep_cache = 1;
3191
3192 node->cache_valid = 1;
3193 pthread_mutex_unlock(&f->lock);
3194 }
3195
3196 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
3197 struct fuse_file_info *fi)
3198 {
3199 struct fuse *f = req_fuse_prepare(req);
3200 struct fuse_intr_data d;
3201 char *path;
3202 int err;
3203
3204 err = get_path(f, ino, &path);
3205 if (!err) {
3206 fuse_prepare_interrupt(f, req, &d);
3207 err = fuse_fs_open(f->fs, path, fi);
3208 if (!err) {
3209 if (f->conf.direct_io)
3210 fi->direct_io = 1;
3211 if (f->conf.kernel_cache)
3212 fi->keep_cache = 1;
3213
3214 if (f->conf.auto_cache)
3215 open_auto_cache(f, ino, path, fi);
3216 }
3217 fuse_finish_interrupt(f, req, &d);
3218 }
3219 if (!err) {
3220 pthread_mutex_lock(&f->lock);
3221 get_node(f, ino)->open_count++;
3222 pthread_mutex_unlock(&f->lock);
3223 if (fuse_reply_open(req, fi) == -ENOENT) {
3224 /* The open syscall was interrupted, so it
3225 must be cancelled */
3226 fuse_do_release(f, ino, path, fi);
3227 }
3228 } else
3229 reply_err(req, err);
3230
3231 free_path(f, ino, path);
3232 }
3233
3234 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
3235 off_t off, struct fuse_file_info *fi)
3236 {
3237 struct fuse *f = req_fuse_prepare(req);
3238 struct fuse_bufvec *buf = NULL;
3239 char *path;
3240 int res;
3241
3242 res = get_path_nullok(f, ino, &path);
3243 if (res == 0) {
3244 struct fuse_intr_data d;
3245
3246 fuse_prepare_interrupt(f, req, &d);
3247 res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3248 fuse_finish_interrupt(f, req, &d);
3249 free_path(f, ino, path);
3250 }
3251
3252 if (res == 0)
3253 fuse_reply_data(req, buf, FUSE_BUF_SPLICE_MOVE);
3254 else
3255 reply_err(req, res);
3256
3257 fuse_free_buf(buf);
3258 }
3259
3260 static void fuse_lib_write_buf(fuse_req_t req, fuse_ino_t ino,
3261 struct fuse_bufvec *buf, off_t off,
3262 struct fuse_file_info *fi)
3263 {
3264 struct fuse *f = req_fuse_prepare(req);
3265 char *path;
3266 int res;
3267
3268 res = get_path_nullok(f, ino, &path);
3269 if (res == 0) {
3270 struct fuse_intr_data d;
3271
3272 fuse_prepare_interrupt(f, req, &d);
3273 res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3274 fuse_finish_interrupt(f, req, &d);
3275 free_path(f, ino, path);
3276 }
3277
3278 if (res >= 0)
3279 fuse_reply_write(req, res);
3280 else
3281 reply_err(req, res);
3282 }
3283
3284 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
3285 struct fuse_file_info *fi)
3286 {
3287 struct fuse *f = req_fuse_prepare(req);
3288 char *path;
3289 int err;
3290
3291 err = get_path_nullok(f, ino, &path);
3292 if (!err) {
3293 struct fuse_intr_data d;
3294
3295 fuse_prepare_interrupt(f, req, &d);
3296 err = fuse_fs_fsync(f->fs, path, datasync, fi);
3297 fuse_finish_interrupt(f, req, &d);
3298 free_path(f, ino, path);
3299 }
3300 reply_err(req, err);
3301 }
3302
3303 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
3304 struct fuse_file_info *fi)
3305 {
3306 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
3307 memset(fi, 0, sizeof(struct fuse_file_info));
3308 fi->fh = dh->fh;
3309 return dh;
3310 }
3311
3312 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
3313 struct fuse_file_info *llfi)
3314 {
3315 struct fuse *f = req_fuse_prepare(req);
3316 struct fuse_intr_data d;
3317 struct fuse_dh *dh;
3318 struct fuse_file_info fi;
3319 char *path;
3320 int err;
3321
3322 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
3323 if (dh == NULL) {
3324 reply_err(req, -ENOMEM);
3325 return;
3326 }
3327 memset(dh, 0, sizeof(struct fuse_dh));
3328 dh->fuse = f;
3329 dh->contents = NULL;
3330 dh->first = NULL;
3331 dh->len = 0;
3332 dh->filled = 0;
3333 dh->nodeid = ino;
3334 fuse_mutex_init(&dh->lock);
3335
3336 llfi->fh = (uintptr_t) dh;
3337
3338 memset(&fi, 0, sizeof(fi));
3339 fi.flags = llfi->flags;
3340
3341 err = get_path(f, ino, &path);
3342 if (!err) {
3343 fuse_prepare_interrupt(f, req, &d);
3344 err = fuse_fs_opendir(f->fs, path, &fi);
3345 fuse_finish_interrupt(f, req, &d);
3346 dh->fh = fi.fh;
3347 }
3348 if (!err) {
3349 if (fuse_reply_open(req, llfi) == -ENOENT) {
3350 /* The opendir syscall was interrupted, so it
3351 must be cancelled */
3352 fuse_fs_releasedir(f->fs, path, &fi);
3353 pthread_mutex_destroy(&dh->lock);
3354 free(dh);
3355 }
3356 } else {
3357 reply_err(req, err);
3358 pthread_mutex_destroy(&dh->lock);
3359 free(dh);
3360 }
3361 free_path(f, ino, path);
3362 }
3363
3364 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
3365 {
3366 if (minsize > dh->size) {
3367 char *newptr;
3368 unsigned newsize = dh->size;
3369 if (!newsize)
3370 newsize = 1024;
3371 while (newsize < minsize) {
3372 if (newsize >= 0x80000000)
3373 newsize = 0xffffffff;
3374 else
3375 newsize *= 2;
3376 }
3377
3378 newptr = (char *) realloc(dh->contents, newsize);
3379 if (!newptr) {
3380 dh->error = -ENOMEM;
3381 return -1;
3382 }
3383 dh->contents = newptr;
3384 dh->size = newsize;
3385 }
3386 return 0;
3387 }
3388
3389 static int fuse_add_direntry_to_dh(struct fuse_dh *dh, const char *name,
3390 struct stat *st)
3391 {
3392 struct fuse_direntry *de;
3393
3394 de = malloc(sizeof(struct fuse_direntry));
3395 if (!de) {
3396 dh->error = -ENOMEM;
3397 return -1;
3398 }
3399 de->name = strdup(name);
3400 if (!de->name) {
3401 dh->error = -ENOMEM;
3402 free(de);
3403 return -1;
3404 }
3405 de->stat = *st;
3406 de->next = NULL;
3407
3408 *dh->last = de;
3409 dh->last = &de->next;
3410
3411 return 0;
3412 }
3413
3414 static fuse_ino_t lookup_nodeid(struct fuse *f, fuse_ino_t parent,
3415 const char *name)
3416 {
3417 struct node *node;
3418 fuse_ino_t res = FUSE_UNKNOWN_INO;
3419
3420 pthread_mutex_lock(&f->lock);
3421 node = lookup_node(f, parent, name);
3422 if (node)
3423 res = node->nodeid;
3424 pthread_mutex_unlock(&f->lock);
3425
3426 return res;
3427 }
3428
3429 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
3430 off_t off, enum fuse_fill_dir_flags flags)
3431 {
3432 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3433 struct stat stbuf;
3434
3435 if ((flags & ~FUSE_FILL_DIR_PLUS) != 0) {
3436 dh->error = -EIO;
3437 return 1;
3438 }
3439
3440 if (statp)
3441 stbuf = *statp;
3442 else {
3443 memset(&stbuf, 0, sizeof(stbuf));
3444 stbuf.st_ino = FUSE_UNKNOWN_INO;
3445 }
3446
3447 if (!dh->fuse->conf.use_ino) {
3448 stbuf.st_ino = FUSE_UNKNOWN_INO;
3449 if (dh->fuse->conf.readdir_ino) {
3450 stbuf.st_ino = (ino_t)
3451 lookup_nodeid(dh->fuse, dh->nodeid, name);
3452 }
3453 }
3454
3455 if (off) {
3456 size_t newlen;
3457
3458 if (dh->first) {
3459 dh->error = -EIO;
3460 return 1;
3461 }
3462
3463 if (extend_contents(dh, dh->needlen) == -1)
3464 return 1;
3465
3466 dh->filled = 0;
3467 newlen = dh->len +
3468 fuse_add_direntry(dh->req, dh->contents + dh->len,
3469 dh->needlen - dh->len, name,
3470 &stbuf, off);
3471 if (newlen > dh->needlen)
3472 return 1;
3473
3474 dh->len = newlen;
3475 } else {
3476 if (!dh->filled) {
3477 dh->error = -EIO;
3478 return 1;
3479 }
3480 if (fuse_add_direntry_to_dh(dh, name, &stbuf) == -1)
3481 return 1;
3482 }
3483 return 0;
3484 }
3485
3486 static int is_dot_or_dotdot(const char *name)
3487 {
3488 return name[0] == '.' && (name[1] == '\0' ||
3489 (name[1] == '.' && name[2] == '\0'));
3490 }
3491
3492 static int fill_dir_plus(void *dh_, const char *name, const struct stat *statp,
3493 off_t off, enum fuse_fill_dir_flags flags)
3494 {
3495 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3496 struct fuse_entry_param e = {
3497 /* ino=0 tells the kernel to ignore readdirplus stat info */
3498 .ino = 0,
3499 };
3500 struct fuse *f = dh->fuse;
3501 int res;
3502
3503 if ((flags & ~FUSE_FILL_DIR_PLUS) != 0) {
3504 dh->error = -EIO;
3505 return 1;
3506 }
3507
3508 if (off && statp && (flags & FUSE_FILL_DIR_PLUS)) {
3509 e.attr = *statp;
3510
3511 if (!is_dot_or_dotdot(name)) {
3512 res = do_lookup(f, dh->nodeid, name, &e);
3513 if (res) {
3514 dh->error = res;
3515 return 1;
3516 }
3517 }
3518 } else {
3519 e.attr.st_ino = FUSE_UNKNOWN_INO;
3520 if (!f->conf.use_ino && f->conf.readdir_ino) {
3521 e.attr.st_ino = (ino_t)
3522 lookup_nodeid(f, dh->nodeid, name);
3523 }
3524 }
3525
3526 if (off) {
3527 size_t newlen;
3528
3529 if (dh->first) {
3530 dh->error = -EIO;
3531 return 1;
3532 }
3533 if (extend_contents(dh, dh->needlen) == -1)
3534 return 1;
3535
3536 dh->filled = 0;
3537 newlen = dh->len +
3538 fuse_add_direntry_plus(dh->req, dh->contents + dh->len,
3539 dh->needlen - dh->len, name,
3540 &e, off);
3541 if (newlen > dh->needlen)
3542 return 1;
3543 dh->len = newlen;
3544 } else {
3545 if (!dh->filled) {
3546 dh->error = -EIO;
3547 return 1;
3548 }
3549 if (fuse_add_direntry_to_dh(dh, name, &e.attr) == -1)
3550 return 1;
3551 }
3552
3553 return 0;
3554 }
3555
3556 static void free_direntries(struct fuse_direntry *de)
3557 {
3558 while (de) {
3559 struct fuse_direntry *next = de->next;
3560 free(de->name);
3561 free(de);
3562 de = next;
3563 }
3564 }
3565
3566 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3567 size_t size, off_t off, struct fuse_dh *dh,
3568 struct fuse_file_info *fi,
3569 enum fuse_readdir_flags flags)
3570 {
3571 char *path;
3572 int err;
3573
3574 if (f->fs->op.readdir)
3575 err = get_path_nullok(f, ino, &path);
3576 else
3577 err = get_path(f, ino, &path);
3578 if (!err) {
3579 struct fuse_intr_data d;
3580 fuse_fill_dir_t filler = fill_dir;
3581
3582 if (flags & FUSE_READDIR_PLUS)
3583 filler = fill_dir_plus;
3584
3585 free_direntries(dh->first);
3586 dh->first = NULL;
3587 dh->last = &dh->first;
3588 dh->len = 0;
3589 dh->error = 0;
3590 dh->needlen = size;
3591 dh->filled = 1;
3592 dh->req = req;
3593 fuse_prepare_interrupt(f, req, &d);
3594 err = fuse_fs_readdir(f->fs, path, dh, filler, off, fi, flags);
3595 fuse_finish_interrupt(f, req, &d);
3596 dh->req = NULL;
3597 if (!err)
3598 err = dh->error;
3599 if (err)
3600 dh->filled = 0;
3601 free_path(f, ino, path);
3602 }
3603 return err;
3604 }
3605
3606 static int readdir_fill_from_list(fuse_req_t req, struct fuse_dh *dh,
3607 off_t off, enum fuse_readdir_flags flags)
3608 {
3609 off_t pos;
3610 struct fuse_direntry *de = dh->first;
3611
3612 dh->len = 0;
3613
3614 if (extend_contents(dh, dh->needlen) == -1)
3615 return dh->error;
3616
3617 for (pos = 0; pos < off; pos++) {
3618 if (!de)
3619 break;
3620
3621 de = de->next;
3622 }
3623 while (de) {
3624 char *p = dh->contents + dh->len;
3625 unsigned rem = dh->needlen - dh->len;
3626 unsigned thislen;
3627 unsigned newlen;
3628 pos++;
3629
3630 if (flags & FUSE_READDIR_PLUS) {
3631 struct fuse_entry_param e = {
3632 .ino = 0,
3633 .attr = de->stat,
3634 };
3635 thislen = fuse_add_direntry_plus(req, p, rem,
3636 de->name, &e, pos);
3637 } else {
3638 thislen = fuse_add_direntry(req, p, rem,
3639 de->name, &de->stat, pos);
3640 }
3641 newlen = dh->len + thislen;
3642 if (newlen > dh->needlen)
3643 break;
3644 dh->len = newlen;
3645 de = de->next;
3646 }
3647 return 0;
3648 }
3649
3650 static void fuse_readdir_common(fuse_req_t req, fuse_ino_t ino, size_t size,
3651 off_t off, struct fuse_file_info *llfi,
3652 enum fuse_readdir_flags flags)
3653 {
3654 struct fuse *f = req_fuse_prepare(req);
3655 struct fuse_file_info fi;
3656 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3657 int err;
3658
3659 pthread_mutex_lock(&dh->lock);
3660 /* According to SUS, directory contents need to be refreshed on
3661 rewinddir() */
3662 if (!off)
3663 dh->filled = 0;
3664
3665 if (!dh->filled) {
3666 err = readdir_fill(f, req, ino, size, off, dh, &fi, flags);
3667 if (err) {
3668 reply_err(req, err);
3669 goto out;
3670 }
3671 }
3672 if (dh->filled) {
3673 dh->needlen = size;
3674 err = readdir_fill_from_list(req, dh, off, flags);
3675 if (err) {
3676 reply_err(req, err);
3677 goto out;
3678 }
3679 }
3680 fuse_reply_buf(req, dh->contents, dh->len);
3681 out:
3682 pthread_mutex_unlock(&dh->lock);
3683 }
3684
3685 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
3686 off_t off, struct fuse_file_info *llfi)
3687 {
3688 fuse_readdir_common(req, ino, size, off, llfi, 0);
3689 }
3690
3691 static void fuse_lib_readdirplus(fuse_req_t req, fuse_ino_t ino, size_t size,
3692 off_t off, struct fuse_file_info *llfi)
3693 {
3694 fuse_readdir_common(req, ino, size, off, llfi, FUSE_READDIR_PLUS);
3695 }
3696
3697 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
3698 struct fuse_file_info *llfi)
3699 {
3700 struct fuse *f = req_fuse_prepare(req);
3701 struct fuse_intr_data d;
3702 struct fuse_file_info fi;
3703 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3704 char *path;
3705
3706 get_path_nullok(f, ino, &path);
3707
3708 fuse_prepare_interrupt(f, req, &d);
3709 fuse_fs_releasedir(f->fs, path, &fi);
3710 fuse_finish_interrupt(f, req, &d);
3711 free_path(f, ino, path);
3712
3713 pthread_mutex_lock(&dh->lock);
3714 pthread_mutex_unlock(&dh->lock);
3715 pthread_mutex_destroy(&dh->lock);
3716 free_direntries(dh->first);
3717 free(dh->contents);
3718 free(dh);
3719 reply_err(req, 0);
3720 }
3721
3722 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
3723 struct fuse_file_info *llfi)
3724 {
3725 struct fuse *f = req_fuse_prepare(req);
3726 struct fuse_file_info fi;
3727 char *path;
3728 int err;
3729
3730 get_dirhandle(llfi, &fi);
3731
3732 err = get_path_nullok(f, ino, &path);
3733 if (!err) {
3734 struct fuse_intr_data d;
3735 fuse_prepare_interrupt(f, req, &d);
3736 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3737 fuse_finish_interrupt(f, req, &d);
3738 free_path(f, ino, path);
3739 }
3740 reply_err(req, err);
3741 }
3742
3743 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
3744 {
3745 struct fuse *f = req_fuse_prepare(req);
3746 struct statvfs buf;
3747 char *path = NULL;
3748 int err = 0;
3749
3750 memset(&buf, 0, sizeof(buf));
3751 if (ino)
3752 err = get_path(f, ino, &path);
3753
3754 if (!err) {
3755 struct fuse_intr_data d;
3756 fuse_prepare_interrupt(f, req, &d);
3757 err = fuse_fs_statfs(f->fs, path ? path : "/", &buf);
3758 fuse_finish_interrupt(f, req, &d);
3759 free_path(f, ino, path);
3760 }
3761
3762 if (!err)
3763 fuse_reply_statfs(req, &buf);
3764 else
3765 reply_err(req, err);
3766 }
3767
3768 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3769 const char *value, size_t size, int flags)
3770 {
3771 struct fuse *f = req_fuse_prepare(req);
3772 char *path;
3773 int err;
3774
3775 err = get_path(f, ino, &path);
3776 if (!err) {
3777 struct fuse_intr_data d;
3778 fuse_prepare_interrupt(f, req, &d);
3779 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3780 fuse_finish_interrupt(f, req, &d);
3781 free_path(f, ino, path);
3782 }
3783 reply_err(req, err);
3784 }
3785
3786 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3787 const char *name, char *value, size_t size)
3788 {
3789 int err;
3790 char *path;
3791
3792 err = get_path(f, ino, &path);
3793 if (!err) {
3794 struct fuse_intr_data d;
3795 fuse_prepare_interrupt(f, req, &d);
3796 err = fuse_fs_getxattr(f->fs, path, name, value, size);
3797 fuse_finish_interrupt(f, req, &d);
3798 free_path(f, ino, path);
3799 }
3800 return err;
3801 }
3802
3803 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3804 size_t size)
3805 {
3806 struct fuse *f = req_fuse_prepare(req);
3807 int res;
3808
3809 if (size) {
3810 char *value = (char *) malloc(size);
3811 if (value == NULL) {
3812 reply_err(req, -ENOMEM);
3813 return;
3814 }
3815 res = common_getxattr(f, req, ino, name, value, size);
3816 if (res > 0)
3817 fuse_reply_buf(req, value, res);
3818 else
3819 reply_err(req, res);
3820 free(value);
3821 } else {
3822 res = common_getxattr(f, req, ino, name, NULL, 0);
3823 if (res >= 0)
3824 fuse_reply_xattr(req, res);
3825 else
3826 reply_err(req, res);
3827 }
3828 }
3829
3830 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3831 char *list, size_t size)
3832 {
3833 char *path;
3834 int err;
3835
3836 err = get_path(f, ino, &path);
3837 if (!err) {
3838 struct fuse_intr_data d;
3839 fuse_prepare_interrupt(f, req, &d);
3840 err = fuse_fs_listxattr(f->fs, path, list, size);
3841 fuse_finish_interrupt(f, req, &d);
3842 free_path(f, ino, path);
3843 }
3844 return err;
3845 }
3846
3847 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
3848 {
3849 struct fuse *f = req_fuse_prepare(req);
3850 int res;
3851
3852 if (size) {
3853 char *list = (char *) malloc(size);
3854 if (list == NULL) {
3855 reply_err(req, -ENOMEM);
3856 return;
3857 }
3858 res = common_listxattr(f, req, ino, list, size);
3859 if (res > 0)
3860 fuse_reply_buf(req, list, res);
3861 else
3862 reply_err(req, res);
3863 free(list);
3864 } else {
3865 res = common_listxattr(f, req, ino, NULL, 0);
3866 if (res >= 0)
3867 fuse_reply_xattr(req, res);
3868 else
3869 reply_err(req, res);
3870 }
3871 }
3872
3873 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
3874 const char *name)
3875 {
3876 struct fuse *f = req_fuse_prepare(req);
3877 char *path;
3878 int err;
3879
3880 err = get_path(f, ino, &path);
3881 if (!err) {
3882 struct fuse_intr_data d;
3883 fuse_prepare_interrupt(f, req, &d);
3884 err = fuse_fs_removexattr(f->fs, path, name);
3885 fuse_finish_interrupt(f, req, &d);
3886 free_path(f, ino, path);
3887 }
3888 reply_err(req, err);
3889 }
3890
3891 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
3892 {
3893 struct lock *l;
3894
3895 for (l = node->locks; l; l = l->next)
3896 if (l->owner != lock->owner &&
3897 lock->start <= l->end && l->start <= lock->end &&
3898 (l->type == F_WRLCK || lock->type == F_WRLCK))
3899 break;
3900
3901 return l;
3902 }
3903
3904 static void delete_lock(struct lock **lockp)
3905 {
3906 struct lock *l = *lockp;
3907 *lockp = l->next;
3908 free(l);
3909 }
3910
3911 static void insert_lock(struct lock **pos, struct lock *lock)
3912 {
3913 lock->next = *pos;
3914 *pos = lock;
3915 }
3916
3917 static int locks_insert(struct node *node, struct lock *lock)
3918 {
3919 struct lock **lp;
3920 struct lock *newl1 = NULL;
3921 struct lock *newl2 = NULL;
3922
3923 if (lock->type != F_UNLCK || lock->start != 0 ||
3924 lock->end != OFFSET_MAX) {
3925 newl1 = malloc(sizeof(struct lock));
3926 newl2 = malloc(sizeof(struct lock));
3927
3928 if (!newl1 || !newl2) {
3929 free(newl1);
3930 free(newl2);
3931 return -ENOLCK;
3932 }
3933 }
3934
3935 for (lp = &node->locks; *lp;) {
3936 struct lock *l = *lp;
3937 if (l->owner != lock->owner)
3938 goto skip;
3939
3940 if (lock->type == l->type) {
3941 if (l->end < lock->start - 1)
3942 goto skip;
3943 if (lock->end < l->start - 1)
3944 break;
3945 if (l->start <= lock->start && lock->end <= l->end)
3946 goto out;
3947 if (l->start < lock->start)
3948 lock->start = l->start;
3949 if (lock->end < l->end)
3950 lock->end = l->end;
3951 goto delete;
3952 } else {
3953 if (l->end < lock->start)
3954 goto skip;
3955 if (lock->end < l->start)
3956 break;
3957 if (lock->start <= l->start && l->end <= lock->end)
3958 goto delete;
3959 if (l->end <= lock->end) {
3960 l->end = lock->start - 1;
3961 goto skip;
3962 }
3963 if (lock->start <= l->start) {
3964 l->start = lock->end + 1;
3965 break;
3966 }
3967 *newl2 = *l;
3968 newl2->start = lock->end + 1;
3969 l->end = lock->start - 1;
3970 insert_lock(&l->next, newl2);
3971 newl2 = NULL;
3972 }
3973 skip:
3974 lp = &l->next;
3975 continue;
3976
3977 delete:
3978 delete_lock(lp);
3979 }
3980 if (lock->type != F_UNLCK) {
3981 *newl1 = *lock;
3982 insert_lock(lp, newl1);
3983 newl1 = NULL;
3984 }
3985 out:
3986 free(newl1);
3987 free(newl2);
3988 return 0;
3989 }
3990
3991 static void flock_to_lock(struct flock *flock, struct lock *lock)
3992 {
3993 memset(lock, 0, sizeof(struct lock));
3994 lock->type = flock->l_type;
3995 lock->start = flock->l_start;
3996 lock->end =
3997 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
3998 lock->pid = flock->l_pid;
3999 }
4000
4001 static void lock_to_flock(struct lock *lock, struct flock *flock)
4002 {
4003 flock->l_type = lock->type;
4004 flock->l_start = lock->start;
4005 flock->l_len =
4006 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
4007 flock->l_pid = lock->pid;
4008 }
4009
4010 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
4011 const char *path, struct fuse_file_info *fi)
4012 {
4013 struct fuse_intr_data d;
4014 struct flock lock;
4015 struct lock l;
4016 int err;
4017 int errlock;
4018
4019 fuse_prepare_interrupt(f, req, &d);
4020 memset(&lock, 0, sizeof(lock));
4021 lock.l_type = F_UNLCK;
4022 lock.l_whence = SEEK_SET;
4023 err = fuse_fs_flush(f->fs, path, fi);
4024 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
4025 fuse_finish_interrupt(f, req, &d);
4026
4027 if (errlock != -ENOSYS) {
4028 flock_to_lock(&lock, &l);
4029 l.owner = fi->lock_owner;
4030 pthread_mutex_lock(&f->lock);
4031 locks_insert(get_node(f, ino), &l);
4032 pthread_mutex_unlock(&f->lock);
4033
4034 /* if op.lock() is defined FLUSH is needed regardless
4035 of op.flush() */
4036 if (err == -ENOSYS)
4037 err = 0;
4038 }
4039 return err;
4040 }
4041
4042 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
4043 struct fuse_file_info *fi)
4044 {
4045 struct fuse *f = req_fuse_prepare(req);
4046 struct fuse_intr_data d;
4047 char *path;
4048 int err = 0;
4049
4050 get_path_nullok(f, ino, &path);
4051 if (fi->flush) {
4052 err = fuse_flush_common(f, req, ino, path, fi);
4053 if (err == -ENOSYS)
4054 err = 0;
4055 }
4056
4057 fuse_prepare_interrupt(f, req, &d);
4058 fuse_do_release(f, ino, path, fi);
4059 fuse_finish_interrupt(f, req, &d);
4060 free_path(f, ino, path);
4061
4062 reply_err(req, err);
4063 }
4064
4065 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
4066 struct fuse_file_info *fi)
4067 {
4068 struct fuse *f = req_fuse_prepare(req);
4069 char *path;
4070 int err;
4071
4072 get_path_nullok(f, ino, &path);
4073 err = fuse_flush_common(f, req, ino, path, fi);
4074 free_path(f, ino, path);
4075
4076 reply_err(req, err);
4077 }
4078
4079 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
4080 struct fuse_file_info *fi, struct flock *lock,
4081 int cmd)
4082 {
4083 struct fuse *f = req_fuse_prepare(req);
4084 char *path;
4085 int err;
4086
4087 err = get_path_nullok(f, ino, &path);
4088 if (!err) {
4089 struct fuse_intr_data d;
4090 fuse_prepare_interrupt(f, req, &d);
4091 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
4092 fuse_finish_interrupt(f, req, &d);
4093 free_path(f, ino, path);
4094 }
4095 return err;
4096 }
4097
4098 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
4099 struct fuse_file_info *fi, struct flock *lock)
4100 {
4101 int err;
4102 struct lock l;
4103 struct lock *conflict;
4104 struct fuse *f = req_fuse(req);
4105
4106 flock_to_lock(lock, &l);
4107 l.owner = fi->lock_owner;
4108 pthread_mutex_lock(&f->lock);
4109 conflict = locks_conflict(get_node(f, ino), &l);
4110 if (conflict)
4111 lock_to_flock(conflict, lock);
4112 pthread_mutex_unlock(&f->lock);
4113 if (!conflict)
4114 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
4115 else
4116 err = 0;
4117
4118 if (!err)
4119 fuse_reply_lock(req, lock);
4120 else
4121 reply_err(req, err);
4122 }
4123
4124 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
4125 struct fuse_file_info *fi, struct flock *lock,
4126 int sleep)
4127 {
4128 int err = fuse_lock_common(req, ino, fi, lock,
4129 sleep ? F_SETLKW : F_SETLK);
4130 if (!err) {
4131 struct fuse *f = req_fuse(req);
4132 struct lock l;
4133 flock_to_lock(lock, &l);
4134 l.owner = fi->lock_owner;
4135 pthread_mutex_lock(&f->lock);
4136 locks_insert(get_node(f, ino), &l);
4137 pthread_mutex_unlock(&f->lock);
4138 }
4139 reply_err(req, err);
4140 }
4141
4142 static void fuse_lib_flock(fuse_req_t req, fuse_ino_t ino,
4143 struct fuse_file_info *fi, int op)
4144 {
4145 struct fuse *f = req_fuse_prepare(req);
4146 char *path;
4147 int err;
4148
4149 err = get_path_nullok(f, ino, &path);
4150 if (err == 0) {
4151 struct fuse_intr_data d;
4152 fuse_prepare_interrupt(f, req, &d);
4153 err = fuse_fs_flock(f->fs, path, fi, op);
4154 fuse_finish_interrupt(f, req, &d);
4155 free_path(f, ino, path);
4156 }
4157 reply_err(req, err);
4158 }
4159
4160 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
4161 uint64_t idx)
4162 {
4163 struct fuse *f = req_fuse_prepare(req);
4164 struct fuse_intr_data d;
4165 char *path;
4166 int err;
4167
4168 err = get_path(f, ino, &path);
4169 if (!err) {
4170 fuse_prepare_interrupt(f, req, &d);
4171 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
4172 fuse_finish_interrupt(f, req, &d);
4173 free_path(f, ino, path);
4174 }
4175 if (!err)
4176 fuse_reply_bmap(req, idx);
4177 else
4178 reply_err(req, err);
4179 }
4180
4181 static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
4182 struct fuse_file_info *llfi, unsigned int flags,
4183 const void *in_buf, size_t in_bufsz,
4184 size_t out_bufsz)
4185 {
4186 struct fuse *f = req_fuse_prepare(req);
4187 struct fuse_intr_data d;
4188 struct fuse_file_info fi;
4189 char *path, *out_buf = NULL;
4190 int err;
4191
4192 err = -EPERM;
4193 if (flags & FUSE_IOCTL_UNRESTRICTED)
4194 goto err;
4195
4196 if (flags & FUSE_IOCTL_DIR)
4197 get_dirhandle(llfi, &fi);
4198 else
4199 fi = *llfi;
4200
4201 if (out_bufsz) {
4202 err = -ENOMEM;
4203 out_buf = malloc(out_bufsz);
4204 if (!out_buf)
4205 goto err;
4206 }
4207
4208 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
4209 if (out_buf && in_bufsz)
4210 memcpy(out_buf, in_buf, in_bufsz);
4211
4212 err = get_path_nullok(f, ino, &path);
4213 if (err)
4214 goto err;
4215
4216 fuse_prepare_interrupt(f, req, &d);
4217
4218 err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
4219 out_buf ?: (void *)in_buf);
4220
4221 fuse_finish_interrupt(f, req, &d);
4222 free_path(f, ino, path);
4223
4224 fuse_reply_ioctl(req, err, out_buf, out_bufsz);
4225 goto out;
4226 err:
4227 reply_err(req, err);
4228 out:
4229 free(out_buf);
4230 }
4231
4232 static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
4233 struct fuse_file_info *fi, struct fuse_pollhandle *ph)
4234 {
4235 struct fuse *f = req_fuse_prepare(req);
4236 struct fuse_intr_data d;
4237 char *path;
4238 int err;
4239 unsigned revents = 0;
4240
4241 err = get_path_nullok(f, ino, &path);
4242 if (!err) {
4243 fuse_prepare_interrupt(f, req, &d);
4244 err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4245 fuse_finish_interrupt(f, req, &d);
4246 free_path(f, ino, path);
4247 }
4248 if (!err)
4249 fuse_reply_poll(req, revents);
4250 else
4251 reply_err(req, err);
4252 }
4253
4254 static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode,
4255 off_t offset, off_t length, struct fuse_file_info *fi)
4256 {
4257 struct fuse *f = req_fuse_prepare(req);
4258 struct fuse_intr_data d;
4259 char *path;
4260 int err;
4261
4262 err = get_path_nullok(f, ino, &path);
4263 if (!err) {
4264 fuse_prepare_interrupt(f, req, &d);
4265 err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4266 fuse_finish_interrupt(f, req, &d);
4267 free_path(f, ino, path);
4268 }
4269 reply_err(req, err);
4270 }
4271
4272 static int clean_delay(struct fuse *f)
4273 {
4274 /*
4275 * This is calculating the delay between clean runs. To
4276 * reduce the number of cleans we are doing them 10 times
4277 * within the remember window.
4278 */
4279 int min_sleep = 60;
4280 int max_sleep = 3600;
4281 int sleep_time = f->conf.remember / 10;
4282
4283 if (sleep_time > max_sleep)
4284 return max_sleep;
4285 if (sleep_time < min_sleep)
4286 return min_sleep;
4287 return sleep_time;
4288 }
4289
4290 int fuse_clean_cache(struct fuse *f)
4291 {
4292 struct node_lru *lnode;
4293 struct list_head *curr, *next;
4294 struct node *node;
4295 struct timespec now;
4296
4297 pthread_mutex_lock(&f->lock);
4298
4299 curr_time(&now);
4300
4301 for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4302 double age;
4303
4304 next = curr->next;
4305 lnode = list_entry(curr, struct node_lru, lru);
4306 node = &lnode->node;
4307
4308 age = diff_timespec(&now, &lnode->forget_time);
4309 if (age <= f->conf.remember)
4310 break;
4311
4312 assert(node->nlookup == 1);
4313
4314 /* Don't forget active directories */
4315 if (node->refctr > 1)
4316 continue;
4317
4318 node->nlookup = 0;
4319 unhash_name(f, node);
4320 unref_node(f, node);
4321 }
4322 pthread_mutex_unlock(&f->lock);
4323
4324 return clean_delay(f);
4325 }
4326
4327 static struct fuse_lowlevel_ops fuse_path_ops = {
4328 .init = fuse_lib_init,
4329 .destroy = fuse_lib_destroy,
4330 .lookup = fuse_lib_lookup,
4331 .forget = fuse_lib_forget,
4332 .forget_multi = fuse_lib_forget_multi,
4333 .getattr = fuse_lib_getattr,
4334 .setattr = fuse_lib_setattr,
4335 .access = fuse_lib_access,
4336 .readlink = fuse_lib_readlink,
4337 .mknod = fuse_lib_mknod,
4338 .mkdir = fuse_lib_mkdir,
4339 .unlink = fuse_lib_unlink,
4340 .rmdir = fuse_lib_rmdir,
4341 .symlink = fuse_lib_symlink,
4342 .rename = fuse_lib_rename,
4343 .link = fuse_lib_link,
4344 .create = fuse_lib_create,
4345 .open = fuse_lib_open,
4346 .read = fuse_lib_read,
4347 .write_buf = fuse_lib_write_buf,
4348 .flush = fuse_lib_flush,
4349 .release = fuse_lib_release,
4350 .fsync = fuse_lib_fsync,
4351 .opendir = fuse_lib_opendir,
4352 .readdir = fuse_lib_readdir,
4353 .readdirplus = fuse_lib_readdirplus,
4354 .releasedir = fuse_lib_releasedir,
4355 .fsyncdir = fuse_lib_fsyncdir,
4356 .statfs = fuse_lib_statfs,
4357 .setxattr = fuse_lib_setxattr,
4358 .getxattr = fuse_lib_getxattr,
4359 .listxattr = fuse_lib_listxattr,
4360 .removexattr = fuse_lib_removexattr,
4361 .getlk = fuse_lib_getlk,
4362 .setlk = fuse_lib_setlk,
4363 .flock = fuse_lib_flock,
4364 .bmap = fuse_lib_bmap,
4365 .ioctl = fuse_lib_ioctl,
4366 .poll = fuse_lib_poll,
4367 .fallocate = fuse_lib_fallocate,
4368 };
4369
4370 int fuse_notify_poll(struct fuse_pollhandle *ph)
4371 {
4372 return fuse_lowlevel_notify_poll(ph);
4373 }
4374
4375 struct fuse_session *fuse_get_session(struct fuse *f)
4376 {
4377 return f->se;
4378 }
4379
4380 static int fuse_session_loop_remember(struct fuse *f)
4381 {
4382 struct fuse_session *se = f->se;
4383 int res = 0;
4384 struct timespec now;
4385 time_t next_clean;
4386 struct pollfd fds = {
4387 .fd = se->fd,
4388 .events = POLLIN
4389 };
4390 struct fuse_buf fbuf = {
4391 .mem = NULL,
4392 };
4393
4394 curr_time(&now);
4395 next_clean = now.tv_sec;
4396 while (!fuse_session_exited(se)) {
4397 unsigned timeout;
4398
4399 curr_time(&now);
4400 if (now.tv_sec < next_clean)
4401 timeout = next_clean - now.tv_sec;
4402 else
4403 timeout = 0;
4404
4405 res = poll(&fds, 1, timeout * 1000);
4406 if (res == -1) {
4407 if (errno == -EINTR)
4408 continue;
4409 else
4410 break;
4411 } else if (res > 0) {
4412 res = fuse_session_receive_buf_int(se, &fbuf, NULL);
4413
4414 if (res == -EINTR)
4415 continue;
4416 if (res <= 0)
4417 break;
4418
4419 fuse_session_process_buf_int(se, &fbuf, NULL);
4420 } else {
4421 timeout = fuse_clean_cache(f);
4422 curr_time(&now);
4423 next_clean = now.tv_sec + timeout;
4424 }
4425 }
4426
4427 free(fbuf.mem);
4428 fuse_session_reset(se);
4429 return res < 0 ? -1 : 0;
4430 }
4431
4432 int fuse_loop(struct fuse *f)
4433 {
4434 if (!f)
4435 return -1;
4436
4437 if (lru_enabled(f))
4438 return fuse_session_loop_remember(f);
4439
4440 return fuse_session_loop(f->se);
4441 }
4442
4443 FUSE_SYMVER(".symver fuse_loop_mt_32,fuse_loop_mt@@FUSE_3.2");
4444 int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config)
4445 {
4446 if (f == NULL)
4447 return -1;
4448
4449 int res = fuse_start_cleanup_thread(f);
4450 if (res)
4451 return -1;
4452
4453 res = fuse_session_loop_mt_32(fuse_get_session(f), config);
4454 fuse_stop_cleanup_thread(f);
4455 return res;
4456 }
4457
4458 int fuse_loop_mt_31(struct fuse *f, int clone_fd);
4459 FUSE_SYMVER(".symver fuse_loop_mt_31,fuse_loop_mt@FUSE_3.0");
4460 int fuse_loop_mt_31(struct fuse *f, int clone_fd)
4461 {
4462 struct fuse_loop_config config;
4463 config.clone_fd = clone_fd;
4464 config.max_idle_threads = 10;
4465 return fuse_loop_mt_32(f, &config);
4466 }
4467
4468 void fuse_exit(struct fuse *f)
4469 {
4470 fuse_session_exit(f->se);
4471 }
4472
4473 struct fuse_context *fuse_get_context(void)
4474 {
4475 struct fuse_context_i *c = fuse_get_context_internal();
4476
4477 if (c)
4478 return &c->ctx;
4479 else
4480 return NULL;
4481 }
4482
4483 int fuse_getgroups(int size, gid_t list[])
4484 {
4485 struct fuse_context_i *c = fuse_get_context_internal();
4486 if (!c)
4487 return -EINVAL;
4488
4489 return fuse_req_getgroups(c->req, size, list);
4490 }
4491
4492 int fuse_interrupted(void)
4493 {
4494 struct fuse_context_i *c = fuse_get_context_internal();
4495
4496 if (c)
4497 return fuse_req_interrupted(c->req);
4498 else
4499 return 0;
4500 }
4501
4502 int fuse_invalidate_path(struct fuse *f, const char *path) {
4503 fuse_ino_t ino;
4504 int err = lookup_path_in_cache(f, path, &ino);
4505 if (err) {
4506 return err;
4507 }
4508
4509 return fuse_lowlevel_notify_inval_inode(f->se, ino, 0, 0);
4510 }
4511
4512 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4513
4514 static const struct fuse_opt fuse_lib_opts[] = {
4515 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
4516 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
4517 FUSE_LIB_OPT("debug", debug, 1),
4518 FUSE_LIB_OPT("-d", debug, 1),
4519 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
4520 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
4521 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
4522 FUSE_LIB_OPT("umask=", set_mode, 1),
4523 FUSE_LIB_OPT("umask=%o", umask, 0),
4524 FUSE_LIB_OPT("uid=", set_uid, 1),
4525 FUSE_LIB_OPT("uid=%d", uid, 0),
4526 FUSE_LIB_OPT("gid=", set_gid, 1),
4527 FUSE_LIB_OPT("gid=%d", gid, 0),
4528 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
4529 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
4530 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
4531 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
4532 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
4533 FUSE_LIB_OPT("noforget", remember, -1),
4534 FUSE_LIB_OPT("remember=%u", remember, 0),
4535 FUSE_LIB_OPT("modules=%s", modules, 0),
4536 FUSE_OPT_END
4537 };
4538
4539 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
4540 struct fuse_args *outargs)
4541 {
4542 (void) arg; (void) outargs; (void) data; (void) key;
4543
4544 /* Pass through unknown options */
4545 return 1;
4546 }
4547
4548
4549 static const struct fuse_opt fuse_help_opts[] = {
4550 FUSE_LIB_OPT("modules=%s", modules, 1),
4551 FUSE_OPT_KEY("modules=%s", FUSE_OPT_KEY_KEEP),
4552 FUSE_OPT_END
4553 };
4554
4555 static void print_module_help(const char *name,
4556 fuse_module_factory_t *fac)
4557 {
4558 struct fuse_args a = FUSE_ARGS_INIT(0, NULL);
4559 if (fuse_opt_add_arg(&a, "") == -1 ||
4560 fuse_opt_add_arg(&a, "-h") == -1)
4561 return;
4562 printf("\nOptions for %s module:\n", name);
4563 (*fac)(&a, NULL);
4564 }
4565
4566 void fuse_lib_help(struct fuse_args *args)
4567 {
4568 /* These are not all options, but only the ones that
4569 may be of interest to an end-user */
4570 printf(
4571 " -o kernel_cache cache files in kernel\n"
4572 " -o [no]auto_cache enable caching based on modification times (off)\n"
4573 " -o umask=M set file permissions (octal)\n"
4574 " -o uid=N set file owner\n"
4575 " -o gid=N set file group\n"
4576 " -o entry_timeout=T cache timeout for names (1.0s)\n"
4577 " -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
4578 " -o attr_timeout=T cache timeout for attributes (1.0s)\n"
4579 " -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
4580 " -o noforget never forget cached inodes\n"
4581 " -o remember=T remember cached inodes for T seconds (0s)\n"
4582 " -o modules=M1[:M2...] names of modules to push onto filesystem stack\n");
4583
4584
4585 /* Print low-level help */
4586 fuse_lowlevel_help();
4587
4588 /* Print help for builtin modules */
4589 print_module_help("subdir", &fuse_module_subdir_factory);
4590 #ifdef HAVE_ICONV
4591 print_module_help("iconv", &fuse_module_iconv_factory);
4592 #endif
4593
4594 /* Parse command line options in case we need to
4595 activate more modules */
4596 struct fuse_config conf = { .modules = NULL };
4597 if (fuse_opt_parse(args, &conf, fuse_help_opts,
4598 fuse_lib_opt_proc) == -1
4599 || !conf.modules)
4600 return;
4601
4602 char *module;
4603 char *next;
4604 struct fuse_module *m;
4605
4606 // Iterate over all modules
4607 for (module = conf.modules; module; module = next) {
4608 char *p;
4609 for (p = module; *p && *p != ':'; p++);
4610 next = *p ? p + 1 : NULL;
4611 *p = '\0';
4612
4613 m = fuse_get_module(module);
4614 if (m)
4615 print_module_help(module, &m->factory);
4616 }
4617 }
4618
4619
4620
4621 static int fuse_init_intr_signal(int signum, int *installed)
4622 {
4623 struct sigaction old_sa;
4624
4625 if (sigaction(signum, NULL, &old_sa) == -1) {
4626 perror("fuse: cannot get old signal handler");
4627 return -1;
4628 }
4629
4630 if (old_sa.sa_handler == SIG_DFL) {
4631 struct sigaction sa;
4632
4633 memset(&sa, 0, sizeof(struct sigaction));
4634 sa.sa_handler = fuse_intr_sighandler;
4635 sigemptyset(&sa.sa_mask);
4636
4637 if (sigaction(signum, &sa, NULL) == -1) {
4638 perror("fuse: cannot set interrupt signal handler");
4639 return -1;
4640 }
4641 *installed = 1;
4642 }
4643 return 0;
4644 }
4645
4646 static void fuse_restore_intr_signal(int signum)
4647 {
4648 struct sigaction sa;
4649
4650 memset(&sa, 0, sizeof(struct sigaction));
4651 sa.sa_handler = SIG_DFL;
4652 sigaction(signum, &sa, NULL);
4653 }
4654
4655
4656 static int fuse_push_module(struct fuse *f, const char *module,
4657 struct fuse_args *args)
4658 {
4659 struct fuse_fs *fs[2] = { f->fs, NULL };
4660 struct fuse_fs *newfs;
4661 struct fuse_module *m = fuse_get_module(module);
4662
4663 if (!m)
4664 return -1;
4665
4666 newfs = m->factory(args, fs);
4667 if (!newfs) {
4668 fuse_put_module(m);
4669 return -1;
4670 }
4671 newfs->m = m;
4672 f->fs = newfs;
4673 return 0;
4674 }
4675
4676 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
4677 void *user_data)
4678 {
4679 struct fuse_fs *fs;
4680
4681 if (sizeof(struct fuse_operations) < op_size) {
4682 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
4683 op_size = sizeof(struct fuse_operations);
4684 }
4685
4686 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
4687 if (!fs) {
4688 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
4689 return NULL;
4690 }
4691
4692 fs->user_data = user_data;
4693 if (op)
4694 memcpy(&fs->op, op, op_size);
4695 return fs;
4696 }
4697
4698 static int node_table_init(struct node_table *t)
4699 {
4700 t->size = NODE_TABLE_MIN_SIZE;
4701 t->array = (struct node **) calloc(1, sizeof(struct node *) * t->size);
4702 if (t->array == NULL) {
4703 fprintf(stderr, "fuse: memory allocation failed\n");
4704 return -1;
4705 }
4706 t->use = 0;
4707 t->split = 0;
4708
4709 return 0;
4710 }
4711
4712 static void *fuse_prune_nodes(void *fuse)
4713 {
4714 struct fuse *f = fuse;
4715 int sleep_time;
4716
4717 while(1) {
4718 sleep_time = fuse_clean_cache(f);
4719 sleep(sleep_time);
4720 }
4721 return NULL;
4722 }
4723
4724 int fuse_start_cleanup_thread(struct fuse *f)
4725 {
4726 if (lru_enabled(f))
4727 return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4728
4729 return 0;
4730 }
4731
4732 void fuse_stop_cleanup_thread(struct fuse *f)
4733 {
4734 if (lru_enabled(f)) {
4735 pthread_mutex_lock(&f->lock);
4736 pthread_cancel(f->prune_thread);
4737 pthread_mutex_unlock(&f->lock);
4738 pthread_join(f->prune_thread, NULL);
4739 }
4740 }
4741
4742
4743 FUSE_SYMVER(".symver fuse_new_31,fuse_new@@FUSE_3.1");
4744 struct fuse *fuse_new_31(struct fuse_args *args,
4745 const struct fuse_operations *op,
4746 size_t op_size, void *user_data)
4747 {
4748 struct fuse *f;
4749 struct node *root;
4750 struct fuse_fs *fs;
4751 struct fuse_lowlevel_ops llop = fuse_path_ops;
4752
4753 f = (struct fuse *) calloc(1, sizeof(struct fuse));
4754 if (f == NULL) {
4755 fprintf(stderr, "fuse: failed to allocate fuse object\n");
4756 goto out;
4757 }
4758
4759 f->conf.entry_timeout = 1.0;
4760 f->conf.attr_timeout = 1.0;
4761 f->conf.negative_timeout = 0.0;
4762 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
4763
4764 /* Parse options */
4765 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
4766 fuse_lib_opt_proc) == -1)
4767 goto out_free;
4768
4769 pthread_mutex_lock(&fuse_context_lock);
4770 static int builtin_modules_registered = 0;
4771 /* Have the builtin modules already been registered? */
4772 if (builtin_modules_registered == 0) {
4773 /* If not, register them. */
4774 fuse_register_module("subdir", fuse_module_subdir_factory, NULL);
4775 #ifdef HAVE_ICONV
4776 fuse_register_module("iconv", fuse_module_iconv_factory, NULL);
4777 #endif
4778 builtin_modules_registered= 1;
4779 }
4780 pthread_mutex_unlock(&fuse_context_lock);
4781
4782 if (fuse_create_context_key() == -1)
4783 goto out_free;
4784
4785 fs = fuse_fs_new(op, op_size, user_data);
4786 if (!fs)
4787 goto out_delete_context_key;
4788
4789 f->fs = fs;
4790
4791 /* Oh f**k, this is ugly! */
4792 if (!fs->op.lock) {
4793 llop.getlk = NULL;
4794 llop.setlk = NULL;
4795 }
4796
4797 f->pagesize = getpagesize();
4798 init_list_head(&f->partial_slabs);
4799 init_list_head(&f->full_slabs);
4800 init_list_head(&f->lru_table);
4801
4802 if (f->conf.modules) {
4803 char *module;
4804 char *next;
4805
4806 for (module = f->conf.modules; module; module = next) {
4807 char *p;
4808 for (p = module; *p && *p != ':'; p++);
4809 next = *p ? p + 1 : NULL;
4810 *p = '\0';
4811 if (module[0] &&
4812 fuse_push_module(f, module, args) == -1)
4813 goto out_free_fs;
4814 }
4815 }
4816
4817 if (!f->conf.ac_attr_timeout_set)
4818 f->conf.ac_attr_timeout = f->conf.attr_timeout;
4819
4820 #if defined(__FreeBSD__) || defined(__NetBSD__)
4821 /*
4822 * In FreeBSD, we always use these settings as inode numbers
4823 * are needed to make getcwd(3) work.
4824 */
4825 f->conf.readdir_ino = 1;
4826 #endif
4827
4828 f->se = fuse_session_new(args, &llop, sizeof(llop), f);
4829 if (f->se == NULL)
4830 goto out_free_fs;
4831
4832 if (f->conf.debug) {
4833 fprintf(stderr, "nullpath_ok: %i\n", f->conf.nullpath_ok);
4834 }
4835
4836 /* Trace topmost layer by default */
4837 f->fs->debug = f->conf.debug;
4838 f->ctr = 0;
4839 f->generation = 0;
4840 if (node_table_init(&f->name_table) == -1)
4841 goto out_free_session;
4842
4843 if (node_table_init(&f->id_table) == -1)
4844 goto out_free_name_table;
4845
4846 fuse_mutex_init(&f->lock);
4847
4848 root = alloc_node(f);
4849 if (root == NULL) {
4850 fprintf(stderr, "fuse: memory allocation failed\n");
4851 goto out_free_id_table;
4852 }
4853 if (lru_enabled(f)) {
4854 struct node_lru *lnode = node_lru(root);
4855 init_list_head(&lnode->lru);
4856 }
4857
4858 strcpy(root->inline_name, "/");
4859 root->name = root->inline_name;
4860
4861 if (f->conf.intr &&
4862 fuse_init_intr_signal(f->conf.intr_signal,
4863 &f->intr_installed) == -1)
4864 goto out_free_root;
4865
4866 root->parent = NULL;
4867 root->nodeid = FUSE_ROOT_ID;
4868 inc_nlookup(root);
4869 hash_id(f, root);
4870
4871 return f;
4872
4873 out_free_root:
4874 free(root);
4875 out_free_id_table:
4876 free(f->id_table.array);
4877 out_free_name_table:
4878 free(f->name_table.array);
4879 out_free_session:
4880 fuse_session_destroy(f->se);
4881 out_free_fs:
4882 if (f->fs->m)
4883 fuse_put_module(f->fs->m);
4884 free(f->fs);
4885 free(f->conf.modules);
4886 out_delete_context_key:
4887 fuse_delete_context_key();
4888 out_free:
4889 free(f);
4890 out:
4891 return NULL;
4892 }
4893
4894 /* Emulates 3.0-style fuse_new(), which processes --help */
4895 struct fuse *fuse_new_30(struct fuse_args *args, const struct fuse_operations *op,
4896 size_t op_size, void *private_data);
4897 FUSE_SYMVER(".symver fuse_new_30,fuse_new@FUSE_3.0");
4898 struct fuse *fuse_new_30(struct fuse_args *args,
4899 const struct fuse_operations *op,
4900 size_t op_size, void *user_data)
4901 {
4902 struct fuse_config conf;
4903
4904 memset(&conf, 0, sizeof(conf));
4905
4906 const struct fuse_opt opts[] = {
4907 FUSE_LIB_OPT("-h", show_help, 1),
4908 FUSE_LIB_OPT("--help", show_help, 1),
4909 FUSE_OPT_END
4910 };
4911
4912 if (fuse_opt_parse(args, &conf, opts,
4913 fuse_lib_opt_proc) == -1)
4914 return NULL;
4915
4916 if (conf.show_help) {
4917 fuse_lib_help(args);
4918 return NULL;
4919 } else
4920 return fuse_new_31(args, op, op_size, user_data);
4921 }
4922
4923 void fuse_destroy(struct fuse *f)
4924 {
4925 size_t i;
4926
4927 if (f->conf.intr && f->intr_installed)
4928 fuse_restore_intr_signal(f->conf.intr_signal);
4929
4930 if (f->fs) {
4931 fuse_create_context(f);
4932
4933 for (i = 0; i < f->id_table.size; i++) {
4934 struct node *node;
4935
4936 for (node = f->id_table.array[i]; node != NULL;
4937 node = node->id_next) {
4938 if (node->is_hidden) {
4939 char *path;
4940 if (try_get_path(f, node->nodeid, NULL, &path, NULL, false) == 0) {
4941 fuse_fs_unlink(f->fs, path);
4942 free(path);
4943 }
4944 }
4945 }
4946 }
4947 }
4948 for (i = 0; i < f->id_table.size; i++) {
4949 struct node *node;
4950 struct node *next;
4951
4952 for (node = f->id_table.array[i]; node != NULL; node = next) {
4953 next = node->id_next;
4954 free_node(f, node);
4955 f->id_table.use--;
4956 }
4957 }
4958 assert(list_empty(&f->partial_slabs));
4959 assert(list_empty(&f->full_slabs));
4960
4961 free(f->id_table.array);
4962 free(f->name_table.array);
4963 pthread_mutex_destroy(&f->lock);
4964 fuse_session_destroy(f->se);
4965 free(f->conf.modules);
4966 free(f);
4967 fuse_delete_context_key();
4968 }
4969
4970 int fuse_mount(struct fuse *f, const char *mountpoint) {
4971 return fuse_session_mount(fuse_get_session(f), mountpoint);
4972 }
4973
4974
4975 void fuse_unmount(struct fuse *f) {
4976 return fuse_session_unmount(fuse_get_session(f));
4977 }
4978
4979 int fuse_version(void)
4980 {
4981 return FUSE_VERSION;
4982 }
4983
4984 const char *fuse_pkgversion(void)
4985 {
4986 return PACKAGE_VERSION;
4987 }
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