libfuse: lib/fuse.c Source File

libfuse

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