libfuse

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