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