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