libfuse: 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[0].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, int cmd, void *arg,
2308 struct fuse_file_info *fi, unsigned int flags, void *data)
2309 {
2310 fuse_get_context()->private_data = fs->user_data;
2311 if (fs->op.ioctl) {
2312 if (fs->debug)
2313 fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
2314 (unsigned long long) fi->fh, cmd, flags);
2315
2316 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2317 } else
2318 return -ENOSYS;
2319 }
2320
2321 int fuse_fs_poll(struct fuse_fs *fs, const char *path,
2322 struct fuse_file_info *fi, struct fuse_pollhandle *ph,
2323 unsigned *reventsp)
2324 {
2325 fuse_get_context()->private_data = fs->user_data;
2326 if (fs->op.poll) {
2327 int res;
2328
2329 if (fs->debug)
2330 fprintf(stderr, "poll[%llu] ph: %p, events 0x%x\n",
2331 (unsigned long long) fi->fh, ph,
2332 fi->poll_events);
2333
2334 res = fs->op.poll(path, fi, ph, reventsp);
2335
2336 if (fs->debug && !res)
2337 fprintf(stderr, " poll[%llu] revents: 0x%x\n",
2338 (unsigned long long) fi->fh, *reventsp);
2339
2340 return res;
2341 } else
2342 return -ENOSYS;
2343 }
2344
2345 int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
2346 off_t offset, off_t length, struct fuse_file_info *fi)
2347 {
2348 fuse_get_context()->private_data = fs->user_data;
2349 if (fs->op.fallocate) {
2350 if (fs->debug)
2351 fprintf(stderr, "fallocate %s mode %x, offset: %llu, length: %llu\n",
2352 path,
2353 mode,
2354 (unsigned long long) offset,
2355 (unsigned long long) length);
2356
2357 return fs->op.fallocate(path, mode, offset, length, fi);
2358 } else
2359 return -ENOSYS;
2360 }
2361
2362 ssize_t fuse_fs_copy_file_range(struct fuse_fs *fs, const char *path_in,
2363 struct fuse_file_info *fi_in, off_t off_in,
2364 const char *path_out,
2365 struct fuse_file_info *fi_out, off_t off_out,
2366 size_t len, int flags)
2367 {
2368 fuse_get_context()->private_data = fs->user_data;
2369 if (fs->op.copy_file_range) {
2370 if (fs->debug)
2371 fprintf(stderr, "copy_file_range from %s:%llu to "
2372 "%s:%llu, length: %llu\n",
2373 path_in,
2374 (unsigned long long) off_in,
2375 path_out,
2376 (unsigned long long) off_out,
2377 (unsigned long long) len);
2378
2379 return fs->op.copy_file_range(path_in, fi_in, off_in, path_out,
2380 fi_out, off_out, len, flags);
2381 } else
2382 return -ENOSYS;
2383 }
2384
2385 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
2386 {
2387 struct node *node;
2388 int isopen = 0;
2389 pthread_mutex_lock(&f->lock);
2390 node = lookup_node(f, dir, name);
2391 if (node && node->open_count > 0)
2392 isopen = 1;
2393 pthread_mutex_unlock(&f->lock);
2394 return isopen;
2395 }
2396
2397 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
2398 char *newname, size_t bufsize)
2399 {
2400 struct stat buf;
2401 struct node *node;
2402 struct node *newnode;
2403 char *newpath;
2404 int res;
2405 int failctr = 10;
2406
2407 do {
2408 pthread_mutex_lock(&f->lock);
2409 node = lookup_node(f, dir, oldname);
2410 if (node == NULL) {
2411 pthread_mutex_unlock(&f->lock);
2412 return NULL;
2413 }
2414 do {
2415 f->hidectr ++;
2416 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
2417 (unsigned int) node->nodeid, f->hidectr);
2418 newnode = lookup_node(f, dir, newname);
2419 } while(newnode);
2420
2421 res = try_get_path(f, dir, newname, &newpath, NULL, false);
2422 pthread_mutex_unlock(&f->lock);
2423 if (res)
2424 break;
2425
2426 memset(&buf, 0, sizeof(buf));
2427 res = fuse_fs_getattr(f->fs, newpath, &buf, NULL);
2428 if (res == -ENOENT)
2429 break;
2430 free(newpath);
2431 newpath = NULL;
2432 } while(res == 0 && --failctr);
2433
2434 return newpath;
2435 }
2436
2437 static int hide_node(struct fuse *f, const char *oldpath,
2438 fuse_ino_t dir, const char *oldname)
2439 {
2440 char newname[64];
2441 char *newpath;
2442 int err = -EBUSY;
2443
2444 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
2445 if (newpath) {
2446 err = fuse_fs_rename(f->fs, oldpath, newpath, 0);
2447 if (!err)
2448 err = rename_node(f, dir, oldname, dir, newname, 1);
2449 free(newpath);
2450 }
2451 return err;
2452 }
2453
2454 static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
2455 {
2456 return stbuf->st_mtime == ts->tv_sec &&
2457 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2458 }
2459
2460 #ifndef CLOCK_MONOTONIC
2461 #define CLOCK_MONOTONIC CLOCK_REALTIME
2462 #endif
2463
2464 static void curr_time(struct timespec *now)
2465 {
2466 static clockid_t clockid = CLOCK_MONOTONIC;
2467 int res = clock_gettime(clockid, now);
2468 if (res == -1 && errno == EINVAL) {
2469 clockid = CLOCK_REALTIME;
2470 res = clock_gettime(clockid, now);
2471 }
2472 if (res == -1) {
2473 perror("fuse: clock_gettime");
2474 abort();
2475 }
2476 }
2477
2478 static void update_stat(struct node *node, const struct stat *stbuf)
2479 {
2480 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2481 stbuf->st_size != node->size))
2482 node->cache_valid = 0;
2483 node->mtime.tv_sec = stbuf->st_mtime;
2484 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2485 node->size = stbuf->st_size;
2486 curr_time(&node->stat_updated);
2487 }
2488
2489 static int do_lookup(struct fuse *f, fuse_ino_t nodeid, const char *name,
2490 struct fuse_entry_param *e)
2491 {
2492 struct node *node;
2493
2494 node = find_node(f, nodeid, name);
2495 if (node == NULL)
2496 return -ENOMEM;
2497
2498 e->ino = node->nodeid;
2499 e->generation = node->generation;
2500 e->entry_timeout = f->conf.entry_timeout;
2501 e->attr_timeout = f->conf.attr_timeout;
2502 if (f->conf.auto_cache) {
2503 pthread_mutex_lock(&f->lock);
2504 update_stat(node, &e->attr);
2505 pthread_mutex_unlock(&f->lock);
2506 }
2507 set_stat(f, e->ino, &e->attr);
2508 return 0;
2509 }
2510
2511 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
2512 const char *name, const char *path,
2513 struct fuse_entry_param *e, struct fuse_file_info *fi)
2514 {
2515 int res;
2516
2517 memset(e, 0, sizeof(struct fuse_entry_param));
2518 res = fuse_fs_getattr(f->fs, path, &e->attr, fi);
2519 if (res == 0) {
2520 res = do_lookup(f, nodeid, name, e);
2521 if (res == 0 && f->conf.debug) {
2522 fprintf(stderr, " NODEID: %llu\n",
2523 (unsigned long long) e->ino);
2524 }
2525 }
2526 return res;
2527 }
2528
2529 static struct fuse_context_i *fuse_get_context_internal(void)
2530 {
2531 return (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2532 }
2533
2534 static struct fuse_context_i *fuse_create_context(struct fuse *f)
2535 {
2536 struct fuse_context_i *c = fuse_get_context_internal();
2537 if (c == NULL) {
2538 c = (struct fuse_context_i *)
2539 calloc(1, sizeof(struct fuse_context_i));
2540 if (c == NULL) {
2541 /* This is hard to deal with properly, so just
2542 abort. If memory is so low that the
2543 context cannot be allocated, there's not
2544 much hope for the filesystem anyway */
2545 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
2546 abort();
2547 }
2548 pthread_setspecific(fuse_context_key, c);
2549 } else {
2550 memset(c, 0, sizeof(*c));
2551 }
2552 c->ctx.fuse = f;
2553
2554 return c;
2555 }
2556
2557 static void fuse_freecontext(void *data)
2558 {
2559 free(data);
2560 }
2561
2562 static int fuse_create_context_key(void)
2563 {
2564 int err = 0;
2565 pthread_mutex_lock(&fuse_context_lock);
2566 if (!fuse_context_ref) {
2567 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2568 if (err) {
2569 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
2570 strerror(err));
2571 pthread_mutex_unlock(&fuse_context_lock);
2572 return -1;
2573 }
2574 }
2575 fuse_context_ref++;
2576 pthread_mutex_unlock(&fuse_context_lock);
2577 return 0;
2578 }
2579
2580 static void fuse_delete_context_key(void)
2581 {
2582 pthread_mutex_lock(&fuse_context_lock);
2583 fuse_context_ref--;
2584 if (!fuse_context_ref) {
2585 free(pthread_getspecific(fuse_context_key));
2586 pthread_key_delete(fuse_context_key);
2587 }
2588 pthread_mutex_unlock(&fuse_context_lock);
2589 }
2590
2591 static struct fuse *req_fuse_prepare(fuse_req_t req)
2592 {
2593 struct fuse_context_i *c = fuse_create_context(req_fuse(req));
2594 const struct fuse_ctx *ctx = fuse_req_ctx(req);
2595 c->req = req;
2596 c->ctx.uid = ctx->uid;
2597 c->ctx.gid = ctx->gid;
2598 c->ctx.pid = ctx->pid;
2599 c->ctx.umask = ctx->umask;
2600 return c->ctx.fuse;
2601 }
2602
2603 static inline void reply_err(fuse_req_t req, int err)
2604 {
2605 /* fuse_reply_err() uses non-negated errno values */
2606 fuse_reply_err(req, -err);
2607 }
2608
2609 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
2610 int err)
2611 {
2612 if (!err) {
2613 struct fuse *f = req_fuse(req);
2614 if (fuse_reply_entry(req, e) == -ENOENT) {
2615 /* Skip forget for negative result */
2616 if (e->ino != 0)
2617 forget_node(f, e->ino, 1);
2618 }
2619 } else
2620 reply_err(req, err);
2621 }
2622
2623 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn,
2624 struct fuse_config *cfg)
2625 {
2626 fuse_get_context()->private_data = fs->user_data;
2627 if (!fs->op.write_buf)
2628 conn->want &= ~FUSE_CAP_SPLICE_READ;
2629 if (!fs->op.lock)
2630 conn->want &= ~FUSE_CAP_POSIX_LOCKS;
2631 if (!fs->op.flock)
2632 conn->want &= ~FUSE_CAP_FLOCK_LOCKS;
2633 if (fs->op.init)
2634 fs->user_data = fs->op.init(conn, cfg);
2635 }
2636
2637 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
2638 {
2639 struct fuse *f = (struct fuse *) data;
2640
2641 fuse_create_context(f);
2642 if(conn->capable & FUSE_CAP_EXPORT_SUPPORT)
2643 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
2644 fuse_fs_init(f->fs, conn, &f->conf);
2645 }
2646
2647 void fuse_fs_destroy(struct fuse_fs *fs)
2648 {
2649 fuse_get_context()->private_data = fs->user_data;
2650 if (fs->op.destroy)
2651 fs->op.destroy(fs->user_data);
2652 if (fs->m)
2653 fuse_put_module(fs->m);
2654 free(fs);
2655 }
2656
2657 static void fuse_lib_destroy(void *data)
2658 {
2659 struct fuse *f = (struct fuse *) data;
2660
2661 fuse_create_context(f);
2662 fuse_fs_destroy(f->fs);
2663 f->fs = NULL;
2664 }
2665
2666 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
2667 const char *name)
2668 {
2669 struct fuse *f = req_fuse_prepare(req);
2670 struct fuse_entry_param e;
2671 char *path;
2672 int err;
2673 struct node *dot = NULL;
2674
2675 if (name[0] == '.') {
2676 int len = strlen(name);
2677
2678 if (len == 1 || (name[1] == '.' && len == 2)) {
2679 pthread_mutex_lock(&f->lock);
2680 if (len == 1) {
2681 if (f->conf.debug)
2682 fprintf(stderr, "LOOKUP-DOT\n");
2683 dot = get_node_nocheck(f, parent);
2684 if (dot == NULL) {
2685 pthread_mutex_unlock(&f->lock);
2686 reply_entry(req, &e, -ESTALE);
2687 return;
2688 }
2689 dot->refctr++;
2690 } else {
2691 if (f->conf.debug)
2692 fprintf(stderr, "LOOKUP-DOTDOT\n");
2693 parent = get_node(f, parent)->parent->nodeid;
2694 }
2695 pthread_mutex_unlock(&f->lock);
2696 name = NULL;
2697 }
2698 }
2699
2700 err = get_path_name(f, parent, name, &path);
2701 if (!err) {
2702 struct fuse_intr_data d;
2703 if (f->conf.debug)
2704 fprintf(stderr, "LOOKUP %s\n", path);
2705 fuse_prepare_interrupt(f, req, &d);
2706 err = lookup_path(f, parent, name, path, &e, NULL);
2707 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2708 e.ino = 0;
2709 e.entry_timeout = f->conf.negative_timeout;
2710 err = 0;
2711 }
2712 fuse_finish_interrupt(f, req, &d);
2713 free_path(f, parent, path);
2714 }
2715 if (dot) {
2716 pthread_mutex_lock(&f->lock);
2717 unref_node(f, dot);
2718 pthread_mutex_unlock(&f->lock);
2719 }
2720 reply_entry(req, &e, err);
2721 }
2722
2723 static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
2724 {
2725 if (f->conf.debug)
2726 fprintf(stderr, "FORGET %llu/%llu\n", (unsigned long long)ino,
2727 (unsigned long long) nlookup);
2728 forget_node(f, ino, nlookup);
2729 }
2730
2731 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
2732 {
2733 do_forget(req_fuse(req), ino, nlookup);
2734 fuse_reply_none(req);
2735 }
2736
2737 static void fuse_lib_forget_multi(fuse_req_t req, size_t count,
2738 struct fuse_forget_data *forgets)
2739 {
2740 struct fuse *f = req_fuse(req);
2741 size_t i;
2742
2743 for (i = 0; i < count; i++)
2744 do_forget(f, forgets[i].ino, forgets[i].nlookup);
2745
2746 fuse_reply_none(req);
2747 }
2748
2749
2750 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
2751 struct fuse_file_info *fi)
2752 {
2753 struct fuse *f = req_fuse_prepare(req);
2754 struct stat buf;
2755 char *path;
2756 int err;
2757
2758 memset(&buf, 0, sizeof(buf));
2759
2760 if (fi != NULL)
2761 err = get_path_nullok(f, ino, &path);
2762 else
2763 err = get_path(f, ino, &path);
2764 if (!err) {
2765 struct fuse_intr_data d;
2766 fuse_prepare_interrupt(f, req, &d);
2767 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2768 fuse_finish_interrupt(f, req, &d);
2769 free_path(f, ino, path);
2770 }
2771 if (!err) {
2772 struct node *node;
2773
2774 pthread_mutex_lock(&f->lock);
2775 node = get_node(f, ino);
2776 if (node->is_hidden && buf.st_nlink > 0)
2777 buf.st_nlink--;
2778 if (f->conf.auto_cache)
2779 update_stat(node, &buf);
2780 pthread_mutex_unlock(&f->lock);
2781 set_stat(f, ino, &buf);
2782 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2783 } else
2784 reply_err(req, err);
2785 }
2786
2787 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode,
2788 struct fuse_file_info *fi)
2789 {
2790 fuse_get_context()->private_data = fs->user_data;
2791 if (fs->op.chmod) {
2792 if (fs->debug) {
2793 char buf[10];
2794 fprintf(stderr, "chmod[%s] %s %llo\n",
2795 file_info_string(fi, buf, sizeof(buf)),
2796 path, (unsigned long long) mode);
2797 }
2798 return fs->op.chmod(path, mode, fi);
2799 }
2800 else
2801 return -ENOSYS;
2802 }
2803
2804 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2805 int valid, struct fuse_file_info *fi)
2806 {
2807 struct fuse *f = req_fuse_prepare(req);
2808 struct stat buf;
2809 char *path;
2810 int err;
2811
2812 memset(&buf, 0, sizeof(buf));
2813 if (fi != NULL)
2814 err = get_path_nullok(f, ino, &path);
2815 else
2816 err = get_path(f, ino, &path);
2817 if (!err) {
2818 struct fuse_intr_data d;
2819 fuse_prepare_interrupt(f, req, &d);
2820 err = 0;
2821 if (!err && (valid & FUSE_SET_ATTR_MODE))
2822 err = fuse_fs_chmod(f->fs, path, attr->st_mode, fi);
2823 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2824 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2825 attr->st_uid : (uid_t) -1;
2826 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2827 attr->st_gid : (gid_t) -1;
2828 err = fuse_fs_chown(f->fs, path, uid, gid, fi);
2829 }
2830 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2831 err = fuse_fs_truncate(f->fs, path,
2832 attr->st_size, fi);
2833 }
2834 #ifdef HAVE_UTIMENSAT
2835 if (!err &&
2836 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2837 struct timespec tv[2];
2838
2839 tv[0].tv_sec = 0;
2840 tv[1].tv_sec = 0;
2841 tv[0].tv_nsec = UTIME_OMIT;
2842 tv[1].tv_nsec = UTIME_OMIT;
2843
2844 if (valid & FUSE_SET_ATTR_ATIME_NOW)
2845 tv[0].tv_nsec = UTIME_NOW;
2846 else if (valid & FUSE_SET_ATTR_ATIME)
2847 tv[0] = attr->st_atim;
2848
2849 if (valid & FUSE_SET_ATTR_MTIME_NOW)
2850 tv[1].tv_nsec = UTIME_NOW;
2851 else if (valid & FUSE_SET_ATTR_MTIME)
2852 tv[1] = attr->st_mtim;
2853
2854 err = fuse_fs_utimens(f->fs, path, tv, fi);
2855 } else
2856 #endif
2857 if (!err &&
2858 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2859 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2860 struct timespec tv[2];
2861 tv[0].tv_sec = attr->st_atime;
2862 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2863 tv[1].tv_sec = attr->st_mtime;
2864 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2865 err = fuse_fs_utimens(f->fs, path, tv, fi);
2866 }
2867 if (!err) {
2868 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2869 }
2870 fuse_finish_interrupt(f, req, &d);
2871 free_path(f, ino, path);
2872 }
2873 if (!err) {
2874 if (f->conf.auto_cache) {
2875 pthread_mutex_lock(&f->lock);
2876 update_stat(get_node(f, ino), &buf);
2877 pthread_mutex_unlock(&f->lock);
2878 }
2879 set_stat(f, ino, &buf);
2880 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2881 } else
2882 reply_err(req, err);
2883 }
2884
2885 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
2886 {
2887 struct fuse *f = req_fuse_prepare(req);
2888 char *path;
2889 int err;
2890
2891 err = get_path(f, ino, &path);
2892 if (!err) {
2893 struct fuse_intr_data d;
2894
2895 fuse_prepare_interrupt(f, req, &d);
2896 err = fuse_fs_access(f->fs, path, mask);
2897 fuse_finish_interrupt(f, req, &d);
2898 free_path(f, ino, path);
2899 }
2900 reply_err(req, err);
2901 }
2902
2903 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
2904 {
2905 struct fuse *f = req_fuse_prepare(req);
2906 char linkname[PATH_MAX + 1];
2907 char *path;
2908 int err;
2909
2910 err = get_path(f, ino, &path);
2911 if (!err) {
2912 struct fuse_intr_data d;
2913 fuse_prepare_interrupt(f, req, &d);
2914 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
2915 fuse_finish_interrupt(f, req, &d);
2916 free_path(f, ino, path);
2917 }
2918 if (!err) {
2919 linkname[PATH_MAX] = '\0';
2920 fuse_reply_readlink(req, linkname);
2921 } else
2922 reply_err(req, err);
2923 }
2924
2925 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2926 mode_t mode, dev_t rdev)
2927 {
2928 struct fuse *f = req_fuse_prepare(req);
2929 struct fuse_entry_param e;
2930 char *path;
2931 int err;
2932
2933 err = get_path_name(f, parent, name, &path);
2934 if (!err) {
2935 struct fuse_intr_data d;
2936
2937 fuse_prepare_interrupt(f, req, &d);
2938 err = -ENOSYS;
2939 if (S_ISREG(mode)) {
2940 struct fuse_file_info fi;
2941
2942 memset(&fi, 0, sizeof(fi));
2943 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
2944 err = fuse_fs_create(f->fs, path, mode, &fi);
2945 if (!err) {
2946 err = lookup_path(f, parent, name, path, &e,
2947 &fi);
2948 fuse_fs_release(f->fs, path, &fi);
2949 }
2950 }
2951 if (err == -ENOSYS) {
2952 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2953 if (!err)
2954 err = lookup_path(f, parent, name, path, &e,
2955 NULL);
2956 }
2957 fuse_finish_interrupt(f, req, &d);
2958 free_path(f, parent, path);
2959 }
2960 reply_entry(req, &e, err);
2961 }
2962
2963 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
2964 mode_t mode)
2965 {
2966 struct fuse *f = req_fuse_prepare(req);
2967 struct fuse_entry_param e;
2968 char *path;
2969 int err;
2970
2971 err = get_path_name(f, parent, name, &path);
2972 if (!err) {
2973 struct fuse_intr_data d;
2974
2975 fuse_prepare_interrupt(f, req, &d);
2976 err = fuse_fs_mkdir(f->fs, path, mode);
2977 if (!err)
2978 err = lookup_path(f, parent, name, path, &e, NULL);
2979 fuse_finish_interrupt(f, req, &d);
2980 free_path(f, parent, path);
2981 }
2982 reply_entry(req, &e, err);
2983 }
2984
2985 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
2986 const char *name)
2987 {
2988 struct fuse *f = req_fuse_prepare(req);
2989 struct node *wnode;
2990 char *path;
2991 int err;
2992
2993 err = get_path_wrlock(f, parent, name, &path, &wnode);
2994 if (!err) {
2995 struct fuse_intr_data d;
2996
2997 fuse_prepare_interrupt(f, req, &d);
2998 if (!f->conf.hard_remove && is_open(f, parent, name)) {
2999 err = hide_node(f, path, parent, name);
3000 } else {
3001 err = fuse_fs_unlink(f->fs, path);
3002 if (!err)
3003 remove_node(f, parent, name);
3004 }
3005 fuse_finish_interrupt(f, req, &d);
3006 free_path_wrlock(f, parent, wnode, path);
3007 }
3008 reply_err(req, err);
3009 }
3010
3011 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
3012 {
3013 struct fuse *f = req_fuse_prepare(req);
3014 struct node *wnode;
3015 char *path;
3016 int err;
3017
3018 err = get_path_wrlock(f, parent, name, &path, &wnode);
3019 if (!err) {
3020 struct fuse_intr_data d;
3021
3022 fuse_prepare_interrupt(f, req, &d);
3023 err = fuse_fs_rmdir(f->fs, path);
3024 fuse_finish_interrupt(f, req, &d);
3025 if (!err)
3026 remove_node(f, parent, name);
3027 free_path_wrlock(f, parent, wnode, path);
3028 }
3029 reply_err(req, err);
3030 }
3031
3032 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
3033 fuse_ino_t parent, const char *name)
3034 {
3035 struct fuse *f = req_fuse_prepare(req);
3036 struct fuse_entry_param e;
3037 char *path;
3038 int err;
3039
3040 err = get_path_name(f, parent, name, &path);
3041 if (!err) {
3042 struct fuse_intr_data d;
3043
3044 fuse_prepare_interrupt(f, req, &d);
3045 err = fuse_fs_symlink(f->fs, linkname, path);
3046 if (!err)
3047 err = lookup_path(f, parent, name, path, &e, NULL);
3048 fuse_finish_interrupt(f, req, &d);
3049 free_path(f, parent, path);
3050 }
3051 reply_entry(req, &e, err);
3052 }
3053
3054 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
3055 const char *oldname, fuse_ino_t newdir,
3056 const char *newname, unsigned int flags)
3057 {
3058 struct fuse *f = req_fuse_prepare(req);
3059 char *oldpath;
3060 char *newpath;
3061 struct node *wnode1;
3062 struct node *wnode2;
3063 int err;
3064
3065 err = get_path2(f, olddir, oldname, newdir, newname,
3066 &oldpath, &newpath, &wnode1, &wnode2);
3067 if (!err) {
3068 struct fuse_intr_data d;
3069 err = 0;
3070 fuse_prepare_interrupt(f, req, &d);
3071 if (!f->conf.hard_remove && !(flags & RENAME_EXCHANGE) &&
3072 is_open(f, newdir, newname))
3073 err = hide_node(f, newpath, newdir, newname);
3074 if (!err) {
3075 err = fuse_fs_rename(f->fs, oldpath, newpath, flags);
3076 if (!err) {
3077 if (flags & RENAME_EXCHANGE) {
3078 err = exchange_node(f, olddir, oldname,
3079 newdir, newname);
3080 } else {
3081 err = rename_node(f, olddir, oldname,
3082 newdir, newname, 0);
3083 }
3084 }
3085 }
3086 fuse_finish_interrupt(f, req, &d);
3087 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
3088 }
3089 reply_err(req, err);
3090 }
3091
3092 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
3093 const char *newname)
3094 {
3095 struct fuse *f = req_fuse_prepare(req);
3096 struct fuse_entry_param e;
3097 char *oldpath;
3098 char *newpath;
3099 int err;
3100
3101 err = get_path2(f, ino, NULL, newparent, newname,
3102 &oldpath, &newpath, NULL, NULL);
3103 if (!err) {
3104 struct fuse_intr_data d;
3105
3106 fuse_prepare_interrupt(f, req, &d);
3107 err = fuse_fs_link(f->fs, oldpath, newpath);
3108 if (!err)
3109 err = lookup_path(f, newparent, newname, newpath,
3110 &e, NULL);
3111 fuse_finish_interrupt(f, req, &d);
3112 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3113 }
3114 reply_entry(req, &e, err);
3115 }
3116
3117 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
3118 struct fuse_file_info *fi)
3119 {
3120 struct node *node;
3121 int unlink_hidden = 0;
3122
3123 fuse_fs_release(f->fs, path, fi);
3124
3125 pthread_mutex_lock(&f->lock);
3126 node = get_node(f, ino);
3127 assert(node->open_count > 0);
3128 --node->open_count;
3129 if (node->is_hidden && !node->open_count) {
3130 unlink_hidden = 1;
3131 node->is_hidden = 0;
3132 }
3133 pthread_mutex_unlock(&f->lock);
3134
3135 if(unlink_hidden) {
3136 if (path) {
3137 fuse_fs_unlink(f->fs, path);
3138 } else if (f->conf.nullpath_ok) {
3139 char *unlinkpath;
3140
3141 if (get_path(f, ino, &unlinkpath) == 0)
3142 fuse_fs_unlink(f->fs, unlinkpath);
3143
3144 free_path(f, ino, unlinkpath);
3145 }
3146 }
3147 }
3148
3149 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
3150 const char *name, mode_t mode,
3151 struct fuse_file_info *fi)
3152 {
3153 struct fuse *f = req_fuse_prepare(req);
3154 struct fuse_intr_data d;
3155 struct fuse_entry_param e;
3156 char *path;
3157 int err;
3158
3159 err = get_path_name(f, parent, name, &path);
3160 if (!err) {
3161 fuse_prepare_interrupt(f, req, &d);
3162 err = fuse_fs_create(f->fs, path, mode, fi);
3163 if (!err) {
3164 err = lookup_path(f, parent, name, path, &e, fi);
3165 if (err)
3166 fuse_fs_release(f->fs, path, fi);
3167 else if (!S_ISREG(e.attr.st_mode)) {
3168 err = -EIO;
3169 fuse_fs_release(f->fs, path, fi);
3170 forget_node(f, e.ino, 1);
3171 } else {
3172 if (f->conf.direct_io)
3173 fi->direct_io = 1;
3174 if (f->conf.kernel_cache)
3175 fi->keep_cache = 1;
3176
3177 }
3178 }
3179 fuse_finish_interrupt(f, req, &d);
3180 }
3181 if (!err) {
3182 pthread_mutex_lock(&f->lock);
3183 get_node(f, e.ino)->open_count++;
3184 pthread_mutex_unlock(&f->lock);
3185 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
3186 /* The open syscall was interrupted, so it
3187 must be cancelled */
3188 fuse_do_release(f, e.ino, path, fi);
3189 forget_node(f, e.ino, 1);
3190 }
3191 } else {
3192 reply_err(req, err);
3193 }
3194
3195 free_path(f, parent, path);
3196 }
3197
3198 static double diff_timespec(const struct timespec *t1,
3199 const struct timespec *t2)
3200 {
3201 return (t1->tv_sec - t2->tv_sec) +
3202 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
3203 }
3204
3205 static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
3206 struct fuse_file_info *fi)
3207 {
3208 struct node *node;
3209
3210 pthread_mutex_lock(&f->lock);
3211 node = get_node(f, ino);
3212 if (node->cache_valid) {
3213 struct timespec now;
3214
3215 curr_time(&now);
3216 if (diff_timespec(&now, &node->stat_updated) >
3217 f->conf.ac_attr_timeout) {
3218 struct stat stbuf;
3219 int err;
3220 pthread_mutex_unlock(&f->lock);
3221 err = fuse_fs_getattr(f->fs, path, &stbuf, fi);
3222 pthread_mutex_lock(&f->lock);
3223 if (!err)
3224 update_stat(node, &stbuf);
3225 else
3226 node->cache_valid = 0;
3227 }
3228 }
3229 if (node->cache_valid)
3230 fi->keep_cache = 1;
3231
3232 node->cache_valid = 1;
3233 pthread_mutex_unlock(&f->lock);
3234 }
3235
3236 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
3237 struct fuse_file_info *fi)
3238 {
3239 struct fuse *f = req_fuse_prepare(req);
3240 struct fuse_intr_data d;
3241 char *path;
3242 int err;
3243
3244 err = get_path(f, ino, &path);
3245 if (!err) {
3246 fuse_prepare_interrupt(f, req, &d);
3247 err = fuse_fs_open(f->fs, path, fi);
3248 if (!err) {
3249 if (f->conf.direct_io)
3250 fi->direct_io = 1;
3251 if (f->conf.kernel_cache)
3252 fi->keep_cache = 1;
3253
3254 if (f->conf.auto_cache)
3255 open_auto_cache(f, ino, path, fi);
3256 }
3257 fuse_finish_interrupt(f, req, &d);
3258 }
3259 if (!err) {
3260 pthread_mutex_lock(&f->lock);
3261 get_node(f, ino)->open_count++;
3262 pthread_mutex_unlock(&f->lock);
3263 if (fuse_reply_open(req, fi) == -ENOENT) {
3264 /* The open syscall was interrupted, so it
3265 must be cancelled */
3266 fuse_do_release(f, ino, path, fi);
3267 }
3268 } else
3269 reply_err(req, err);
3270
3271 free_path(f, ino, path);
3272 }
3273
3274 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
3275 off_t off, struct fuse_file_info *fi)
3276 {
3277 struct fuse *f = req_fuse_prepare(req);
3278 struct fuse_bufvec *buf = NULL;
3279 char *path;
3280 int res;
3281
3282 res = get_path_nullok(f, ino, &path);
3283 if (res == 0) {
3284 struct fuse_intr_data d;
3285
3286 fuse_prepare_interrupt(f, req, &d);
3287 res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3288 fuse_finish_interrupt(f, req, &d);
3289 free_path(f, ino, path);
3290 }
3291
3292 if (res == 0)
3293 fuse_reply_data(req, buf, FUSE_BUF_SPLICE_MOVE);
3294 else
3295 reply_err(req, res);
3296
3297 fuse_free_buf(buf);
3298 }
3299
3300 static void fuse_lib_write_buf(fuse_req_t req, fuse_ino_t ino,
3301 struct fuse_bufvec *buf, off_t off,
3302 struct fuse_file_info *fi)
3303 {
3304 struct fuse *f = req_fuse_prepare(req);
3305 char *path;
3306 int res;
3307
3308 res = get_path_nullok(f, ino, &path);
3309 if (res == 0) {
3310 struct fuse_intr_data d;
3311
3312 fuse_prepare_interrupt(f, req, &d);
3313 res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3314 fuse_finish_interrupt(f, req, &d);
3315 free_path(f, ino, path);
3316 }
3317
3318 if (res >= 0)
3319 fuse_reply_write(req, res);
3320 else
3321 reply_err(req, res);
3322 }
3323
3324 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
3325 struct fuse_file_info *fi)
3326 {
3327 struct fuse *f = req_fuse_prepare(req);
3328 char *path;
3329 int err;
3330
3331 err = get_path_nullok(f, ino, &path);
3332 if (!err) {
3333 struct fuse_intr_data d;
3334
3335 fuse_prepare_interrupt(f, req, &d);
3336 err = fuse_fs_fsync(f->fs, path, datasync, fi);
3337 fuse_finish_interrupt(f, req, &d);
3338 free_path(f, ino, path);
3339 }
3340 reply_err(req, err);
3341 }
3342
3343 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
3344 struct fuse_file_info *fi)
3345 {
3346 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
3347 memset(fi, 0, sizeof(struct fuse_file_info));
3348 fi->fh = dh->fh;
3349 return dh;
3350 }
3351
3352 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
3353 struct fuse_file_info *llfi)
3354 {
3355 struct fuse *f = req_fuse_prepare(req);
3356 struct fuse_intr_data d;
3357 struct fuse_dh *dh;
3358 struct fuse_file_info fi;
3359 char *path;
3360 int err;
3361
3362 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
3363 if (dh == NULL) {
3364 reply_err(req, -ENOMEM);
3365 return;
3366 }
3367 memset(dh, 0, sizeof(struct fuse_dh));
3368 dh->fuse = f;
3369 dh->contents = NULL;
3370 dh->first = NULL;
3371 dh->len = 0;
3372 dh->filled = 0;
3373 dh->nodeid = ino;
3374 fuse_mutex_init(&dh->lock);
3375
3376 llfi->fh = (uintptr_t) dh;
3377
3378 memset(&fi, 0, sizeof(fi));
3379 fi.flags = llfi->flags;
3380
3381 err = get_path(f, ino, &path);
3382 if (!err) {
3383 fuse_prepare_interrupt(f, req, &d);
3384 err = fuse_fs_opendir(f->fs, path, &fi);
3385 fuse_finish_interrupt(f, req, &d);
3386 dh->fh = fi.fh;
3387 }
3388 if (!err) {
3389 if (fuse_reply_open(req, llfi) == -ENOENT) {
3390 /* The opendir syscall was interrupted, so it
3391 must be cancelled */
3392 fuse_fs_releasedir(f->fs, path, &fi);
3393 pthread_mutex_destroy(&dh->lock);
3394 free(dh);
3395 }
3396 } else {
3397 reply_err(req, err);
3398 pthread_mutex_destroy(&dh->lock);
3399 free(dh);
3400 }
3401 free_path(f, ino, path);
3402 }
3403
3404 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
3405 {
3406 if (minsize > dh->size) {
3407 char *newptr;
3408 unsigned newsize = dh->size;
3409 if (!newsize)
3410 newsize = 1024;
3411 while (newsize < minsize) {
3412 if (newsize >= 0x80000000)
3413 newsize = 0xffffffff;
3414 else
3415 newsize *= 2;
3416 }
3417
3418 newptr = (char *) realloc(dh->contents, newsize);
3419 if (!newptr) {
3420 dh->error = -ENOMEM;
3421 return -1;
3422 }
3423 dh->contents = newptr;
3424 dh->size = newsize;
3425 }
3426 return 0;
3427 }
3428
3429 static int fuse_add_direntry_to_dh(struct fuse_dh *dh, const char *name,
3430 struct stat *st)
3431 {
3432 struct fuse_direntry *de;
3433
3434 de = malloc(sizeof(struct fuse_direntry));
3435 if (!de) {
3436 dh->error = -ENOMEM;
3437 return -1;
3438 }
3439 de->name = strdup(name);
3440 if (!de->name) {
3441 dh->error = -ENOMEM;
3442 free(de);
3443 return -1;
3444 }
3445 de->stat = *st;
3446 de->next = NULL;
3447
3448 *dh->last = de;
3449 dh->last = &de->next;
3450
3451 return 0;
3452 }
3453
3454 static fuse_ino_t lookup_nodeid(struct fuse *f, fuse_ino_t parent,
3455 const char *name)
3456 {
3457 struct node *node;
3458 fuse_ino_t res = FUSE_UNKNOWN_INO;
3459
3460 pthread_mutex_lock(&f->lock);
3461 node = lookup_node(f, parent, name);
3462 if (node)
3463 res = node->nodeid;
3464 pthread_mutex_unlock(&f->lock);
3465
3466 return res;
3467 }
3468
3469 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
3470 off_t off, enum fuse_fill_dir_flags flags)
3471 {
3472 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3473 struct stat stbuf;
3474
3475 if ((flags & ~FUSE_FILL_DIR_PLUS) != 0) {
3476 dh->error = -EIO;
3477 return 1;
3478 }
3479
3480 if (statp)
3481 stbuf = *statp;
3482 else {
3483 memset(&stbuf, 0, sizeof(stbuf));
3484 stbuf.st_ino = FUSE_UNKNOWN_INO;
3485 }
3486
3487 if (!dh->fuse->conf.use_ino) {
3488 stbuf.st_ino = FUSE_UNKNOWN_INO;
3489 if (dh->fuse->conf.readdir_ino) {
3490 stbuf.st_ino = (ino_t)
3491 lookup_nodeid(dh->fuse, dh->nodeid, name);
3492 }
3493 }
3494
3495 if (off) {
3496 size_t newlen;
3497
3498 if (dh->filled) {
3499 dh->error = -EIO;
3500 return 1;
3501 }
3502
3503 if (dh->first) {
3504 dh->error = -EIO;
3505 return 1;
3506 }
3507
3508 if (extend_contents(dh, dh->needlen) == -1)
3509 return 1;
3510
3511 newlen = dh->len +
3512 fuse_add_direntry(dh->req, dh->contents + dh->len,
3513 dh->needlen - dh->len, name,
3514 &stbuf, off);
3515 if (newlen > dh->needlen)
3516 return 1;
3517
3518 dh->len = newlen;
3519 } else {
3520 dh->filled = 1;
3521
3522 if (fuse_add_direntry_to_dh(dh, name, &stbuf) == -1)
3523 return 1;
3524 }
3525 return 0;
3526 }
3527
3528 static int is_dot_or_dotdot(const char *name)
3529 {
3530 return name[0] == '.' && (name[1] == '\0' ||
3531 (name[1] == '.' && name[2] == '\0'));
3532 }
3533
3534 static int fill_dir_plus(void *dh_, const char *name, const struct stat *statp,
3535 off_t off, enum fuse_fill_dir_flags flags)
3536 {
3537 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3538 struct fuse_entry_param e = {
3539 /* ino=0 tells the kernel to ignore readdirplus stat info */
3540 .ino = 0,
3541 };
3542 struct fuse *f = dh->fuse;
3543 int res;
3544
3545 if ((flags & ~FUSE_FILL_DIR_PLUS) != 0) {
3546 dh->error = -EIO;
3547 return 1;
3548 }
3549
3550 if (off && statp && (flags & FUSE_FILL_DIR_PLUS)) {
3551 e.attr = *statp;
3552
3553 if (!is_dot_or_dotdot(name)) {
3554 res = do_lookup(f, dh->nodeid, name, &e);
3555 if (res) {
3556 dh->error = res;
3557 return 1;
3558 }
3559 }
3560 } else {
3561 e.attr.st_ino = FUSE_UNKNOWN_INO;
3562 if (!f->conf.use_ino && f->conf.readdir_ino) {
3563 e.attr.st_ino = (ino_t)
3564 lookup_nodeid(f, dh->nodeid, name);
3565 }
3566 }
3567
3568 if (off) {
3569 size_t newlen;
3570
3571 if (dh->filled) {
3572 dh->error = -EIO;
3573 return 1;
3574 }
3575
3576 if (dh->first) {
3577 dh->error = -EIO;
3578 return 1;
3579 }
3580 if (extend_contents(dh, dh->needlen) == -1)
3581 return 1;
3582
3583 newlen = dh->len +
3584 fuse_add_direntry_plus(dh->req, dh->contents + dh->len,
3585 dh->needlen - dh->len, name,
3586 &e, off);
3587 if (newlen > dh->needlen)
3588 return 1;
3589 dh->len = newlen;
3590 } else {
3591 dh->filled = 1;
3592
3593 if (fuse_add_direntry_to_dh(dh, name, &e.attr) == -1)
3594 return 1;
3595 }
3596
3597 return 0;
3598 }
3599
3600 static void free_direntries(struct fuse_direntry *de)
3601 {
3602 while (de) {
3603 struct fuse_direntry *next = de->next;
3604 free(de->name);
3605 free(de);
3606 de = next;
3607 }
3608 }
3609
3610 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3611 size_t size, off_t off, struct fuse_dh *dh,
3612 struct fuse_file_info *fi,
3613 enum fuse_readdir_flags flags)
3614 {
3615 char *path;
3616 int err;
3617
3618 if (f->fs->op.readdir)
3619 err = get_path_nullok(f, ino, &path);
3620 else
3621 err = get_path(f, ino, &path);
3622 if (!err) {
3623 struct fuse_intr_data d;
3624 fuse_fill_dir_t filler = fill_dir;
3625
3626 if (flags & FUSE_READDIR_PLUS)
3627 filler = fill_dir_plus;
3628
3629 free_direntries(dh->first);
3630 dh->first = NULL;
3631 dh->last = &dh->first;
3632 dh->len = 0;
3633 dh->error = 0;
3634 dh->needlen = size;
3635 dh->filled = 0;
3636 dh->req = req;
3637 fuse_prepare_interrupt(f, req, &d);
3638 err = fuse_fs_readdir(f->fs, path, dh, filler, off, fi, flags);
3639 fuse_finish_interrupt(f, req, &d);
3640 dh->req = NULL;
3641 if (!err)
3642 err = dh->error;
3643 if (err)
3644 dh->filled = 0;
3645 free_path(f, ino, path);
3646 }
3647 return err;
3648 }
3649
3650 static int readdir_fill_from_list(fuse_req_t req, struct fuse_dh *dh,
3651 off_t off, enum fuse_readdir_flags flags)
3652 {
3653 off_t pos;
3654 struct fuse_direntry *de = dh->first;
3655
3656 dh->len = 0;
3657
3658 if (extend_contents(dh, dh->needlen) == -1)
3659 return dh->error;
3660
3661 for (pos = 0; pos < off; pos++) {
3662 if (!de)
3663 break;
3664
3665 de = de->next;
3666 }
3667 while (de) {
3668 char *p = dh->contents + dh->len;
3669 unsigned rem = dh->needlen - dh->len;
3670 unsigned thislen;
3671 unsigned newlen;
3672 pos++;
3673
3674 if (flags & FUSE_READDIR_PLUS) {
3675 struct fuse_entry_param e = {
3676 .ino = 0,
3677 .attr = de->stat,
3678 };
3679 thislen = fuse_add_direntry_plus(req, p, rem,
3680 de->name, &e, pos);
3681 } else {
3682 thislen = fuse_add_direntry(req, p, rem,
3683 de->name, &de->stat, pos);
3684 }
3685 newlen = dh->len + thislen;
3686 if (newlen > dh->needlen)
3687 break;
3688 dh->len = newlen;
3689 de = de->next;
3690 }
3691 return 0;
3692 }
3693
3694 static void fuse_readdir_common(fuse_req_t req, fuse_ino_t ino, size_t size,
3695 off_t off, struct fuse_file_info *llfi,
3696 enum fuse_readdir_flags flags)
3697 {
3698 struct fuse *f = req_fuse_prepare(req);
3699 struct fuse_file_info fi;
3700 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3701 int err;
3702
3703 pthread_mutex_lock(&dh->lock);
3704 /* According to SUS, directory contents need to be refreshed on
3705 rewinddir() */
3706 if (!off)
3707 dh->filled = 0;
3708
3709 if (!dh->filled) {
3710 err = readdir_fill(f, req, ino, size, off, dh, &fi, flags);
3711 if (err) {
3712 reply_err(req, err);
3713 goto out;
3714 }
3715 }
3716 if (dh->filled) {
3717 dh->needlen = size;
3718 err = readdir_fill_from_list(req, dh, off, flags);
3719 if (err) {
3720 reply_err(req, err);
3721 goto out;
3722 }
3723 }
3724 fuse_reply_buf(req, dh->contents, dh->len);
3725 out:
3726 pthread_mutex_unlock(&dh->lock);
3727 }
3728
3729 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
3730 off_t off, struct fuse_file_info *llfi)
3731 {
3732 fuse_readdir_common(req, ino, size, off, llfi, 0);
3733 }
3734
3735 static void fuse_lib_readdirplus(fuse_req_t req, fuse_ino_t ino, size_t size,
3736 off_t off, struct fuse_file_info *llfi)
3737 {
3738 fuse_readdir_common(req, ino, size, off, llfi, FUSE_READDIR_PLUS);
3739 }
3740
3741 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
3742 struct fuse_file_info *llfi)
3743 {
3744 struct fuse *f = req_fuse_prepare(req);
3745 struct fuse_intr_data d;
3746 struct fuse_file_info fi;
3747 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3748 char *path;
3749
3750 get_path_nullok(f, ino, &path);
3751
3752 fuse_prepare_interrupt(f, req, &d);
3753 fuse_fs_releasedir(f->fs, path, &fi);
3754 fuse_finish_interrupt(f, req, &d);
3755 free_path(f, ino, path);
3756
3757 pthread_mutex_lock(&dh->lock);
3758 pthread_mutex_unlock(&dh->lock);
3759 pthread_mutex_destroy(&dh->lock);
3760 free_direntries(dh->first);
3761 free(dh->contents);
3762 free(dh);
3763 reply_err(req, 0);
3764 }
3765
3766 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
3767 struct fuse_file_info *llfi)
3768 {
3769 struct fuse *f = req_fuse_prepare(req);
3770 struct fuse_file_info fi;
3771 char *path;
3772 int err;
3773
3774 get_dirhandle(llfi, &fi);
3775
3776 err = get_path_nullok(f, ino, &path);
3777 if (!err) {
3778 struct fuse_intr_data d;
3779 fuse_prepare_interrupt(f, req, &d);
3780 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3781 fuse_finish_interrupt(f, req, &d);
3782 free_path(f, ino, path);
3783 }
3784 reply_err(req, err);
3785 }
3786
3787 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
3788 {
3789 struct fuse *f = req_fuse_prepare(req);
3790 struct statvfs buf;
3791 char *path = NULL;
3792 int err = 0;
3793
3794 memset(&buf, 0, sizeof(buf));
3795 if (ino)
3796 err = get_path(f, ino, &path);
3797
3798 if (!err) {
3799 struct fuse_intr_data d;
3800 fuse_prepare_interrupt(f, req, &d);
3801 err = fuse_fs_statfs(f->fs, path ? path : "/", &buf);
3802 fuse_finish_interrupt(f, req, &d);
3803 free_path(f, ino, path);
3804 }
3805
3806 if (!err)
3807 fuse_reply_statfs(req, &buf);
3808 else
3809 reply_err(req, err);
3810 }
3811
3812 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3813 const char *value, size_t size, int flags)
3814 {
3815 struct fuse *f = req_fuse_prepare(req);
3816 char *path;
3817 int err;
3818
3819 err = get_path(f, ino, &path);
3820 if (!err) {
3821 struct fuse_intr_data d;
3822 fuse_prepare_interrupt(f, req, &d);
3823 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3824 fuse_finish_interrupt(f, req, &d);
3825 free_path(f, ino, path);
3826 }
3827 reply_err(req, err);
3828 }
3829
3830 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3831 const char *name, char *value, size_t size)
3832 {
3833 int err;
3834 char *path;
3835
3836 err = get_path(f, ino, &path);
3837 if (!err) {
3838 struct fuse_intr_data d;
3839 fuse_prepare_interrupt(f, req, &d);
3840 err = fuse_fs_getxattr(f->fs, path, name, value, size);
3841 fuse_finish_interrupt(f, req, &d);
3842 free_path(f, ino, path);
3843 }
3844 return err;
3845 }
3846
3847 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3848 size_t size)
3849 {
3850 struct fuse *f = req_fuse_prepare(req);
3851 int res;
3852
3853 if (size) {
3854 char *value = (char *) malloc(size);
3855 if (value == NULL) {
3856 reply_err(req, -ENOMEM);
3857 return;
3858 }
3859 res = common_getxattr(f, req, ino, name, value, size);
3860 if (res > 0)
3861 fuse_reply_buf(req, value, res);
3862 else
3863 reply_err(req, res);
3864 free(value);
3865 } else {
3866 res = common_getxattr(f, req, ino, name, NULL, 0);
3867 if (res >= 0)
3868 fuse_reply_xattr(req, res);
3869 else
3870 reply_err(req, res);
3871 }
3872 }
3873
3874 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3875 char *list, size_t size)
3876 {
3877 char *path;
3878 int err;
3879
3880 err = get_path(f, ino, &path);
3881 if (!err) {
3882 struct fuse_intr_data d;
3883 fuse_prepare_interrupt(f, req, &d);
3884 err = fuse_fs_listxattr(f->fs, path, list, size);
3885 fuse_finish_interrupt(f, req, &d);
3886 free_path(f, ino, path);
3887 }
3888 return err;
3889 }
3890
3891 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
3892 {
3893 struct fuse *f = req_fuse_prepare(req);
3894 int res;
3895
3896 if (size) {
3897 char *list = (char *) malloc(size);
3898 if (list == NULL) {
3899 reply_err(req, -ENOMEM);
3900 return;
3901 }
3902 res = common_listxattr(f, req, ino, list, size);
3903 if (res > 0)
3904 fuse_reply_buf(req, list, res);
3905 else
3906 reply_err(req, res);
3907 free(list);
3908 } else {
3909 res = common_listxattr(f, req, ino, NULL, 0);
3910 if (res >= 0)
3911 fuse_reply_xattr(req, res);
3912 else
3913 reply_err(req, res);
3914 }
3915 }
3916
3917 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
3918 const char *name)
3919 {
3920 struct fuse *f = req_fuse_prepare(req);
3921 char *path;
3922 int err;
3923
3924 err = get_path(f, ino, &path);
3925 if (!err) {
3926 struct fuse_intr_data d;
3927 fuse_prepare_interrupt(f, req, &d);
3928 err = fuse_fs_removexattr(f->fs, path, name);
3929 fuse_finish_interrupt(f, req, &d);
3930 free_path(f, ino, path);
3931 }
3932 reply_err(req, err);
3933 }
3934
3935 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
3936 {
3937 struct lock *l;
3938
3939 for (l = node->locks; l; l = l->next)
3940 if (l->owner != lock->owner &&
3941 lock->start <= l->end && l->start <= lock->end &&
3942 (l->type == F_WRLCK || lock->type == F_WRLCK))
3943 break;
3944
3945 return l;
3946 }
3947
3948 static void delete_lock(struct lock **lockp)
3949 {
3950 struct lock *l = *lockp;
3951 *lockp = l->next;
3952 free(l);
3953 }
3954
3955 static void insert_lock(struct lock **pos, struct lock *lock)
3956 {
3957 lock->next = *pos;
3958 *pos = lock;
3959 }
3960
3961 static int locks_insert(struct node *node, struct lock *lock)
3962 {
3963 struct lock **lp;
3964 struct lock *newl1 = NULL;
3965 struct lock *newl2 = NULL;
3966
3967 if (lock->type != F_UNLCK || lock->start != 0 ||
3968 lock->end != OFFSET_MAX) {
3969 newl1 = malloc(sizeof(struct lock));
3970 newl2 = malloc(sizeof(struct lock));
3971
3972 if (!newl1 || !newl2) {
3973 free(newl1);
3974 free(newl2);
3975 return -ENOLCK;
3976 }
3977 }
3978
3979 for (lp = &node->locks; *lp;) {
3980 struct lock *l = *lp;
3981 if (l->owner != lock->owner)
3982 goto skip;
3983
3984 if (lock->type == l->type) {
3985 if (l->end < lock->start - 1)
3986 goto skip;
3987 if (lock->end < l->start - 1)
3988 break;
3989 if (l->start <= lock->start && lock->end <= l->end)
3990 goto out;
3991 if (l->start < lock->start)
3992 lock->start = l->start;
3993 if (lock->end < l->end)
3994 lock->end = l->end;
3995 goto delete;
3996 } else {
3997 if (l->end < lock->start)
3998 goto skip;
3999 if (lock->end < l->start)
4000 break;
4001 if (lock->start <= l->start && l->end <= lock->end)
4002 goto delete;
4003 if (l->end <= lock->end) {
4004 l->end = lock->start - 1;
4005 goto skip;
4006 }
4007 if (lock->start <= l->start) {
4008 l->start = lock->end + 1;
4009 break;
4010 }
4011 *newl2 = *l;
4012 newl2->start = lock->end + 1;
4013 l->end = lock->start - 1;
4014 insert_lock(&l->next, newl2);
4015 newl2 = NULL;
4016 }
4017 skip:
4018 lp = &l->next;
4019 continue;
4020
4021 delete:
4022 delete_lock(lp);
4023 }
4024 if (lock->type != F_UNLCK) {
4025 *newl1 = *lock;
4026 insert_lock(lp, newl1);
4027 newl1 = NULL;
4028 }
4029 out:
4030 free(newl1);
4031 free(newl2);
4032 return 0;
4033 }
4034
4035 static void flock_to_lock(struct flock *flock, struct lock *lock)
4036 {
4037 memset(lock, 0, sizeof(struct lock));
4038 lock->type = flock->l_type;
4039 lock->start = flock->l_start;
4040 lock->end =
4041 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
4042 lock->pid = flock->l_pid;
4043 }
4044
4045 static void lock_to_flock(struct lock *lock, struct flock *flock)
4046 {
4047 flock->l_type = lock->type;
4048 flock->l_start = lock->start;
4049 flock->l_len =
4050 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
4051 flock->l_pid = lock->pid;
4052 }
4053
4054 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
4055 const char *path, struct fuse_file_info *fi)
4056 {
4057 struct fuse_intr_data d;
4058 struct flock lock;
4059 struct lock l;
4060 int err;
4061 int errlock;
4062
4063 fuse_prepare_interrupt(f, req, &d);
4064 memset(&lock, 0, sizeof(lock));
4065 lock.l_type = F_UNLCK;
4066 lock.l_whence = SEEK_SET;
4067 err = fuse_fs_flush(f->fs, path, fi);
4068 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
4069 fuse_finish_interrupt(f, req, &d);
4070
4071 if (errlock != -ENOSYS) {
4072 flock_to_lock(&lock, &l);
4073 l.owner = fi->lock_owner;
4074 pthread_mutex_lock(&f->lock);
4075 locks_insert(get_node(f, ino), &l);
4076 pthread_mutex_unlock(&f->lock);
4077
4078 /* if op.lock() is defined FLUSH is needed regardless
4079 of op.flush() */
4080 if (err == -ENOSYS)
4081 err = 0;
4082 }
4083 return err;
4084 }
4085
4086 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
4087 struct fuse_file_info *fi)
4088 {
4089 struct fuse *f = req_fuse_prepare(req);
4090 struct fuse_intr_data d;
4091 char *path;
4092 int err = 0;
4093
4094 get_path_nullok(f, ino, &path);
4095 if (fi->flush) {
4096 err = fuse_flush_common(f, req, ino, path, fi);
4097 if (err == -ENOSYS)
4098 err = 0;
4099 }
4100
4101 fuse_prepare_interrupt(f, req, &d);
4102 fuse_do_release(f, ino, path, fi);
4103 fuse_finish_interrupt(f, req, &d);
4104 free_path(f, ino, path);
4105
4106 reply_err(req, err);
4107 }
4108
4109 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
4110 struct fuse_file_info *fi)
4111 {
4112 struct fuse *f = req_fuse_prepare(req);
4113 char *path;
4114 int err;
4115
4116 get_path_nullok(f, ino, &path);
4117 err = fuse_flush_common(f, req, ino, path, fi);
4118 free_path(f, ino, path);
4119
4120 reply_err(req, err);
4121 }
4122
4123 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
4124 struct fuse_file_info *fi, struct flock *lock,
4125 int cmd)
4126 {
4127 struct fuse *f = req_fuse_prepare(req);
4128 char *path;
4129 int err;
4130
4131 err = get_path_nullok(f, ino, &path);
4132 if (!err) {
4133 struct fuse_intr_data d;
4134 fuse_prepare_interrupt(f, req, &d);
4135 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
4136 fuse_finish_interrupt(f, req, &d);
4137 free_path(f, ino, path);
4138 }
4139 return err;
4140 }
4141
4142 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
4143 struct fuse_file_info *fi, struct flock *lock)
4144 {
4145 int err;
4146 struct lock l;
4147 struct lock *conflict;
4148 struct fuse *f = req_fuse(req);
4149
4150 flock_to_lock(lock, &l);
4151 l.owner = fi->lock_owner;
4152 pthread_mutex_lock(&f->lock);
4153 conflict = locks_conflict(get_node(f, ino), &l);
4154 if (conflict)
4155 lock_to_flock(conflict, lock);
4156 pthread_mutex_unlock(&f->lock);
4157 if (!conflict)
4158 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
4159 else
4160 err = 0;
4161
4162 if (!err)
4163 fuse_reply_lock(req, lock);
4164 else
4165 reply_err(req, err);
4166 }
4167
4168 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
4169 struct fuse_file_info *fi, struct flock *lock,
4170 int sleep)
4171 {
4172 int err = fuse_lock_common(req, ino, fi, lock,
4173 sleep ? F_SETLKW : F_SETLK);
4174 if (!err) {
4175 struct fuse *f = req_fuse(req);
4176 struct lock l;
4177 flock_to_lock(lock, &l);
4178 l.owner = fi->lock_owner;
4179 pthread_mutex_lock(&f->lock);
4180 locks_insert(get_node(f, ino), &l);
4181 pthread_mutex_unlock(&f->lock);
4182 }
4183 reply_err(req, err);
4184 }
4185
4186 static void fuse_lib_flock(fuse_req_t req, fuse_ino_t ino,
4187 struct fuse_file_info *fi, int op)
4188 {
4189 struct fuse *f = req_fuse_prepare(req);
4190 char *path;
4191 int err;
4192
4193 err = get_path_nullok(f, ino, &path);
4194 if (err == 0) {
4195 struct fuse_intr_data d;
4196 fuse_prepare_interrupt(f, req, &d);
4197 err = fuse_fs_flock(f->fs, path, fi, op);
4198 fuse_finish_interrupt(f, req, &d);
4199 free_path(f, ino, path);
4200 }
4201 reply_err(req, err);
4202 }
4203
4204 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
4205 uint64_t idx)
4206 {
4207 struct fuse *f = req_fuse_prepare(req);
4208 struct fuse_intr_data d;
4209 char *path;
4210 int err;
4211
4212 err = get_path(f, ino, &path);
4213 if (!err) {
4214 fuse_prepare_interrupt(f, req, &d);
4215 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
4216 fuse_finish_interrupt(f, req, &d);
4217 free_path(f, ino, path);
4218 }
4219 if (!err)
4220 fuse_reply_bmap(req, idx);
4221 else
4222 reply_err(req, err);
4223 }
4224
4225 static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
4226 struct fuse_file_info *llfi, unsigned int flags,
4227 const void *in_buf, size_t in_bufsz,
4228 size_t out_bufsz)
4229 {
4230 struct fuse *f = req_fuse_prepare(req);
4231 struct fuse_intr_data d;
4232 struct fuse_file_info fi;
4233 char *path, *out_buf = NULL;
4234 int err;
4235
4236 err = -EPERM;
4237 if (flags & FUSE_IOCTL_UNRESTRICTED)
4238 goto err;
4239
4240 if (flags & FUSE_IOCTL_DIR)
4241 get_dirhandle(llfi, &fi);
4242 else
4243 fi = *llfi;
4244
4245 if (out_bufsz) {
4246 err = -ENOMEM;
4247 out_buf = malloc(out_bufsz);
4248 if (!out_buf)
4249 goto err;
4250 }
4251
4252 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
4253 if (out_buf && in_bufsz)
4254 memcpy(out_buf, in_buf, in_bufsz);
4255
4256 err = get_path_nullok(f, ino, &path);
4257 if (err)
4258 goto err;
4259
4260 fuse_prepare_interrupt(f, req, &d);
4261
4262 err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
4263 out_buf ?: (void *)in_buf);
4264
4265 fuse_finish_interrupt(f, req, &d);
4266 free_path(f, ino, path);
4267
4268 fuse_reply_ioctl(req, err, out_buf, out_bufsz);
4269 goto out;
4270 err:
4271 reply_err(req, err);
4272 out:
4273 free(out_buf);
4274 }
4275
4276 static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
4277 struct fuse_file_info *fi, struct fuse_pollhandle *ph)
4278 {
4279 struct fuse *f = req_fuse_prepare(req);
4280 struct fuse_intr_data d;
4281 char *path;
4282 int err;
4283 unsigned revents = 0;
4284
4285 err = get_path_nullok(f, ino, &path);
4286 if (!err) {
4287 fuse_prepare_interrupt(f, req, &d);
4288 err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4289 fuse_finish_interrupt(f, req, &d);
4290 free_path(f, ino, path);
4291 }
4292 if (!err)
4293 fuse_reply_poll(req, revents);
4294 else
4295 reply_err(req, err);
4296 }
4297
4298 static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode,
4299 off_t offset, off_t length, struct fuse_file_info *fi)
4300 {
4301 struct fuse *f = req_fuse_prepare(req);
4302 struct fuse_intr_data d;
4303 char *path;
4304 int err;
4305
4306 err = get_path_nullok(f, ino, &path);
4307 if (!err) {
4308 fuse_prepare_interrupt(f, req, &d);
4309 err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4310 fuse_finish_interrupt(f, req, &d);
4311 free_path(f, ino, path);
4312 }
4313 reply_err(req, err);
4314 }
4315
4316 static void fuse_lib_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in,
4317 off_t off_in, struct fuse_file_info *fi_in,
4318 fuse_ino_t nodeid_out, off_t off_out,
4319 struct fuse_file_info *fi_out, size_t len,
4320 int flags)
4321 {
4322 struct fuse *f = req_fuse_prepare(req);
4323 struct fuse_intr_data d;
4324 char *path_in, *path_out;
4325 int err;
4326 ssize_t res;
4327
4328 err = get_path_nullok(f, nodeid_in, &path_in);
4329 if (err) {
4330 reply_err(req, err);
4331 return;
4332 }
4333
4334 err = get_path_nullok(f, nodeid_out, &path_out);
4335 if (err) {
4336 free_path(f, nodeid_in, path_in);
4337 reply_err(req, err);
4338 return;
4339 }
4340
4341 fuse_prepare_interrupt(f, req, &d);
4342 res = fuse_fs_copy_file_range(f->fs, path_in, fi_in, off_in, path_out,
4343 fi_out, off_out, len, flags);
4344 fuse_finish_interrupt(f, req, &d);
4345
4346 if (res >= 0)
4347 fuse_reply_write(req, res);
4348 else
4349 reply_err(req, res);
4350
4351 free_path(f, nodeid_in, path_in);
4352 free_path(f, nodeid_out, path_out);
4353 }
4354
4355 static int clean_delay(struct fuse *f)
4356 {
4357 /*
4358 * This is calculating the delay between clean runs. To
4359 * reduce the number of cleans we are doing them 10 times
4360 * within the remember window.
4361 */
4362 int min_sleep = 60;
4363 int max_sleep = 3600;
4364 int sleep_time = f->conf.remember / 10;
4365
4366 if (sleep_time > max_sleep)
4367 return max_sleep;
4368 if (sleep_time < min_sleep)
4369 return min_sleep;
4370 return sleep_time;
4371 }
4372
4373 int fuse_clean_cache(struct fuse *f)
4374 {
4375 struct node_lru *lnode;
4376 struct list_head *curr, *next;
4377 struct node *node;
4378 struct timespec now;
4379
4380 pthread_mutex_lock(&f->lock);
4381
4382 curr_time(&now);
4383
4384 for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4385 double age;
4386
4387 next = curr->next;
4388 lnode = list_entry(curr, struct node_lru, lru);
4389 node = &lnode->node;
4390
4391 age = diff_timespec(&now, &lnode->forget_time);
4392 if (age <= f->conf.remember)
4393 break;
4394
4395 assert(node->nlookup == 1);
4396
4397 /* Don't forget active directories */
4398 if (node->refctr > 1)
4399 continue;
4400
4401 node->nlookup = 0;
4402 unhash_name(f, node);
4403 unref_node(f, node);
4404 }
4405 pthread_mutex_unlock(&f->lock);
4406
4407 return clean_delay(f);
4408 }
4409
4410 static struct fuse_lowlevel_ops fuse_path_ops = {
4411 .init = fuse_lib_init,
4412 .destroy = fuse_lib_destroy,
4413 .lookup = fuse_lib_lookup,
4414 .forget = fuse_lib_forget,
4415 .forget_multi = fuse_lib_forget_multi,
4416 .getattr = fuse_lib_getattr,
4417 .setattr = fuse_lib_setattr,
4418 .access = fuse_lib_access,
4419 .readlink = fuse_lib_readlink,
4420 .mknod = fuse_lib_mknod,
4421 .mkdir = fuse_lib_mkdir,
4422 .unlink = fuse_lib_unlink,
4423 .rmdir = fuse_lib_rmdir,
4424 .symlink = fuse_lib_symlink,
4425 .rename = fuse_lib_rename,
4426 .link = fuse_lib_link,
4427 .create = fuse_lib_create,
4428 .open = fuse_lib_open,
4429 .read = fuse_lib_read,
4430 .write_buf = fuse_lib_write_buf,
4431 .flush = fuse_lib_flush,
4432 .release = fuse_lib_release,
4433 .fsync = fuse_lib_fsync,
4434 .opendir = fuse_lib_opendir,
4435 .readdir = fuse_lib_readdir,
4436 .readdirplus = fuse_lib_readdirplus,
4437 .releasedir = fuse_lib_releasedir,
4438 .fsyncdir = fuse_lib_fsyncdir,
4439 .statfs = fuse_lib_statfs,
4440 .setxattr = fuse_lib_setxattr,
4441 .getxattr = fuse_lib_getxattr,
4442 .listxattr = fuse_lib_listxattr,
4443 .removexattr = fuse_lib_removexattr,
4444 .getlk = fuse_lib_getlk,
4445 .setlk = fuse_lib_setlk,
4446 .flock = fuse_lib_flock,
4447 .bmap = fuse_lib_bmap,
4448 .ioctl = fuse_lib_ioctl,
4449 .poll = fuse_lib_poll,
4450 .fallocate = fuse_lib_fallocate,
4451 .copy_file_range = fuse_lib_copy_file_range,
4452 };
4453
4454 int fuse_notify_poll(struct fuse_pollhandle *ph)
4455 {
4456 return fuse_lowlevel_notify_poll(ph);
4457 }
4458
4459 struct fuse_session *fuse_get_session(struct fuse *f)
4460 {
4461 return f->se;
4462 }
4463
4464 static int fuse_session_loop_remember(struct fuse *f)
4465 {
4466 struct fuse_session *se = f->se;
4467 int res = 0;
4468 struct timespec now;
4469 time_t next_clean;
4470 struct pollfd fds = {
4471 .fd = se->fd,
4472 .events = POLLIN
4473 };
4474 struct fuse_buf fbuf = {
4475 .mem = NULL,
4476 };
4477
4478 curr_time(&now);
4479 next_clean = now.tv_sec;
4480 while (!fuse_session_exited(se)) {
4481 unsigned timeout;
4482
4483 curr_time(&now);
4484 if (now.tv_sec < next_clean)
4485 timeout = next_clean - now.tv_sec;
4486 else
4487 timeout = 0;
4488
4489 res = poll(&fds, 1, timeout * 1000);
4490 if (res == -1) {
4491 if (errno == -EINTR)
4492 continue;
4493 else
4494 break;
4495 } else if (res > 0) {
4496 res = fuse_session_receive_buf_int(se, &fbuf, NULL);
4497
4498 if (res == -EINTR)
4499 continue;
4500 if (res <= 0)
4501 break;
4502
4503 fuse_session_process_buf_int(se, &fbuf, NULL);
4504 } else {
4505 timeout = fuse_clean_cache(f);
4506 curr_time(&now);
4507 next_clean = now.tv_sec + timeout;
4508 }
4509 }
4510
4511 free(fbuf.mem);
4512 fuse_session_reset(se);
4513 return res < 0 ? -1 : 0;
4514 }
4515
4516 int fuse_loop(struct fuse *f)
4517 {
4518 if (!f)
4519 return -1;
4520
4521 if (lru_enabled(f))
4522 return fuse_session_loop_remember(f);
4523
4524 return fuse_session_loop(f->se);
4525 }
4526
4527 FUSE_SYMVER(".symver fuse_loop_mt_32,fuse_loop_mt@@FUSE_3.2");
4528 int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config)
4529 {
4530 if (f == NULL)
4531 return -1;
4532
4533 int res = fuse_start_cleanup_thread(f);
4534 if (res)
4535 return -1;
4536
4537 res = fuse_session_loop_mt_32(fuse_get_session(f), config);
4538 fuse_stop_cleanup_thread(f);
4539 return res;
4540 }
4541
4542 int fuse_loop_mt_31(struct fuse *f, int clone_fd);
4543 FUSE_SYMVER(".symver fuse_loop_mt_31,fuse_loop_mt@FUSE_3.0");
4544 int fuse_loop_mt_31(struct fuse *f, int clone_fd)
4545 {
4546 struct fuse_loop_config config;
4547 config.clone_fd = clone_fd;
4548 config.max_idle_threads = 10;
4549 return fuse_loop_mt_32(f, &config);
4550 }
4551
4552 void fuse_exit(struct fuse *f)
4553 {
4554 fuse_session_exit(f->se);
4555 }
4556
4557 struct fuse_context *fuse_get_context(void)
4558 {
4559 struct fuse_context_i *c = fuse_get_context_internal();
4560
4561 if (c)
4562 return &c->ctx;
4563 else
4564 return NULL;
4565 }
4566
4567 int fuse_getgroups(int size, gid_t list[])
4568 {
4569 struct fuse_context_i *c = fuse_get_context_internal();
4570 if (!c)
4571 return -EINVAL;
4572
4573 return fuse_req_getgroups(c->req, size, list);
4574 }
4575
4576 int fuse_interrupted(void)
4577 {
4578 struct fuse_context_i *c = fuse_get_context_internal();
4579
4580 if (c)
4581 return fuse_req_interrupted(c->req);
4582 else
4583 return 0;
4584 }
4585
4586 int fuse_invalidate_path(struct fuse *f, const char *path) {
4587 fuse_ino_t ino;
4588 int err = lookup_path_in_cache(f, path, &ino);
4589 if (err) {
4590 return err;
4591 }
4592
4593 return fuse_lowlevel_notify_inval_inode(f->se, ino, 0, 0);
4594 }
4595
4596 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4597
4598 static const struct fuse_opt fuse_lib_opts[] = {
4599 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
4600 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
4601 FUSE_LIB_OPT("debug", debug, 1),
4602 FUSE_LIB_OPT("-d", debug, 1),
4603 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
4604 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
4605 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
4606 FUSE_LIB_OPT("umask=", set_mode, 1),
4607 FUSE_LIB_OPT("umask=%o", umask, 0),
4608 FUSE_LIB_OPT("uid=", set_uid, 1),
4609 FUSE_LIB_OPT("uid=%d", uid, 0),
4610 FUSE_LIB_OPT("gid=", set_gid, 1),
4611 FUSE_LIB_OPT("gid=%d", gid, 0),
4612 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
4613 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
4614 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
4615 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
4616 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
4617 FUSE_LIB_OPT("noforget", remember, -1),
4618 FUSE_LIB_OPT("remember=%u", remember, 0),
4619 FUSE_LIB_OPT("modules=%s", modules, 0),
4620 FUSE_OPT_END
4621 };
4622
4623 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
4624 struct fuse_args *outargs)
4625 {
4626 (void) arg; (void) outargs; (void) data; (void) key;
4627
4628 /* Pass through unknown options */
4629 return 1;
4630 }
4631
4632
4633 static const struct fuse_opt fuse_help_opts[] = {
4634 FUSE_LIB_OPT("modules=%s", modules, 1),
4635 FUSE_OPT_KEY("modules=%s", FUSE_OPT_KEY_KEEP),
4636 FUSE_OPT_END
4637 };
4638
4639 static void print_module_help(const char *name,
4640 fuse_module_factory_t *fac)
4641 {
4642 struct fuse_args a = FUSE_ARGS_INIT(0, NULL);
4643 if (fuse_opt_add_arg(&a, "") == -1 ||
4644 fuse_opt_add_arg(&a, "-h") == -1)
4645 return;
4646 printf("\nOptions for %s module:\n", name);
4647 (*fac)(&a, NULL);
4648 }
4649
4650 void fuse_lib_help(struct fuse_args *args)
4651 {
4652 /* These are not all options, but only the ones that
4653 may be of interest to an end-user */
4654 printf(
4655 " -o kernel_cache cache files in kernel\n"
4656 " -o [no]auto_cache enable caching based on modification times (off)\n"
4657 " -o umask=M set file permissions (octal)\n"
4658 " -o uid=N set file owner\n"
4659 " -o gid=N set file group\n"
4660 " -o entry_timeout=T cache timeout for names (1.0s)\n"
4661 " -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
4662 " -o attr_timeout=T cache timeout for attributes (1.0s)\n"
4663 " -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
4664 " -o noforget never forget cached inodes\n"
4665 " -o remember=T remember cached inodes for T seconds (0s)\n"
4666 " -o modules=M1[:M2...] names of modules to push onto filesystem stack\n");
4667
4668
4669 /* Print low-level help */
4670 fuse_lowlevel_help();
4671
4672 /* Print help for builtin modules */
4673 print_module_help("subdir", &fuse_module_subdir_factory);
4674 #ifdef HAVE_ICONV
4675 print_module_help("iconv", &fuse_module_iconv_factory);
4676 #endif
4677
4678 /* Parse command line options in case we need to
4679 activate more modules */
4680 struct fuse_config conf = { .modules = NULL };
4681 if (fuse_opt_parse(args, &conf, fuse_help_opts,
4682 fuse_lib_opt_proc) == -1
4683 || !conf.modules)
4684 return;
4685
4686 char *module;
4687 char *next;
4688 struct fuse_module *m;
4689
4690 // Iterate over all modules
4691 for (module = conf.modules; module; module = next) {
4692 char *p;
4693 for (p = module; *p && *p != ':'; p++);
4694 next = *p ? p + 1 : NULL;
4695 *p = '\0';
4696
4697 m = fuse_get_module(module);
4698 if (m)
4699 print_module_help(module, &m->factory);
4700 }
4701 }
4702
4703
4704
4705 static int fuse_init_intr_signal(int signum, int *installed)
4706 {
4707 struct sigaction old_sa;
4708
4709 if (sigaction(signum, NULL, &old_sa) == -1) {
4710 perror("fuse: cannot get old signal handler");
4711 return -1;
4712 }
4713
4714 if (old_sa.sa_handler == SIG_DFL) {
4715 struct sigaction sa;
4716
4717 memset(&sa, 0, sizeof(struct sigaction));
4718 sa.sa_handler = fuse_intr_sighandler;
4719 sigemptyset(&sa.sa_mask);
4720
4721 if (sigaction(signum, &sa, NULL) == -1) {
4722 perror("fuse: cannot set interrupt signal handler");
4723 return -1;
4724 }
4725 *installed = 1;
4726 }
4727 return 0;
4728 }
4729
4730 static void fuse_restore_intr_signal(int signum)
4731 {
4732 struct sigaction sa;
4733
4734 memset(&sa, 0, sizeof(struct sigaction));
4735 sa.sa_handler = SIG_DFL;
4736 sigaction(signum, &sa, NULL);
4737 }
4738
4739
4740 static int fuse_push_module(struct fuse *f, const char *module,
4741 struct fuse_args *args)
4742 {
4743 struct fuse_fs *fs[2] = { f->fs, NULL };
4744 struct fuse_fs *newfs;
4745 struct fuse_module *m = fuse_get_module(module);
4746
4747 if (!m)
4748 return -1;
4749
4750 newfs = m->factory(args, fs);
4751 if (!newfs) {
4752 fuse_put_module(m);
4753 return -1;
4754 }
4755 newfs->m = m;
4756 f->fs = newfs;
4757 return 0;
4758 }
4759
4760 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
4761 void *user_data)
4762 {
4763 struct fuse_fs *fs;
4764
4765 if (sizeof(struct fuse_operations) < op_size) {
4766 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
4767 op_size = sizeof(struct fuse_operations);
4768 }
4769
4770 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
4771 if (!fs) {
4772 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
4773 return NULL;
4774 }
4775
4776 fs->user_data = user_data;
4777 if (op)
4778 memcpy(&fs->op, op, op_size);
4779 return fs;
4780 }
4781
4782 static int node_table_init(struct node_table *t)
4783 {
4784 t->size = NODE_TABLE_MIN_SIZE;
4785 t->array = (struct node **) calloc(1, sizeof(struct node *) * t->size);
4786 if (t->array == NULL) {
4787 fprintf(stderr, "fuse: memory allocation failed\n");
4788 return -1;
4789 }
4790 t->use = 0;
4791 t->split = 0;
4792
4793 return 0;
4794 }
4795
4796 static void *fuse_prune_nodes(void *fuse)
4797 {
4798 struct fuse *f = fuse;
4799 int sleep_time;
4800
4801 while(1) {
4802 sleep_time = fuse_clean_cache(f);
4803 sleep(sleep_time);
4804 }
4805 return NULL;
4806 }
4807
4808 int fuse_start_cleanup_thread(struct fuse *f)
4809 {
4810 if (lru_enabled(f))
4811 return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4812
4813 return 0;
4814 }
4815
4816 void fuse_stop_cleanup_thread(struct fuse *f)
4817 {
4818 if (lru_enabled(f)) {
4819 pthread_mutex_lock(&f->lock);
4820 pthread_cancel(f->prune_thread);
4821 pthread_mutex_unlock(&f->lock);
4822 pthread_join(f->prune_thread, NULL);
4823 }
4824 }
4825
4826
4827 FUSE_SYMVER(".symver fuse_new_31,fuse_new@@FUSE_3.1");
4828 struct fuse *fuse_new_31(struct fuse_args *args,
4829 const struct fuse_operations *op,
4830 size_t op_size, void *user_data)
4831 {
4832 struct fuse *f;
4833 struct node *root;
4834 struct fuse_fs *fs;
4835 struct fuse_lowlevel_ops llop = fuse_path_ops;
4836
4837 f = (struct fuse *) calloc(1, sizeof(struct fuse));
4838 if (f == NULL) {
4839 fprintf(stderr, "fuse: failed to allocate fuse object\n");
4840 goto out;
4841 }
4842
4843 f->conf.entry_timeout = 1.0;
4844 f->conf.attr_timeout = 1.0;
4845 f->conf.negative_timeout = 0.0;
4846 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
4847
4848 /* Parse options */
4849 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
4850 fuse_lib_opt_proc) == -1)
4851 goto out_free;
4852
4853 pthread_mutex_lock(&fuse_context_lock);
4854 static int builtin_modules_registered = 0;
4855 /* Have the builtin modules already been registered? */
4856 if (builtin_modules_registered == 0) {
4857 /* If not, register them. */
4858 fuse_register_module("subdir", fuse_module_subdir_factory, NULL);
4859 #ifdef HAVE_ICONV
4860 fuse_register_module("iconv", fuse_module_iconv_factory, NULL);
4861 #endif
4862 builtin_modules_registered= 1;
4863 }
4864 pthread_mutex_unlock(&fuse_context_lock);
4865
4866 if (fuse_create_context_key() == -1)
4867 goto out_free;
4868
4869 fs = fuse_fs_new(op, op_size, user_data);
4870 if (!fs)
4871 goto out_delete_context_key;
4872
4873 f->fs = fs;
4874
4875 /* Oh f**k, this is ugly! */
4876 if (!fs->op.lock) {
4877 llop.getlk = NULL;
4878 llop.setlk = NULL;
4879 }
4880
4881 f->pagesize = getpagesize();
4882 init_list_head(&f->partial_slabs);
4883 init_list_head(&f->full_slabs);
4884 init_list_head(&f->lru_table);
4885
4886 if (f->conf.modules) {
4887 char *module;
4888 char *next;
4889
4890 for (module = f->conf.modules; module; module = next) {
4891 char *p;
4892 for (p = module; *p && *p != ':'; p++);
4893 next = *p ? p + 1 : NULL;
4894 *p = '\0';
4895 if (module[0] &&
4896 fuse_push_module(f, module, args) == -1)
4897 goto out_free_fs;
4898 }
4899 }
4900
4901 if (!f->conf.ac_attr_timeout_set)
4902 f->conf.ac_attr_timeout = f->conf.attr_timeout;
4903
4904 #if defined(__FreeBSD__) || defined(__NetBSD__)
4905 /*
4906 * In FreeBSD, we always use these settings as inode numbers
4907 * are needed to make getcwd(3) work.
4908 */
4909 f->conf.readdir_ino = 1;
4910 #endif
4911
4912 f->se = fuse_session_new(args, &llop, sizeof(llop), f);
4913 if (f->se == NULL)
4914 goto out_free_fs;
4915
4916 if (f->conf.debug) {
4917 fprintf(stderr, "nullpath_ok: %i\n", f->conf.nullpath_ok);
4918 }
4919
4920 /* Trace topmost layer by default */
4921 f->fs->debug = f->conf.debug;
4922 f->ctr = 0;
4923 f->generation = 0;
4924 if (node_table_init(&f->name_table) == -1)
4925 goto out_free_session;
4926
4927 if (node_table_init(&f->id_table) == -1)
4928 goto out_free_name_table;
4929
4930 fuse_mutex_init(&f->lock);
4931
4932 root = alloc_node(f);
4933 if (root == NULL) {
4934 fprintf(stderr, "fuse: memory allocation failed\n");
4935 goto out_free_id_table;
4936 }
4937 if (lru_enabled(f)) {
4938 struct node_lru *lnode = node_lru(root);
4939 init_list_head(&lnode->lru);
4940 }
4941
4942 strcpy(root->inline_name, "/");
4943 root->name = root->inline_name;
4944
4945 if (f->conf.intr &&
4946 fuse_init_intr_signal(f->conf.intr_signal,
4947 &f->intr_installed) == -1)
4948 goto out_free_root;
4949
4950 root->parent = NULL;
4951 root->nodeid = FUSE_ROOT_ID;
4952 inc_nlookup(root);
4953 hash_id(f, root);
4954
4955 return f;
4956
4957 out_free_root:
4958 free(root);
4959 out_free_id_table:
4960 free(f->id_table.array);
4961 out_free_name_table:
4962 free(f->name_table.array);
4963 out_free_session:
4964 fuse_session_destroy(f->se);
4965 out_free_fs:
4966 if (f->fs->m)
4967 fuse_put_module(f->fs->m);
4968 free(f->fs);
4969 free(f->conf.modules);
4970 out_delete_context_key:
4971 fuse_delete_context_key();
4972 out_free:
4973 free(f);
4974 out:
4975 return NULL;
4976 }
4977
4978 /* Emulates 3.0-style fuse_new(), which processes --help */
4979 struct fuse *fuse_new_30(struct fuse_args *args, const struct fuse_operations *op,
4980 size_t op_size, void *private_data);
4981 FUSE_SYMVER(".symver fuse_new_30,fuse_new@FUSE_3.0");
4982 struct fuse *fuse_new_30(struct fuse_args *args,
4983 const struct fuse_operations *op,
4984 size_t op_size, void *user_data)
4985 {
4986 struct fuse_config conf;
4987
4988 memset(&conf, 0, sizeof(conf));
4989
4990 const struct fuse_opt opts[] = {
4991 FUSE_LIB_OPT("-h", show_help, 1),
4992 FUSE_LIB_OPT("--help", show_help, 1),
4993 FUSE_OPT_END
4994 };
4995
4996 if (fuse_opt_parse(args, &conf, opts,
4997 fuse_lib_opt_proc) == -1)
4998 return NULL;
4999
5000 if (conf.show_help) {
5001 fuse_lib_help(args);
5002 return NULL;
5003 } else
5004 return fuse_new_31(args, op, op_size, user_data);
5005 }
5006
5007 void fuse_destroy(struct fuse *f)
5008 {
5009 size_t i;
5010
5011 if (f->conf.intr && f->intr_installed)
5012 fuse_restore_intr_signal(f->conf.intr_signal);
5013
5014 if (f->fs) {
5015 fuse_create_context(f);
5016
5017 for (i = 0; i < f->id_table.size; i++) {
5018 struct node *node;
5019
5020 for (node = f->id_table.array[i]; node != NULL;
5021 node = node->id_next) {
5022 if (node->is_hidden) {
5023 char *path;
5024 if (try_get_path(f, node->nodeid, NULL, &path, NULL, false) == 0) {
5025 fuse_fs_unlink(f->fs, path);
5026 free(path);
5027 }
5028 }
5029 }
5030 }
5031 }
5032 for (i = 0; i < f->id_table.size; i++) {
5033 struct node *node;
5034 struct node *next;
5035
5036 for (node = f->id_table.array[i]; node != NULL; node = next) {
5037 next = node->id_next;
5038 free_node(f, node);
5039 f->id_table.use--;
5040 }
5041 }
5042 assert(list_empty(&f->partial_slabs));
5043 assert(list_empty(&f->full_slabs));
5044
5045 while (fuse_modules) {
5046 fuse_put_module(fuse_modules);
5047 }
5048 free(f->id_table.array);
5049 free(f->name_table.array);
5050 pthread_mutex_destroy(&f->lock);
5051 fuse_session_destroy(f->se);
5052 free(f->conf.modules);
5053 free(f);
5054 fuse_delete_context_key();
5055 }
5056
5057 int fuse_mount(struct fuse *f, const char *mountpoint) {
5058 return fuse_session_mount(fuse_get_session(f), mountpoint);
5059 }
5060
5061
5062 void fuse_unmount(struct fuse *f) {
5063 return fuse_session_unmount(fuse_get_session(f));
5064 }
5065
5066 int fuse_version(void)
5067 {
5068 return FUSE_VERSION;
5069 }
5070
5071 const char *fuse_pkgversion(void)
5072 {
5073 return PACKAGE_VERSION;
5074 }
fuse_session_destroy
void fuse_session_destroy(struct fuse_session *se)
Definition: fuse_lowlevel.c:2621
fuse_reply_err
int fuse_reply_err(fuse_req_t req, int err)
Definition: fuse_lowlevel.c:312
fuse_bufvec::off
size_t off
Definition: fuse_common.h:679
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:2809
fuse_session_exit
void fuse_session_exit(struct fuse_session *se)
Definition: fuse_lowlevel.c:3037
fuse_conn_info::capable
unsigned capable
Definition: fuse_common.h:381
fuse_file_info::fh
uint64_t fh
Definition: fuse_common.h:72
fuse_session_loop
int fuse_session_loop(struct fuse_session *se)
Definition: fuse_loop.c:19
FUSE_FILL_DIR_PLUS
Definition: fuse.h:64
fuse_conn_info
Definition: fuse_common.h:343
fuse_file_info::writepage
unsigned int writepage
Definition: fuse_common.h:43
fuse_reply_ioctl
int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
Definition: fuse_lowlevel.c:979
fuse_lowlevel_help
void fuse_lowlevel_help(void)
Definition: fuse_lowlevel.c:2611
fuse_file_info::direct_io
unsigned int direct_io
Definition: fuse_common.h:46
FUSE_BUF_IS_FD
Definition: fuse_common.h:555
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_data
int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, enum fuse_buf_copy_flags flags)
Definition: fuse_lowlevel.c:820
fuse_file_info::poll_events
uint32_t poll_events
Definition: fuse_common.h:79
fuse_req_ctx
const struct fuse_ctx * fuse_req_ctx(fuse_req_t req)
Definition: fuse_lowlevel.c:2343
fuse_stop_cleanup_thread
void fuse_stop_cleanup_thread(struct fuse *fuse)
Definition: fuse.c:4816
fuse_session_mount
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
Definition: fuse_lowlevel.c:2903
fuse_loop_config::max_idle_threads
unsigned int max_idle_threads
Definition: fuse_common.h:103
fuse_ctx::umask
mode_t umask
Definition: fuse_lowlevel.h:125
fuse_loop
int fuse_loop(struct fuse *f)
Definition: fuse.c:4516
fuse_fill_dir_flags
fuse_fill_dir_flags
Definition: fuse.h:54
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_lowlevel_notify_poll
int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
Definition: fuse_lowlevel.c:2124
fuse_req_t
struct fuse_req * fuse_req_t
Definition: fuse_lowlevel.h:49
fuse_entry_param::attr
struct stat attr
Definition: fuse_lowlevel.h:91
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_req_userdata
void * fuse_req_userdata(fuse_req_t req)
Definition: fuse_lowlevel.c:2338
FUSE_BUF_SPLICE_MOVE
Definition: fuse_common.h:606
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:2141
fuse_ctx::pid
pid_t pid
Definition: fuse_lowlevel.h:122
fuse_reply_bmap
int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
Definition: fuse_lowlevel.c:881
fuse_file_info::keep_cache
unsigned int keep_cache
Definition: fuse_common.h:51
fuse_entry_param
Definition: fuse_lowlevel.h:59
fuse_readdir_flags
fuse_readdir_flags
Definition: fuse.h:42
FUSE_CAP_EXPORT_SUPPORT
#define FUSE_CAP_EXPORT_SUPPORT
Definition: fuse_common.h:144
fuse_entry_param::ino
fuse_ino_t ino
Definition: fuse_lowlevel.h:67
fuse_file_info::lock_owner
uint64_t lock_owner
Definition: fuse_common.h:75
fuse_reply_xattr
int fuse_reply_xattr(fuse_req_t req, size_t count)
Definition: fuse_lowlevel.c:854
fuse_session_exited
int fuse_session_exited(struct fuse_session *se)
Definition: fuse_lowlevel.c:3048
fuse_reply_entry
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
Definition: fuse_lowlevel.c:399
fuse_lowlevel_ops::getlk
void(* getlk)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock)
Definition: fuse_lowlevel.h:922
fuse_opt_add_arg
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
Definition: fuse_opt.c:54
fuse_file_info
Definition: fuse_common.h:37
fuse_clean_cache
int fuse_clean_cache(struct fuse *fuse)
Definition: fuse.c:4373
fuse_ctx::uid
uid_t uid
Definition: fuse_lowlevel.h:116
fuse_reply_lock
int fuse_reply_lock(fuse_req_t req, const struct flock *lock)
Definition: fuse_lowlevel.c:864
fuse_destroy
void fuse_destroy(struct fuse *f)
Definition: fuse.c:5007
fuse_version
int fuse_version(void)
Definition: fuse.c:5066
fuse_req_interrupted
int fuse_req_interrupted(fuse_req_t req)
Definition: fuse_lowlevel.c:2361
fuse_session_reset
void fuse_session_reset(struct fuse_session *se)
Definition: fuse_lowlevel.c:3042
fuse_reply_none
void fuse_reply_none(fuse_req_t req)
Definition: fuse_lowlevel.c:317
fuse_req_getgroups
int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
Definition: fuse_lowlevel.c:3030
fuse_operations
Definition: fuse.h:299
fuse_file_info::flags
int flags
Definition: fuse_common.h:39
fuse_bufvec
Definition: fuse_common.h:665
fuse_loop_config
Definition: fuse_common.h:86
fuse_bufvec::idx
size_t idx
Definition: fuse_common.h:674
fuse_ctx
Definition: fuse_lowlevel.h:114
fuse_bufvec::count
size_t count
Definition: fuse_common.h:669
fuse_opt.h
FUSE_OPT_KEY
#define FUSE_OPT_KEY(templ, key)
Definition: fuse_opt.h:98
fuse_reply_attr
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
Definition: fuse_lowlevel.c:431
FUSE_CAP_SPLICE_READ
#define FUSE_CAP_SPLICE_READ
Definition: fuse_common.h:177
fuse_session_unmount
void fuse_session_unmount(struct fuse_session *se)
Definition: fuse_lowlevel.c:2958
FUSE_OPT_END
#define FUSE_OPT_END
Definition: fuse_opt.h:104
fuse_buf::flags
enum fuse_buf_flags flags
Definition: fuse_common.h:633
fuse_module_factory_t
struct fuse_fs *(* fuse_module_factory_t)(struct fuse_args *args, struct fuse_fs *fs[])
Definition: fuse.h:1226
fuse_reply_statfs
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
Definition: fuse_lowlevel.c:842
fuse_get_session
struct fuse_session * fuse_get_session(struct fuse *f)
Definition: fuse.c:4459
fuse_file_info::flush
unsigned int flush
Definition: fuse_common.h:56
FUSE_OPT_KEY_KEEP
#define FUSE_OPT_KEY_KEEP
Definition: fuse_opt.h:145
fuse_context::private_data
void * private_data
Definition: fuse.h:791
fuse_invalidate_path
int fuse_invalidate_path(struct fuse *f, const char *path)
Definition: fuse.c:4586
FUSE_READDIR_PLUS
Definition: fuse.h:51
fuse_fs_new
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
Definition: fuse.c:4760
FUSE_ROOT_ID
#define FUSE_ROOT_ID
Definition: fuse_lowlevel.h:43
fuse_start_cleanup_thread
int fuse_start_cleanup_thread(struct fuse *fuse)
Definition: fuse.c:4808
fuse_module
Definition: fuse_i.h:82
FUSE_CAP_FLOCK_LOCKS
#define FUSE_CAP_FLOCK_LOCKS
Definition: fuse_common.h:190
fuse_lib_help
void fuse_lib_help(struct fuse_args *args)
Definition: fuse.c:4650
fuse_ino_t
uint64_t fuse_ino_t
Definition: fuse_lowlevel.h:46
fuse_interrupted
int fuse_interrupted(void)
Definition: fuse.c:4576
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_config::show_help
int show_help
Definition: fuse.h:271
fuse_req_interrupt_func
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, void *data)
Definition: fuse_lowlevel.c:2348
fuse_entry_param::generation
uint64_t generation
Definition: fuse_lowlevel.h:82
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:415
fuse_reply_write
int fuse_reply_write(fuse_req_t req, size_t count)
Definition: fuse_lowlevel.c:460
fuse_buf::mem
void * mem
Definition: fuse_common.h:640
fuse_getgroups
int fuse_getgroups(int size, gid_t list[])
Definition: fuse.c:4567
fuse_config
Definition: fuse.h:93
fuse_mount
int fuse_mount(struct fuse *f, const char *mountpoint)
Definition: fuse.c:5057
FUSE_CAP_POSIX_LOCKS
#define FUSE_CAP_POSIX_LOCKS
Definition: fuse_common.h:128
fuse_reply_open
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
Definition: fuse_lowlevel.c:451
fuse_lowlevel_ops::setlk
void(* setlk)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock, int sleep)
Definition: fuse_lowlevel.h:947
fuse_lowlevel.h
fuse_lowlevel_ops
Definition: fuse_lowlevel.h:175
fuse_bufvec::buf
struct fuse_buf buf[1]
Definition: fuse_common.h:684
fuse_context
Definition: fuse.h:777
fuse_opt
Definition: fuse_opt.h:77
fuse_ctx::gid
gid_t gid
Definition: fuse_lowlevel.h:119
fuse_conn_info::want
unsigned want
Definition: fuse_common.h:389
fuse_unmount
void fuse_unmount(struct fuse *f)
Definition: fuse.c:5062
fuse_args
Definition: fuse_opt.h:109
fuse_loop_mt_31
int fuse_loop_mt_31(struct fuse *f, int clone_fd)
Definition: fuse.c:4544
fuse_pkgversion
const char * fuse_pkgversion(void)
Definition: fuse.c:5071
FUSE_ARGS_INIT
#define FUSE_ARGS_INIT(argc, argv)
Definition: fuse_opt.h:123
fuse_buf_size
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
Definition: buffer.c:22
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_buf::size
size_t size
Definition: fuse_common.h:628
fuse_get_context
struct fuse_context * fuse_get_context(void)
Definition: fuse.c:4557
fuse_entry_param::entry_timeout
double entry_timeout
Definition: fuse_lowlevel.h:103
fuse_entry_param::attr_timeout
double attr_timeout
Definition: fuse_lowlevel.h:97
fuse_loop_config::clone_fd
int clone_fd
Definition: fuse_common.h:91
fuse_buf
Definition: fuse_common.h:624
fuse_reply_readlink
int fuse_reply_readlink(fuse_req_t req, const char *link)
Definition: fuse_lowlevel.c:446
fuse_reply_buf
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
Definition: fuse_lowlevel.c:470
fuse_lowlevel_ops::init
void(* init)(void *userdata, struct fuse_conn_info *conn)
Definition: fuse_lowlevel.h:192
fuse_reply_poll
int fuse_reply_poll(fuse_req_t req, unsigned revents)
Definition: fuse_lowlevel.c:1024
fuse_exit
void fuse_exit(struct fuse *f)
Definition: fuse.c:4552