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