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 LGPL2.txt
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
1510#ifdef HAVE_STATX
1511static void set_statx(struct fuse *f, fuse_ino_t nodeid, struct statx *stxbuf)
1512{
1513 if (!f->conf.use_ino)
1514 stxbuf->stx_ino = nodeid;
1515 if (f->conf.set_mode) {
1516 if (f->conf.dmask && S_ISDIR(stxbuf->stx_mode))
1517 stxbuf->stx_mode = (stxbuf->stx_mode & S_IFMT) |
1518 (0777 & ~f->conf.dmask);
1519 else if (f->conf.fmask)
1520 stxbuf->stx_mode = (stxbuf->stx_mode & S_IFMT) |
1521 (0777 & ~f->conf.fmask);
1522 else
1523 stxbuf->stx_mode = (stxbuf->stx_mode & S_IFMT) |
1524 (0777 & ~f->conf.umask);
1525 }
1526 if (f->conf.set_uid)
1527 stxbuf->stx_uid = f->conf.uid;
1528 if (f->conf.set_gid)
1529 stxbuf->stx_gid = f->conf.gid;
1530}
1531#endif
1532
1533static struct fuse *req_fuse(fuse_req_t req)
1534{
1535 return (struct fuse *) fuse_req_userdata(req);
1536}
1537
1538static void fuse_intr_sighandler(int sig)
1539{
1540 (void) sig;
1541 /* Nothing to do */
1542}
1543
1544struct fuse_intr_data {
1545 pthread_t id;
1546 pthread_cond_t cond;
1547 int finished;
1548};
1549
1550static void fuse_interrupt(fuse_req_t req, void *d_)
1551{
1552 struct fuse_intr_data *d = d_;
1553 struct fuse *f = req_fuse(req);
1554
1555 if (d->id == pthread_self())
1556 return;
1557
1558 pthread_mutex_lock(&f->lock);
1559 while (!d->finished) {
1560 struct timeval now;
1561 struct timespec timeout;
1562
1563 pthread_kill(d->id, f->conf.intr_signal);
1564 gettimeofday(&now, NULL);
1565 timeout.tv_sec = now.tv_sec + 1;
1566 timeout.tv_nsec = now.tv_usec * 1000;
1567 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
1568 }
1569 pthread_mutex_unlock(&f->lock);
1570}
1571
1572static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
1573 struct fuse_intr_data *d)
1574{
1575 pthread_mutex_lock(&f->lock);
1576 d->finished = 1;
1577 pthread_cond_broadcast(&d->cond);
1578 pthread_mutex_unlock(&f->lock);
1579 fuse_req_interrupt_func(req, NULL, NULL);
1580 pthread_cond_destroy(&d->cond);
1581}
1582
1583static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
1584{
1585 d->id = pthread_self();
1586 pthread_cond_init(&d->cond, NULL);
1587 d->finished = 0;
1588 fuse_req_interrupt_func(req, fuse_interrupt, d);
1589}
1590
1591static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
1592 struct fuse_intr_data *d)
1593{
1594 if (f->conf.intr)
1595 fuse_do_finish_interrupt(f, req, d);
1596}
1597
1598static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
1599 struct fuse_intr_data *d)
1600{
1601 if (f->conf.intr)
1602 fuse_do_prepare_interrupt(req, d);
1603}
1604
1605static const char* file_info_string(struct fuse_file_info *fi,
1606 char* buf, size_t len)
1607{
1608 if(fi == NULL)
1609 return "NULL";
1610 snprintf(buf, len, "%llu", (unsigned long long) fi->fh);
1611 return buf;
1612}
1613
1614int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf,
1615 struct fuse_file_info *fi)
1616{
1617 fuse_get_context()->private_data = fs->user_data;
1618 if (!fs->op.getattr)
1619 return -ENOSYS;
1620
1621 if (fs->debug) {
1622 char buf[10];
1623
1624 fuse_log(FUSE_LOG_DEBUG, "getattr[%s] %s\n",
1625 file_info_string(fi, buf, sizeof(buf)),
1626 path);
1627 }
1628 return fs->op.getattr(path, buf, fi);
1629}
1630
1631int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
1632 const char *newpath, unsigned int flags)
1633{
1634 fuse_get_context()->private_data = fs->user_data;
1635 if (!fs->op.rename)
1636 return -ENOSYS;
1637 if (fs->debug)
1638 fuse_log(FUSE_LOG_DEBUG, "rename %s %s 0x%x\n", oldpath, newpath,
1639 flags);
1640
1641 return fs->op.rename(oldpath, newpath, flags);
1642}
1643
1644int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
1645{
1646 fuse_get_context()->private_data = fs->user_data;
1647 if (!fs->op.unlink)
1648 return -ENOSYS;
1649 if (fs->debug)
1650 fuse_log(FUSE_LOG_DEBUG, "unlink %s\n", path);
1651
1652 return fs->op.unlink(path);
1653}
1654
1655int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
1656{
1657 fuse_get_context()->private_data = fs->user_data;
1658 if (!fs->op.rmdir)
1659 return -ENOSYS;
1660 if (fs->debug)
1661 fuse_log(FUSE_LOG_DEBUG, "rmdir %s\n", path);
1662
1663 return fs->op.rmdir(path);
1664}
1665
1666int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
1667{
1668 fuse_get_context()->private_data = fs->user_data;
1669 if (!fs->op.symlink)
1670 return -ENOSYS;
1671 if (fs->debug)
1672 fuse_log(FUSE_LOG_DEBUG, "symlink %s %s\n", linkname, path);
1673
1674 return fs->op.symlink(linkname, path);
1675}
1676
1677int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
1678{
1679 fuse_get_context()->private_data = fs->user_data;
1680 if (!fs->op.link)
1681 return -ENOSYS;
1682 if (fs->debug)
1683 fuse_log(FUSE_LOG_DEBUG, "link %s %s\n", oldpath, newpath);
1684
1685 return fs->op.link(oldpath, newpath);
1686}
1687
1688int fuse_fs_release(struct fuse_fs *fs, const char *path,
1689 struct fuse_file_info *fi)
1690{
1691 fuse_get_context()->private_data = fs->user_data;
1692 if (!fs->op.release)
1693 return 0;
1694
1695 if (fs->debug)
1696 fuse_log(FUSE_LOG_DEBUG, "release%s[%llu] flags: 0x%x\n",
1697 fi->flush ? "+flush" : "",
1698 (unsigned long long) fi->fh, fi->flags);
1699
1700 return fs->op.release(path, fi);
1701}
1702
1703int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
1704 struct fuse_file_info *fi)
1705{
1706 int err;
1707
1708 fuse_get_context()->private_data = fs->user_data;
1709 if (!fs->op.opendir)
1710 return 0;
1711
1712 if (fs->debug)
1713 fuse_log(FUSE_LOG_DEBUG, "opendir flags: 0x%x %s\n", fi->flags,
1714 path);
1715
1716 err = fs->op.opendir(path, fi);
1717
1718 if (fs->debug && !err)
1719 fuse_log(FUSE_LOG_DEBUG, " opendir[%llu] flags: 0x%x %s\n",
1720 (unsigned long long) fi->fh, fi->flags, path);
1721
1722 return err;
1723}
1724
1725int fuse_fs_open(struct fuse_fs *fs, const char *path,
1726 struct fuse_file_info *fi)
1727{
1728 int err;
1729
1730 fuse_get_context()->private_data = fs->user_data;
1731 if (!fs->op.open)
1732 return 0;
1733
1734 if (fs->debug)
1735 fuse_log(FUSE_LOG_DEBUG, "open flags: 0x%x %s\n", fi->flags,
1736 path);
1737
1738 err = fs->op.open(path, fi);
1739
1740 if (fs->debug && !err)
1741 fuse_log(FUSE_LOG_DEBUG, " open[%llu] flags: 0x%x %s\n",
1742 (unsigned long long) fi->fh, fi->flags, path);
1743
1744 return err;
1745}
1746
1747static void fuse_free_buf(struct fuse_bufvec *buf)
1748{
1749 if (buf != NULL) {
1750 size_t i;
1751
1752 for (i = 0; i < buf->count; i++)
1753 if (!(buf->buf[i].flags & FUSE_BUF_IS_FD))
1754 free(buf->buf[i].mem);
1755 free(buf);
1756 }
1757}
1758
1759int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
1760 struct fuse_bufvec **bufp, size_t size, off_t off,
1761 struct fuse_file_info *fi)
1762{
1763 int res;
1764
1765 fuse_get_context()->private_data = fs->user_data;
1766 if (!fs->op.read && !fs->op.read_buf)
1767 return -ENOSYS;
1768
1769 if (fs->debug)
1770 fuse_log(FUSE_LOG_DEBUG,
1771 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1772 (unsigned long long) fi->fh,
1773 size, (unsigned long long) off, fi->flags);
1774
1775 if (fs->op.read_buf) {
1776 res = fs->op.read_buf(path, bufp, size, off, fi);
1777 } else {
1778 struct fuse_bufvec *buf;
1779 void *mem;
1780
1781 buf = malloc(sizeof(struct fuse_bufvec));
1782 if (buf == NULL)
1783 return -ENOMEM;
1784
1785 mem = malloc(size);
1786 if (mem == NULL) {
1787 free(buf);
1788 return -ENOMEM;
1789 }
1790 *buf = FUSE_BUFVEC_INIT(size);
1791 buf->buf[0].mem = mem;
1792 *bufp = buf;
1793
1794 res = fs->op.read(path, mem, size, off, fi);
1795 if (res >= 0)
1796 buf->buf[0].size = res;
1797 }
1798
1799 if (fs->debug && res >= 0)
1800 fuse_log(FUSE_LOG_DEBUG, " read[%llu] %zu bytes from %llu\n",
1801 (unsigned long long) fi->fh,
1802 fuse_buf_size(*bufp),
1803 (unsigned long long) off);
1804 if (res >= 0 && fuse_buf_size(*bufp) > size)
1805 fuse_log(FUSE_LOG_ERR, "fuse: read too many bytes\n");
1806
1807 if (res < 0)
1808 return res;
1809
1810 return 0;
1811}
1812
1813int fuse_fs_read(struct fuse_fs *fs, const char *path, char *mem, size_t size,
1814 off_t off, struct fuse_file_info *fi)
1815{
1816 int res;
1817
1818 fuse_get_context()->private_data = fs->user_data;
1819 if (!fs->op.read && !fs->op.read_buf)
1820 return -ENOSYS;
1821
1822 if (fs->debug)
1823 fuse_log(FUSE_LOG_DEBUG,
1824 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1825 (unsigned long long) fi->fh,
1826 size, (unsigned long long) off, fi->flags);
1827
1828 if (fs->op.read_buf) {
1829 struct fuse_bufvec *buf = NULL;
1830
1831 res = fs->op.read_buf(path, &buf, size, off, fi);
1832 if (res == 0) {
1833 struct fuse_bufvec dst = FUSE_BUFVEC_INIT(size);
1834
1835 dst.buf[0].mem = mem;
1836 res = fuse_buf_copy(&dst, buf, 0);
1837 }
1838 fuse_free_buf(buf);
1839 } else {
1840 res = fs->op.read(path, mem, size, off, fi);
1841 }
1842
1843 if (fs->debug && res >= 0)
1844 fuse_log(FUSE_LOG_DEBUG, " read[%llu] %u bytes from %llu\n",
1845 (unsigned long long) fi->fh,
1846 res,
1847 (unsigned long long) off);
1848 if (res >= 0 && res > (int) size)
1849 fuse_log(FUSE_LOG_ERR, "fuse: read too many bytes\n");
1850
1851 return res;
1852}
1853
1854int fuse_fs_write_buf(struct fuse_fs *fs, const char *path,
1855 struct fuse_bufvec *buf, off_t off,
1856 struct fuse_file_info *fi)
1857{
1858 int res;
1859 size_t size;
1860
1861 fuse_get_context()->private_data = fs->user_data;
1862 if (!fs->op.write_buf && !fs->op.write)
1863 return -ENOSYS;
1864
1865 size = fuse_buf_size(buf);
1866 assert(buf->idx == 0 && buf->off == 0);
1867 if (fs->debug)
1868 fuse_log(FUSE_LOG_DEBUG,
1869 "write%s[%llu] %zu bytes to %llu flags: 0x%x\n",
1870 fi->writepage ? "page" : "",
1871 (unsigned long long) fi->fh,
1872 size,
1873 (unsigned long long) off,
1874 fi->flags);
1875
1876 if (fs->op.write_buf) {
1877 res = fs->op.write_buf(path, buf, off, fi);
1878 } else {
1879 void *mem = NULL;
1880 struct fuse_buf *flatbuf;
1881 struct fuse_bufvec tmp = FUSE_BUFVEC_INIT(size);
1882
1883 if (buf->count == 1 &&
1884 !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
1885 flatbuf = &buf->buf[0];
1886 } else {
1887 res = -ENOMEM;
1888 mem = malloc(size);
1889 if (mem == NULL)
1890 goto out;
1891
1892 tmp.buf[0].mem = mem;
1893 res = fuse_buf_copy(&tmp, buf, 0);
1894 if (res <= 0)
1895 goto out_free;
1896
1897 tmp.buf[0].size = res;
1898 flatbuf = &tmp.buf[0];
1899 }
1900
1901 res = fs->op.write(path, flatbuf->mem, flatbuf->size,
1902 off, fi);
1903out_free:
1904 free(mem);
1905 }
1906out:
1907 if (fs->debug && res >= 0)
1908 fuse_log(FUSE_LOG_DEBUG, " write%s[%llu] %u bytes to %llu\n",
1909 fi->writepage ? "page" : "",
1910 (unsigned long long) fi->fh, res,
1911 (unsigned long long) off);
1912 if (res > (int) size)
1913 fuse_log(FUSE_LOG_ERR, "fuse: wrote too many bytes\n");
1914
1915 return res;
1916}
1917
1918int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *mem,
1919 size_t size, off_t off, struct fuse_file_info *fi)
1920{
1921 struct fuse_bufvec bufv = FUSE_BUFVEC_INIT(size);
1922
1923 bufv.buf[0].mem = (void *) mem;
1924
1925 return fuse_fs_write_buf(fs, path, &bufv, off, fi);
1926}
1927
1928int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
1929 struct fuse_file_info *fi)
1930{
1931 fuse_get_context()->private_data = fs->user_data;
1932 if (!fs->op.fsync)
1933 return -ENOSYS;
1934
1935 if (fs->debug)
1936 fuse_log(FUSE_LOG_DEBUG, "fsync[%llu] datasync: %i\n",
1937 (unsigned long long) fi->fh, datasync);
1938
1939 return fs->op.fsync(path, datasync, fi);
1940}
1941
1942int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
1943 struct fuse_file_info *fi)
1944{
1945 fuse_get_context()->private_data = fs->user_data;
1946 if (!fs->op.fsyncdir)
1947 return -ENOSYS;
1948
1949 if (fs->debug)
1950 fuse_log(FUSE_LOG_DEBUG, "fsyncdir[%llu] datasync: %i\n",
1951 (unsigned long long) fi->fh, datasync);
1952
1953 return fs->op.fsyncdir(path, datasync, fi);
1954}
1955
1956int fuse_fs_flush(struct fuse_fs *fs, const char *path,
1957 struct fuse_file_info *fi)
1958{
1959 fuse_get_context()->private_data = fs->user_data;
1960 if (!fs->op.flush)
1961 return -ENOSYS;
1962 if (fs->debug)
1963 fuse_log(FUSE_LOG_DEBUG, "flush[%llu]\n",
1964 (unsigned long long) fi->fh);
1965
1966 return fs->op.flush(path, fi);
1967}
1968
1969int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
1970{
1971 fuse_get_context()->private_data = fs->user_data;
1972 if (fs->op.statfs) {
1973 if (fs->debug)
1974 fuse_log(FUSE_LOG_DEBUG, "statfs %s\n", path);
1975
1976 return fs->op.statfs(path, buf);
1977 } else {
1978 buf->f_namemax = 255;
1979 buf->f_bsize = 512;
1980 return 0;
1981 }
1982}
1983
1984int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
1985 struct fuse_file_info *fi)
1986{
1987 fuse_get_context()->private_data = fs->user_data;
1988 if (!fs->op.releasedir)
1989 return 0;
1990
1991 if (fs->debug)
1992 fuse_log(FUSE_LOG_DEBUG, "releasedir[%llu] flags: 0x%x\n",
1993 (unsigned long long) fi->fh, fi->flags);
1994
1995 return fs->op.releasedir(path, fi);
1996}
1997
1998int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
1999 fuse_fill_dir_t filler, off_t off,
2000 struct fuse_file_info *fi,
2001 enum fuse_readdir_flags flags)
2002{
2003 fuse_get_context()->private_data = fs->user_data;
2004 if (!fs->op.readdir)
2005 return -ENOSYS;
2006 if (fs->debug) {
2007 fuse_log(FUSE_LOG_DEBUG, "readdir%s[%llu] from %llu\n",
2008 (flags & FUSE_READDIR_PLUS) ? "plus" : "",
2009 (unsigned long long) fi->fh,
2010 (unsigned long long) off);
2011 }
2012
2013 return fs->op.readdir(path, buf, filler, off, fi, flags);
2014}
2015
2016int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
2017 struct fuse_file_info *fi)
2018{
2019 int err;
2020
2021 fuse_get_context()->private_data = fs->user_data;
2022 if (!fs->op.create)
2023 return -ENOSYS;
2024
2025 if (fs->debug)
2026 fuse_log(FUSE_LOG_DEBUG,
2027 "create flags: 0x%x %s 0%o umask=0%03o\n",
2028 fi->flags, path, mode,
2029 fuse_get_context()->umask);
2030
2031 err = fs->op.create(path, mode, fi);
2032
2033 if (fs->debug && !err)
2034 fuse_log(FUSE_LOG_DEBUG, " create[%llu] flags: 0x%x %s\n",
2035 (unsigned long long) fi->fh, fi->flags, path);
2036
2037 return err;
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 return -ENOSYS;
2046
2047 if (fs->debug)
2048 fuse_log(FUSE_LOG_DEBUG, "lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
2049 (unsigned long long) fi->fh,
2050 (cmd == F_GETLK ? "F_GETLK" :
2051 (cmd == F_SETLK ? "F_SETLK" :
2052 (cmd == F_SETLKW ? "F_SETLKW" : "???"))),
2053 (lock->l_type == F_RDLCK ? "F_RDLCK" :
2054 (lock->l_type == F_WRLCK ? "F_WRLCK" :
2055 (lock->l_type == F_UNLCK ? "F_UNLCK" :
2056 "???"))),
2057 (unsigned long long) lock->l_start,
2058 (unsigned long long) lock->l_len,
2059 (unsigned long long) lock->l_pid);
2060
2061 return fs->op.lock(path, fi, cmd, lock);
2062}
2063
2064int fuse_fs_flock(struct fuse_fs *fs, const char *path,
2065 struct fuse_file_info *fi, int op)
2066{
2067 fuse_get_context()->private_data = fs->user_data;
2068 if (!fs->op.flock)
2069 return -ENOSYS;
2070
2071 if (fs->debug) {
2072 int xop = op & ~LOCK_NB;
2073
2074 fuse_log(FUSE_LOG_DEBUG, "lock[%llu] %s%s\n",
2075 (unsigned long long) fi->fh,
2076 xop == LOCK_SH ? "LOCK_SH" :
2077 (xop == LOCK_EX ? "LOCK_EX" :
2078 (xop == LOCK_UN ? "LOCK_UN" : "???")),
2079 (op & LOCK_NB) ? "|LOCK_NB" : "");
2080 }
2081 return fs->op.flock(path, fi, op);
2082}
2083
2084int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid,
2085 gid_t gid, struct fuse_file_info *fi)
2086{
2087 fuse_get_context()->private_data = fs->user_data;
2088 if (!fs->op.chown)
2089 return -ENOSYS;
2090 if (fs->debug) {
2091 char buf[10];
2092
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}
2099
2100int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size,
2101 struct fuse_file_info *fi)
2102{
2103 fuse_get_context()->private_data = fs->user_data;
2104 if (!fs->op.truncate)
2105 return -ENOSYS;
2106 if (fs->debug) {
2107 char buf[10];
2108
2109 fuse_log(FUSE_LOG_DEBUG, "truncate[%s] %llu\n",
2110 file_info_string(fi, buf, sizeof(buf)),
2111 (unsigned long long) size);
2112 }
2113 return fs->op.truncate(path, size, fi);
2114}
2115
2116int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
2117 const struct timespec tv[2], struct fuse_file_info *fi)
2118{
2119 fuse_get_context()->private_data = fs->user_data;
2120 if (!fs->op.utimens)
2121 return -ENOSYS;
2122 if (fs->debug) {
2123 char buf[10];
2124
2125 fuse_log(FUSE_LOG_DEBUG, "utimens[%s] %s %jd.%09ld %jd.%09ld\n",
2126 file_info_string(fi, buf, sizeof(buf)),
2127 path, (intmax_t)tv[0].tv_sec, tv[0].tv_nsec,
2128 (intmax_t)tv[1].tv_sec, tv[1].tv_nsec);
2129 }
2130 return fs->op.utimens(path, tv, fi);
2131}
2132
2133int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
2134{
2135 fuse_get_context()->private_data = fs->user_data;
2136 if (!fs->op.access)
2137 return -ENOSYS;
2138 if (fs->debug)
2139 fuse_log(FUSE_LOG_DEBUG, "access %s 0%o\n", path, mask);
2140
2141 return fs->op.access(path, mask);
2142}
2143
2144int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
2145 size_t len)
2146{
2147 fuse_get_context()->private_data = fs->user_data;
2148 if (!fs->op.readlink)
2149 return -ENOSYS;
2150 if (fs->debug)
2151 fuse_log(FUSE_LOG_DEBUG, "readlink %s %lu\n", path,
2152 (unsigned long) len);
2153
2154 return fs->op.readlink(path, buf, len);
2155}
2156
2157int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
2158 dev_t rdev)
2159{
2160 fuse_get_context()->private_data = fs->user_data;
2161 if (!fs->op.mknod)
2162 return -ENOSYS;
2163 if (fs->debug)
2164 fuse_log(FUSE_LOG_DEBUG, "mknod %s 0%o 0x%llx umask=0%03o\n",
2165 path, mode, (unsigned long long) rdev,
2166 fuse_get_context()->umask);
2167
2168 return fs->op.mknod(path, mode, rdev);
2169}
2170
2171int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
2172{
2173 fuse_get_context()->private_data = fs->user_data;
2174 if (!fs->op.mkdir)
2175 return -ENOSYS;
2176 if (fs->debug)
2177 fuse_log(FUSE_LOG_DEBUG, "mkdir %s 0%o umask=0%03o\n",
2178 path, mode, fuse_get_context()->umask);
2179
2180 return fs->op.mkdir(path, mode);
2181}
2182
2183int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
2184 const char *value, size_t size, int flags)
2185{
2186 fuse_get_context()->private_data = fs->user_data;
2187 if (!fs->op.setxattr)
2188 return -ENOSYS;
2189 if (fs->debug)
2190 fuse_log(FUSE_LOG_DEBUG, "setxattr %s %s %lu 0x%x\n",
2191 path, name, (unsigned long) size, flags);
2192
2193 return fs->op.setxattr(path, name, value, size, flags);
2194}
2195
2196int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
2197 char *value, size_t size)
2198{
2199 fuse_get_context()->private_data = fs->user_data;
2200 if (!fs->op.getxattr)
2201 return -ENOSYS;
2202 if (fs->debug)
2203 fuse_log(FUSE_LOG_DEBUG, "getxattr %s %s %lu\n",
2204 path, name, (unsigned long) size);
2205
2206 return fs->op.getxattr(path, name, value, size);
2207}
2208
2209int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
2210 size_t size)
2211{
2212 fuse_get_context()->private_data = fs->user_data;
2213 if (!fs->op.listxattr)
2214 return -ENOSYS;
2215 if (fs->debug)
2216 fuse_log(FUSE_LOG_DEBUG, "listxattr %s %lu\n",
2217 path, (unsigned long) size);
2218
2219 return fs->op.listxattr(path, list, size);
2220}
2221
2222int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
2223 uint64_t *idx)
2224{
2225 fuse_get_context()->private_data = fs->user_data;
2226 if (!fs->op.bmap)
2227 return -ENOSYS;
2228 if (fs->debug)
2229 fuse_log(FUSE_LOG_DEBUG, "bmap %s blocksize: %lu index: %llu\n",
2230 path, (unsigned long) blocksize,
2231 (unsigned long long) *idx);
2232
2233 return fs->op.bmap(path, blocksize, idx);
2234}
2235
2236int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
2237{
2238 fuse_get_context()->private_data = fs->user_data;
2239 if (!fs->op.removexattr)
2240 return -ENOSYS;
2241 if (fs->debug)
2242 fuse_log(FUSE_LOG_DEBUG, "removexattr %s %s\n", path, name);
2243
2244 return fs->op.removexattr(path, name);
2245}
2246
2247int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, unsigned int cmd,
2248 void *arg, struct fuse_file_info *fi, unsigned int flags,
2249 void *data)
2250{
2251 fuse_get_context()->private_data = fs->user_data;
2252 if (!fs->op.ioctl)
2253 return -ENOSYS;
2254 if (fs->debug)
2255 fuse_log(FUSE_LOG_DEBUG, "ioctl[%llu] 0x%x flags: 0x%x\n",
2256 (unsigned long long) fi->fh, cmd, flags);
2257
2258 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2259}
2260
2261int fuse_fs_poll(struct fuse_fs *fs, const char *path,
2262 struct fuse_file_info *fi, struct fuse_pollhandle *ph,
2263 unsigned *reventsp)
2264{
2265 int res;
2266
2267 fuse_get_context()->private_data = fs->user_data;
2268 if (!fs->op.poll)
2269 return -ENOSYS;
2270 if (fs->debug)
2271 fuse_log(FUSE_LOG_DEBUG, "poll[%llu] ph: %p, events 0x%x\n",
2272 (unsigned long long) fi->fh, ph,
2273 fi->poll_events);
2274
2275 res = fs->op.poll(path, fi, ph, reventsp);
2276
2277 if (fs->debug && !res)
2278 fuse_log(FUSE_LOG_DEBUG, " poll[%llu] revents: 0x%x\n",
2279 (unsigned long long) fi->fh, *reventsp);
2280
2281 return res;
2282}
2283
2284int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
2285 off_t offset, off_t length, struct fuse_file_info *fi)
2286{
2287 fuse_get_context()->private_data = fs->user_data;
2288 if (!fs->op.fallocate)
2289 return -ENOSYS;
2290 if (fs->debug)
2291 fuse_log(FUSE_LOG_DEBUG, "fallocate %s mode %x, offset: %llu, length: %llu\n",
2292 path,
2293 mode,
2294 (unsigned long long) offset,
2295 (unsigned long long) length);
2296
2297 return fs->op.fallocate(path, mode, offset, length, fi);
2298}
2299
2300ssize_t fuse_fs_copy_file_range(struct fuse_fs *fs, const char *path_in,
2301 struct fuse_file_info *fi_in, off_t off_in,
2302 const char *path_out,
2303 struct fuse_file_info *fi_out, off_t off_out,
2304 size_t len, int flags)
2305{
2306 fuse_get_context()->private_data = fs->user_data;
2307 if (!fs->op.copy_file_range)
2308 return -ENOSYS;
2309 if (fs->debug)
2310 fuse_log(FUSE_LOG_DEBUG, "copy_file_range from %s:%llu to "
2311 "%s:%llu, length: %llu\n",
2312 path_in,
2313 (unsigned long long) off_in,
2314 path_out,
2315 (unsigned long long) off_out,
2316 (unsigned long long) len);
2317
2318 return fs->op.copy_file_range(path_in, fi_in, off_in, path_out,
2319 fi_out, off_out, len, flags);
2320}
2321
2322off_t fuse_fs_lseek(struct fuse_fs *fs, const char *path, off_t off, int whence,
2323 struct fuse_file_info *fi)
2324{
2325 fuse_get_context()->private_data = fs->user_data;
2326 if (!fs->op.lseek)
2327 return -ENOSYS;
2328 if (fs->debug) {
2329 char buf[10];
2330
2331 fuse_log(FUSE_LOG_DEBUG, "lseek[%s] %llu %d\n",
2332 file_info_string(fi, buf, sizeof(buf)),
2333 (unsigned long long) off, whence);
2334 }
2335 return fs->op.lseek(path, off, whence, fi);
2336}
2337
2338#ifdef HAVE_STATX
2339int fuse_fs_statx(struct fuse_fs *fs, const char *path, int flags, int mask,
2340 struct statx *stxbuf, struct fuse_file_info *fi)
2341{
2342 fuse_get_context()->private_data = fs->user_data;
2343 if (fs->op.statx) {
2344 if (fs->debug) {
2345 char buf[10];
2346
2347 fuse_log(FUSE_LOG_DEBUG, "statx[%s] %s %d %d\n",
2348 file_info_string(fi, buf, sizeof(buf)), path,
2349 flags, mask);
2350 }
2351 return fs->op.statx(path, flags, mask, stxbuf, fi);
2352 }
2353
2354 return -ENOSYS;
2355}
2356#else
2357int fuse_fs_statx(struct fuse_fs *fs, const char *path, int flags, int mask,
2358 struct statx *stxbuf, struct fuse_file_info *fi)
2359{
2360 (void)fs;
2361 (void)path;
2362 (void)flags;
2363 (void)mask;
2364 (void)stxbuf;
2365 (void)fi;
2366
2367 return -ENOSYS;
2368}
2369#endif
2370
2371static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
2372{
2373 struct node *node;
2374 int isopen = 0;
2375 pthread_mutex_lock(&f->lock);
2376 node = lookup_node(f, dir, name);
2377 if (node && node->open_count > 0)
2378 isopen = 1;
2379 pthread_mutex_unlock(&f->lock);
2380 return isopen;
2381}
2382
2383static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
2384 char *newname, size_t bufsize)
2385{
2386 struct stat buf;
2387 struct node *node;
2388 struct node *newnode;
2389 char *newpath;
2390 int res;
2391 int failctr = 10;
2392
2393 do {
2394 pthread_mutex_lock(&f->lock);
2395 node = lookup_node(f, dir, oldname);
2396 if (node == NULL) {
2397 pthread_mutex_unlock(&f->lock);
2398 return NULL;
2399 }
2400 do {
2401 f->hidectr ++;
2402 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
2403 (unsigned int) node->nodeid, f->hidectr);
2404 newnode = lookup_node(f, dir, newname);
2405 } while(newnode);
2406
2407 res = try_get_path(f, dir, newname, &newpath, NULL, false);
2408 pthread_mutex_unlock(&f->lock);
2409 if (res)
2410 break;
2411
2412 memset(&buf, 0, sizeof(buf));
2413 res = fuse_fs_getattr(f->fs, newpath, &buf, NULL);
2414 if (res == -ENOENT)
2415 break;
2416 free(newpath);
2417 newpath = NULL;
2418 } while(res == 0 && --failctr);
2419
2420 return newpath;
2421}
2422
2423static int hide_node(struct fuse *f, const char *oldpath,
2424 fuse_ino_t dir, const char *oldname)
2425{
2426 char newname[64];
2427 char *newpath;
2428 int err = -EBUSY;
2429
2430 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
2431 if (newpath) {
2432 err = fuse_fs_rename(f->fs, oldpath, newpath, 0);
2433 if (!err)
2434 err = rename_node(f, dir, oldname, dir, newname, 1);
2435 free(newpath);
2436 }
2437 return err;
2438}
2439
2440static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
2441{
2442 return stbuf->st_mtime == ts->tv_sec &&
2443 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2444}
2445
2446#ifndef CLOCK_MONOTONIC
2447#define CLOCK_MONOTONIC CLOCK_REALTIME
2448#endif
2449
2450static void curr_time(struct timespec *now)
2451{
2452 static clockid_t clockid = CLOCK_MONOTONIC;
2453 int res = clock_gettime(clockid, now);
2454 if (res == -1 && errno == EINVAL) {
2455 clockid = CLOCK_REALTIME;
2456 res = clock_gettime(clockid, now);
2457 }
2458 if (res == -1) {
2459 perror("fuse: clock_gettime");
2460 abort();
2461 }
2462}
2463
2464static void update_stat(struct node *node, const struct stat *stbuf)
2465{
2466 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2467 stbuf->st_size != node->size))
2468 node->cache_valid = 0;
2469 node->mtime.tv_sec = stbuf->st_mtime;
2470 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2471 node->size = stbuf->st_size;
2472 curr_time(&node->stat_updated);
2473}
2474
2475static int do_lookup(struct fuse *f, fuse_ino_t nodeid, const char *name,
2476 struct fuse_entry_param *e)
2477{
2478 struct node *node;
2479
2480 node = find_node(f, nodeid, name);
2481 if (node == NULL)
2482 return -ENOMEM;
2483
2484 e->ino = node->nodeid;
2485 e->generation = node->generation;
2486 e->entry_timeout = f->conf.entry_timeout;
2487 e->attr_timeout = f->conf.attr_timeout;
2488 if (f->conf.auto_cache) {
2489 pthread_mutex_lock(&f->lock);
2490 update_stat(node, &e->attr);
2491 pthread_mutex_unlock(&f->lock);
2492 }
2493 set_stat(f, e->ino, &e->attr);
2494 return 0;
2495}
2496
2497static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
2498 const char *name, const char *path,
2499 struct fuse_entry_param *e, struct fuse_file_info *fi)
2500{
2501 int res;
2502
2503 memset(e, 0, sizeof(struct fuse_entry_param));
2504 res = fuse_fs_getattr(f->fs, path, &e->attr, fi);
2505 if (res == 0) {
2506 res = do_lookup(f, nodeid, name, e);
2507 if (res == 0 && f->conf.debug) {
2508 fuse_log(FUSE_LOG_DEBUG, " NODEID: %llu\n",
2509 (unsigned long long) e->ino);
2510 }
2511 }
2512 return res;
2513}
2514
2515static struct fuse_context_i *fuse_get_context_internal(void)
2516{
2517 return (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2518}
2519
2520static struct fuse_context_i *fuse_create_context(struct fuse *f)
2521{
2522 struct fuse_context_i *c = fuse_get_context_internal();
2523 if (c == NULL) {
2524 c = (struct fuse_context_i *)
2525 calloc(1, sizeof(struct fuse_context_i));
2526 if (c == NULL) {
2527 /* This is hard to deal with properly, so just
2528 abort. If memory is so low that the
2529 context cannot be allocated, there's not
2530 much hope for the filesystem anyway */
2531 fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate thread specific data\n");
2532 abort();
2533 }
2534 pthread_setspecific(fuse_context_key, c);
2535 } else {
2536 memset(c, 0, sizeof(*c));
2537 }
2538 c->ctx.fuse = f;
2539
2540 return c;
2541}
2542
2543static void fuse_freecontext(void *data)
2544{
2545 free(data);
2546}
2547
2548static int fuse_create_context_key(void)
2549{
2550 int err = 0;
2551 pthread_mutex_lock(&fuse_context_lock);
2552 if (!fuse_context_ref) {
2553 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2554 if (err) {
2555 fuse_log(FUSE_LOG_ERR, "fuse: failed to create thread specific key: %s\n",
2556 strerror(err));
2557 pthread_mutex_unlock(&fuse_context_lock);
2558 return -1;
2559 }
2560 }
2561 fuse_context_ref++;
2562 pthread_mutex_unlock(&fuse_context_lock);
2563 return 0;
2564}
2565
2566static void fuse_delete_context_key(void)
2567{
2568 pthread_mutex_lock(&fuse_context_lock);
2569 fuse_context_ref--;
2570 if (!fuse_context_ref) {
2571 free(pthread_getspecific(fuse_context_key));
2572 pthread_key_delete(fuse_context_key);
2573 }
2574 pthread_mutex_unlock(&fuse_context_lock);
2575}
2576
2577static struct fuse *req_fuse_prepare(fuse_req_t req)
2578{
2579 struct fuse_context_i *c = fuse_create_context(req_fuse(req));
2580 const struct fuse_ctx *ctx = fuse_req_ctx(req);
2581 c->req = req;
2582 c->ctx.uid = ctx->uid;
2583 c->ctx.gid = ctx->gid;
2584 c->ctx.pid = ctx->pid;
2585 c->ctx.umask = ctx->umask;
2586 return c->ctx.fuse;
2587}
2588
2589static inline void reply_err(fuse_req_t req, int err)
2590{
2591 /* fuse_reply_err() uses non-negated errno values */
2592 fuse_reply_err(req, -err);
2593}
2594
2595static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
2596 int err)
2597{
2598 if (!err) {
2599 struct fuse *f = req_fuse(req);
2600 if (fuse_reply_entry(req, e) == -ENOENT) {
2601 /* Skip forget for negative result */
2602 if (e->ino != 0)
2603 forget_node(f, e->ino, 1);
2604 }
2605 } else
2606 reply_err(req, err);
2607}
2608
2609void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn,
2610 struct fuse_config *cfg)
2611{
2612 fuse_get_context()->private_data = fs->user_data;
2613 if (!fs->op.write_buf)
2615 if (!fs->op.lock)
2617 if (!fs->op.flock)
2619 if (fs->op.init)
2620 fs->user_data = fs->op.init(conn, cfg);
2621}
2622
2623static int fuse_init_intr_signal(int signum, int *installed);
2624
2625static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
2626{
2627 struct fuse *f = (struct fuse *) data;
2628
2629 fuse_create_context(f);
2631 fuse_fs_init(f->fs, conn, &f->conf);
2632
2633 if (f->conf.intr) {
2634 if (fuse_init_intr_signal(f->conf.intr_signal,
2635 &f->intr_installed) == -1)
2636 fuse_log(FUSE_LOG_ERR, "fuse: failed to init interrupt signal\n");
2637 } else {
2638 /* Disable the receiving and processing of FUSE_INTERRUPT requests */
2639 conn->no_interrupt = 1;
2640 }
2641}
2642
2643void fuse_fs_destroy(struct fuse_fs *fs)
2644{
2645 fuse_get_context()->private_data = fs->user_data;
2646 if (fs->op.destroy)
2647 fs->op.destroy(fs->user_data);
2648}
2649
2650static void fuse_lib_destroy(void *data)
2651{
2652 struct fuse *f = (struct fuse *) data;
2653
2654 fuse_create_context(f);
2655 fuse_fs_destroy(f->fs);
2656}
2657
2658static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
2659 const char *name)
2660{
2661 struct fuse *f = req_fuse_prepare(req);
2662 struct fuse_entry_param e = { .ino = 0 }; /* invalid ino */
2663 char *path;
2664 int err;
2665 struct node *dot = NULL;
2666
2667 if (name[0] == '.') {
2668 int len = strlen(name);
2669
2670 if (len == 1 || (name[1] == '.' && len == 2)) {
2671 pthread_mutex_lock(&f->lock);
2672 if (len == 1) {
2673 if (f->conf.debug)
2674 fuse_log(FUSE_LOG_DEBUG, "LOOKUP-DOT\n");
2675 dot = get_node_nocheck(f, parent);
2676 if (dot == NULL) {
2677 pthread_mutex_unlock(&f->lock);
2678 reply_entry(req, &e, -ESTALE);
2679 return;
2680 }
2681 dot->refctr++;
2682 } else {
2683 if (f->conf.debug)
2684 fuse_log(FUSE_LOG_DEBUG, "LOOKUP-DOTDOT\n");
2685 parent = get_node(f, parent)->parent->nodeid;
2686 }
2687 pthread_mutex_unlock(&f->lock);
2688 name = NULL;
2689 }
2690 }
2691
2692 err = get_path_name(f, parent, name, &path);
2693 if (!err) {
2694 struct fuse_intr_data d;
2695 if (f->conf.debug)
2696 fuse_log(FUSE_LOG_DEBUG, "LOOKUP %s\n", path);
2697 fuse_prepare_interrupt(f, req, &d);
2698 err = lookup_path(f, parent, name, path, &e, NULL);
2699 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2700 e.ino = 0;
2701 e.entry_timeout = f->conf.negative_timeout;
2702 err = 0;
2703 }
2704 fuse_finish_interrupt(f, req, &d);
2705 free_path(f, parent, path);
2706 }
2707 if (dot) {
2708 pthread_mutex_lock(&f->lock);
2709 unref_node(f, dot);
2710 pthread_mutex_unlock(&f->lock);
2711 }
2712 reply_entry(req, &e, err);
2713}
2714
2715static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
2716{
2717 if (f->conf.debug)
2718 fuse_log(FUSE_LOG_DEBUG, "FORGET %llu/%llu\n", (unsigned long long)ino,
2719 (unsigned long long) nlookup);
2720 forget_node(f, ino, nlookup);
2721}
2722
2723static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
2724{
2725 do_forget(req_fuse(req), ino, nlookup);
2726 fuse_reply_none(req);
2727}
2728
2729static void fuse_lib_forget_multi(fuse_req_t req, size_t count,
2730 struct fuse_forget_data *forgets)
2731{
2732 struct fuse *f = req_fuse(req);
2733 size_t i;
2734
2735 for (i = 0; i < count; i++)
2736 do_forget(f, forgets[i].ino, forgets[i].nlookup);
2737
2738 fuse_reply_none(req);
2739}
2740
2741
2742static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
2743 struct fuse_file_info *fi)
2744{
2745 struct fuse *f = req_fuse_prepare(req);
2746 struct stat buf;
2747 char *path;
2748 int err;
2749
2750 memset(&buf, 0, sizeof(buf));
2751
2752 if (fi != NULL)
2753 err = get_path_nullok(f, ino, &path);
2754 else
2755 err = get_path(f, ino, &path);
2756 if (!err) {
2757 struct fuse_intr_data d;
2758 fuse_prepare_interrupt(f, req, &d);
2759 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2760 fuse_finish_interrupt(f, req, &d);
2761 free_path(f, ino, path);
2762 }
2763 if (!err) {
2764 struct node *node;
2765
2766 pthread_mutex_lock(&f->lock);
2767 node = get_node(f, ino);
2768 if (node->is_hidden && buf.st_nlink > 0)
2769 buf.st_nlink--;
2770 if (f->conf.auto_cache)
2771 update_stat(node, &buf);
2772 pthread_mutex_unlock(&f->lock);
2773 set_stat(f, ino, &buf);
2774 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2775 } else
2776 reply_err(req, err);
2777}
2778
2779int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode,
2780 struct fuse_file_info *fi)
2781{
2782 fuse_get_context()->private_data = fs->user_data;
2783 if (!fs->op.chmod)
2784 return -ENOSYS;
2785
2786 if (fs->debug) {
2787 char buf[10];
2788
2789 fuse_log(FUSE_LOG_DEBUG, "chmod[%s] %s %llo\n",
2790 file_info_string(fi, buf, sizeof(buf)),
2791 path, (unsigned long long) mode);
2792 }
2793 return fs->op.chmod(path, mode, fi);
2794}
2795
2796static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2797 int valid, struct fuse_file_info *fi)
2798{
2799 struct fuse *f = req_fuse_prepare(req);
2800 struct stat buf;
2801 char *path;
2802 int err;
2803
2804 memset(&buf, 0, sizeof(buf));
2805 if (fi != NULL)
2806 err = get_path_nullok(f, ino, &path);
2807 else
2808 err = get_path(f, ino, &path);
2809 if (!err) {
2810 struct fuse_intr_data d;
2811 fuse_prepare_interrupt(f, req, &d);
2812 err = 0;
2813 if (!err && (valid & FUSE_SET_ATTR_MODE))
2814 err = fuse_fs_chmod(f->fs, path, attr->st_mode, fi);
2815 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2816 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2817 attr->st_uid : (uid_t) -1;
2818 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2819 attr->st_gid : (gid_t) -1;
2820 err = fuse_fs_chown(f->fs, path, uid, gid, fi);
2821 }
2822 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2823 err = fuse_fs_truncate(f->fs, path,
2824 attr->st_size, fi);
2825 }
2826#ifdef HAVE_UTIMENSAT
2827 if (!err &&
2828 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2829 struct timespec tv[2];
2830
2831 tv[0].tv_sec = 0;
2832 tv[1].tv_sec = 0;
2833 tv[0].tv_nsec = UTIME_OMIT;
2834 tv[1].tv_nsec = UTIME_OMIT;
2835
2836 if (valid & FUSE_SET_ATTR_ATIME_NOW)
2837 tv[0].tv_nsec = UTIME_NOW;
2838 else if (valid & FUSE_SET_ATTR_ATIME)
2839 tv[0] = attr->st_atim;
2840
2841 if (valid & FUSE_SET_ATTR_MTIME_NOW)
2842 tv[1].tv_nsec = UTIME_NOW;
2843 else if (valid & FUSE_SET_ATTR_MTIME)
2844 tv[1] = attr->st_mtim;
2845
2846 err = fuse_fs_utimens(f->fs, path, tv, fi);
2847 } else
2848#endif
2849 if (!err &&
2850 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2851 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2852 struct timespec tv[2];
2853 tv[0].tv_sec = attr->st_atime;
2854 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2855 tv[1].tv_sec = attr->st_mtime;
2856 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2857 err = fuse_fs_utimens(f->fs, path, tv, fi);
2858 }
2859 if (!err) {
2860 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2861 }
2862 fuse_finish_interrupt(f, req, &d);
2863 free_path(f, ino, path);
2864 }
2865 if (!err) {
2866 if (f->conf.auto_cache) {
2867 pthread_mutex_lock(&f->lock);
2868 update_stat(get_node(f, ino), &buf);
2869 pthread_mutex_unlock(&f->lock);
2870 }
2871 set_stat(f, ino, &buf);
2872 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2873 } else
2874 reply_err(req, err);
2875}
2876
2877static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
2878{
2879 struct fuse *f = req_fuse_prepare(req);
2880 char *path;
2881 int err;
2882
2883 err = get_path(f, ino, &path);
2884 if (!err) {
2885 struct fuse_intr_data d;
2886
2887 fuse_prepare_interrupt(f, req, &d);
2888 err = fuse_fs_access(f->fs, path, mask);
2889 fuse_finish_interrupt(f, req, &d);
2890 free_path(f, ino, path);
2891 }
2892 reply_err(req, err);
2893}
2894
2895static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
2896{
2897 struct fuse *f = req_fuse_prepare(req);
2898 char linkname[PATH_MAX + 1];
2899 char *path;
2900 int err;
2901
2902 err = get_path(f, ino, &path);
2903 if (!err) {
2904 struct fuse_intr_data d;
2905 fuse_prepare_interrupt(f, req, &d);
2906 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
2907 fuse_finish_interrupt(f, req, &d);
2908 free_path(f, ino, path);
2909 }
2910 if (!err) {
2911 linkname[PATH_MAX] = '\0';
2912 fuse_reply_readlink(req, linkname);
2913 } else
2914 reply_err(req, err);
2915}
2916
2917static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2918 mode_t mode, dev_t rdev)
2919{
2920 struct fuse *f = req_fuse_prepare(req);
2921 struct fuse_entry_param e;
2922 char *path;
2923 int err;
2924
2925 err = get_path_name(f, parent, name, &path);
2926 if (!err) {
2927 struct fuse_intr_data d;
2928
2929 fuse_prepare_interrupt(f, req, &d);
2930 err = -ENOSYS;
2931 if (S_ISREG(mode)) {
2932 struct fuse_file_info fi;
2933
2934 memset(&fi, 0, sizeof(fi));
2935 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
2936 err = fuse_fs_create(f->fs, path, mode, &fi);
2937 if (!err) {
2938 err = lookup_path(f, parent, name, path, &e,
2939 &fi);
2940 fuse_fs_release(f->fs, path, &fi);
2941 }
2942 }
2943 if (err == -ENOSYS) {
2944 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2945 if (!err)
2946 err = lookup_path(f, parent, name, path, &e,
2947 NULL);
2948 }
2949 fuse_finish_interrupt(f, req, &d);
2950 free_path(f, parent, path);
2951 }
2952 reply_entry(req, &e, err);
2953}
2954
2955static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
2956 mode_t mode)
2957{
2958 struct fuse *f = req_fuse_prepare(req);
2959 struct fuse_entry_param e;
2960 char *path;
2961 int err;
2962
2963 err = get_path_name(f, parent, name, &path);
2964 if (!err) {
2965 struct fuse_intr_data d;
2966
2967 fuse_prepare_interrupt(f, req, &d);
2968 err = fuse_fs_mkdir(f->fs, path, mode);
2969 if (!err)
2970 err = lookup_path(f, parent, name, path, &e, NULL);
2971 fuse_finish_interrupt(f, req, &d);
2972 free_path(f, parent, path);
2973 }
2974 reply_entry(req, &e, err);
2975}
2976
2977static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
2978 const char *name)
2979{
2980 struct fuse *f = req_fuse_prepare(req);
2981 struct node *wnode;
2982 char *path;
2983 int err;
2984
2985 err = get_path_wrlock(f, parent, name, &path, &wnode);
2986 if (!err) {
2987 struct fuse_intr_data d;
2988
2989 fuse_prepare_interrupt(f, req, &d);
2990 if (!f->conf.hard_remove && is_open(f, parent, name)) {
2991 err = hide_node(f, path, parent, name);
2992 if (!err) {
2993 /* we have hidden the node so now check again under a lock in case it is not used any more */
2994 if (!is_open(f, parent, wnode->name)) {
2995 char *unlinkpath;
2996
2997 /* get the hidden file path, to unlink it */
2998 if (try_get_path(f, wnode->nodeid, NULL, &unlinkpath, NULL, false) == 0) {
2999 err = fuse_fs_unlink(f->fs, unlinkpath);
3000 if (!err)
3001 remove_node(f, parent, wnode->name);
3002 free(unlinkpath);
3003 }
3004 }
3005 }
3006 } else {
3007 err = fuse_fs_unlink(f->fs, path);
3008 if (!err)
3009 remove_node(f, parent, name);
3010 }
3011 fuse_finish_interrupt(f, req, &d);
3012 free_path_wrlock(f, parent, wnode, path);
3013 }
3014 reply_err(req, err);
3015}
3016
3017static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
3018{
3019 struct fuse *f = req_fuse_prepare(req);
3020 struct node *wnode;
3021 char *path;
3022 int err;
3023
3024 err = get_path_wrlock(f, parent, name, &path, &wnode);
3025 if (!err) {
3026 struct fuse_intr_data d;
3027
3028 fuse_prepare_interrupt(f, req, &d);
3029 err = fuse_fs_rmdir(f->fs, path);
3030 fuse_finish_interrupt(f, req, &d);
3031 if (!err)
3032 remove_node(f, parent, name);
3033 free_path_wrlock(f, parent, wnode, path);
3034 }
3035 reply_err(req, err);
3036}
3037
3038static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
3039 fuse_ino_t parent, const char *name)
3040{
3041 struct fuse *f = req_fuse_prepare(req);
3042 struct fuse_entry_param e;
3043 char *path;
3044 int err;
3045
3046 err = get_path_name(f, parent, name, &path);
3047 if (!err) {
3048 struct fuse_intr_data d;
3049
3050 fuse_prepare_interrupt(f, req, &d);
3051 err = fuse_fs_symlink(f->fs, linkname, path);
3052 if (!err)
3053 err = lookup_path(f, parent, name, path, &e, NULL);
3054 fuse_finish_interrupt(f, req, &d);
3055 free_path(f, parent, path);
3056 }
3057 reply_entry(req, &e, err);
3058}
3059
3060static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
3061 const char *oldname, fuse_ino_t newdir,
3062 const char *newname, unsigned int flags)
3063{
3064 struct fuse *f = req_fuse_prepare(req);
3065 char *oldpath;
3066 char *newpath;
3067 struct node *wnode1;
3068 struct node *wnode2;
3069 int err;
3070
3071 err = get_path2(f, olddir, oldname, newdir, newname,
3072 &oldpath, &newpath, &wnode1, &wnode2);
3073 if (!err) {
3074 struct fuse_intr_data d;
3075 err = 0;
3076 fuse_prepare_interrupt(f, req, &d);
3077 if (!f->conf.hard_remove && !(flags & RENAME_EXCHANGE) &&
3078 is_open(f, newdir, newname))
3079 err = hide_node(f, newpath, newdir, newname);
3080 if (!err) {
3081 err = fuse_fs_rename(f->fs, oldpath, newpath, flags);
3082 if (!err) {
3083 if (flags & RENAME_EXCHANGE) {
3084 err = exchange_node(f, olddir, oldname,
3085 newdir, newname);
3086 } else {
3087 err = rename_node(f, olddir, oldname,
3088 newdir, newname, 0);
3089 }
3090 }
3091 }
3092 fuse_finish_interrupt(f, req, &d);
3093 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
3094 }
3095 reply_err(req, err);
3096}
3097
3098static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
3099 const char *newname)
3100{
3101 struct fuse *f = req_fuse_prepare(req);
3102 struct fuse_entry_param e;
3103 char *oldpath;
3104 char *newpath;
3105 int err;
3106
3107 err = get_path2(f, ino, NULL, newparent, newname,
3108 &oldpath, &newpath, NULL, NULL);
3109 if (!err) {
3110 struct fuse_intr_data d;
3111
3112 fuse_prepare_interrupt(f, req, &d);
3113 err = fuse_fs_link(f->fs, oldpath, newpath);
3114 if (!err)
3115 err = lookup_path(f, newparent, newname, newpath,
3116 &e, NULL);
3117 fuse_finish_interrupt(f, req, &d);
3118 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3119 }
3120 reply_entry(req, &e, err);
3121}
3122
3123static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
3124 struct fuse_file_info *fi)
3125{
3126 struct node *node;
3127 int unlink_hidden = 0;
3128
3129 fuse_fs_release(f->fs, path, fi);
3130
3131 pthread_mutex_lock(&f->lock);
3132 node = get_node(f, ino);
3133 assert(node->open_count > 0);
3134 --node->open_count;
3135 if (node->is_hidden && !node->open_count) {
3136 unlink_hidden = 1;
3137 node->is_hidden = 0;
3138 }
3139 pthread_mutex_unlock(&f->lock);
3140
3141 if(unlink_hidden) {
3142 if (path) {
3143 fuse_fs_unlink(f->fs, path);
3144 } else if (f->conf.nullpath_ok) {
3145 char *unlinkpath;
3146
3147 if (get_path(f, ino, &unlinkpath) == 0)
3148 fuse_fs_unlink(f->fs, unlinkpath);
3149
3150 free_path(f, ino, unlinkpath);
3151 }
3152 }
3153}
3154
3155static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
3156 const char *name, mode_t mode,
3157 struct fuse_file_info *fi)
3158{
3159 struct fuse *f = req_fuse_prepare(req);
3160 struct fuse_intr_data d;
3161 struct fuse_entry_param e;
3162 char *path;
3163 int err;
3164
3165 err = get_path_name(f, parent, name, &path);
3166 if (!err) {
3167 fuse_prepare_interrupt(f, req, &d);
3168 err = fuse_fs_create(f->fs, path, mode, fi);
3169 if (!err) {
3170 err = lookup_path(f, parent, name, path, &e, fi);
3171 if (err)
3172 fuse_fs_release(f->fs, path, fi);
3173 else if (!S_ISREG(e.attr.st_mode)) {
3174 err = -EIO;
3175 fuse_fs_release(f->fs, path, fi);
3176 forget_node(f, e.ino, 1);
3177 } else {
3178 if (f->conf.direct_io)
3179 fi->direct_io = 1;
3180 if (f->conf.kernel_cache)
3181 fi->keep_cache = 1;
3182 if (fi->direct_io &&
3183 f->conf.parallel_direct_writes)
3184 fi->parallel_direct_writes = 1;
3185 }
3186 }
3187 fuse_finish_interrupt(f, req, &d);
3188 }
3189 if (!err) {
3190 pthread_mutex_lock(&f->lock);
3191 get_node(f, e.ino)->open_count++;
3192 pthread_mutex_unlock(&f->lock);
3193 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
3194 /* The open syscall was interrupted, so it
3195 must be cancelled */
3196 fuse_do_release(f, e.ino, path, fi);
3197 forget_node(f, e.ino, 1);
3198 }
3199 } else {
3200 reply_err(req, err);
3201 }
3202
3203 free_path(f, parent, path);
3204}
3205
3206static double diff_timespec(const struct timespec *t1,
3207 const struct timespec *t2)
3208{
3209 return (t1->tv_sec - t2->tv_sec) +
3210 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
3211}
3212
3213static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
3214 struct fuse_file_info *fi)
3215{
3216 struct node *node;
3217
3218 pthread_mutex_lock(&f->lock);
3219 node = get_node(f, ino);
3220 if (node->cache_valid) {
3221 struct timespec now;
3222
3223 curr_time(&now);
3224 if (diff_timespec(&now, &node->stat_updated) >
3225 f->conf.ac_attr_timeout) {
3226 struct stat stbuf;
3227 int err;
3228 pthread_mutex_unlock(&f->lock);
3229 err = fuse_fs_getattr(f->fs, path, &stbuf, fi);
3230 pthread_mutex_lock(&f->lock);
3231 if (!err)
3232 update_stat(node, &stbuf);
3233 else
3234 node->cache_valid = 0;
3235 }
3236 }
3237 if (node->cache_valid)
3238 fi->keep_cache = 1;
3239
3240 node->cache_valid = 1;
3241 pthread_mutex_unlock(&f->lock);
3242}
3243
3244static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
3245 struct fuse_file_info *fi)
3246{
3247 struct fuse *f = req_fuse_prepare(req);
3248 struct fuse_intr_data d;
3249 char *path;
3250 int err;
3251
3252 err = get_path(f, ino, &path);
3253 if (!err) {
3254 fuse_prepare_interrupt(f, req, &d);
3255 err = fuse_fs_open(f->fs, path, fi);
3256 if (!err) {
3257 if (f->conf.direct_io)
3258 fi->direct_io = 1;
3259 if (f->conf.kernel_cache)
3260 fi->keep_cache = 1;
3261
3262 if (f->conf.auto_cache)
3263 open_auto_cache(f, ino, path, fi);
3264
3265 if (f->conf.no_rofd_flush &&
3266 (fi->flags & O_ACCMODE) == O_RDONLY)
3267 fi->noflush = 1;
3268
3269 if (fi->direct_io && f->conf.parallel_direct_writes)
3270 fi->parallel_direct_writes = 1;
3271
3272 }
3273 fuse_finish_interrupt(f, req, &d);
3274 }
3275 if (!err) {
3276 pthread_mutex_lock(&f->lock);
3277 get_node(f, ino)->open_count++;
3278 pthread_mutex_unlock(&f->lock);
3279 if (fuse_reply_open(req, fi) == -ENOENT) {
3280 /* The open syscall was interrupted, so it
3281 must be cancelled */
3282 fuse_do_release(f, ino, path, fi);
3283 }
3284 } else
3285 reply_err(req, err);
3286
3287 free_path(f, ino, path);
3288}
3289
3290static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
3291 off_t off, struct fuse_file_info *fi)
3292{
3293 struct fuse *f = req_fuse_prepare(req);
3294 struct fuse_bufvec *buf = NULL;
3295 char *path;
3296 int res;
3297
3298 res = get_path_nullok(f, ino, &path);
3299 if (res == 0) {
3300 struct fuse_intr_data d;
3301
3302 fuse_prepare_interrupt(f, req, &d);
3303 res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3304 fuse_finish_interrupt(f, req, &d);
3305 free_path(f, ino, path);
3306 }
3307
3308 if (res == 0)
3310 else
3311 reply_err(req, res);
3312
3313 fuse_free_buf(buf);
3314}
3315
3316static void fuse_lib_write_buf(fuse_req_t req, fuse_ino_t ino,
3317 struct fuse_bufvec *buf, off_t off,
3318 struct fuse_file_info *fi)
3319{
3320 struct fuse *f = req_fuse_prepare(req);
3321 char *path;
3322 int res;
3323
3324 res = get_path_nullok(f, ino, &path);
3325 if (res == 0) {
3326 struct fuse_intr_data d;
3327
3328 fuse_prepare_interrupt(f, req, &d);
3329 res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3330 fuse_finish_interrupt(f, req, &d);
3331 free_path(f, ino, path);
3332 }
3333
3334 if (res >= 0)
3335 fuse_reply_write(req, res);
3336 else
3337 reply_err(req, res);
3338}
3339
3340static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
3341 struct fuse_file_info *fi)
3342{
3343 struct fuse *f = req_fuse_prepare(req);
3344 char *path;
3345 int err;
3346
3347 err = get_path_nullok(f, ino, &path);
3348 if (!err) {
3349 struct fuse_intr_data d;
3350
3351 fuse_prepare_interrupt(f, req, &d);
3352 err = fuse_fs_fsync(f->fs, path, datasync, fi);
3353 fuse_finish_interrupt(f, req, &d);
3354 free_path(f, ino, path);
3355 }
3356 reply_err(req, err);
3357}
3358
3359static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
3360 struct fuse_file_info *fi)
3361{
3362 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
3363 memset(fi, 0, sizeof(struct fuse_file_info));
3364 fi->fh = dh->fh;
3365 return dh;
3366}
3367
3368static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
3369 struct fuse_file_info *llfi)
3370{
3371 struct fuse *f = req_fuse_prepare(req);
3372 struct fuse_intr_data d;
3373 struct fuse_dh *dh;
3374 struct fuse_file_info fi;
3375 char *path;
3376 int err;
3377
3378 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
3379 if (dh == NULL) {
3380 reply_err(req, -ENOMEM);
3381 return;
3382 }
3383 memset(dh, 0, sizeof(struct fuse_dh));
3384 dh->fuse = f;
3385 dh->contents = NULL;
3386 dh->first = NULL;
3387 dh->len = 0;
3388 dh->filled = 0;
3389 dh->nodeid = ino;
3390 pthread_mutex_init(&dh->lock, NULL);
3391
3392 llfi->fh = (uintptr_t) dh;
3393
3394 memset(&fi, 0, sizeof(fi));
3395 fi.flags = llfi->flags;
3396
3397 err = get_path(f, ino, &path);
3398 if (!err) {
3399 fuse_prepare_interrupt(f, req, &d);
3400 err = fuse_fs_opendir(f->fs, path, &fi);
3401 fuse_finish_interrupt(f, req, &d);
3402 dh->fh = fi.fh;
3403 llfi->cache_readdir = fi.cache_readdir;
3404 llfi->keep_cache = fi.keep_cache;
3405 }
3406 if (!err) {
3407 if (fuse_reply_open(req, llfi) == -ENOENT) {
3408 /* The opendir syscall was interrupted, so it
3409 must be cancelled */
3410 fuse_fs_releasedir(f->fs, path, &fi);
3411 pthread_mutex_destroy(&dh->lock);
3412 free(dh);
3413 }
3414 } else {
3415 reply_err(req, err);
3416 pthread_mutex_destroy(&dh->lock);
3417 free(dh);
3418 }
3419 free_path(f, ino, path);
3420}
3421
3422static int extend_contents(struct fuse_dh *dh, unsigned minsize)
3423{
3424 if (minsize > dh->size) {
3425 char *newptr;
3426 unsigned newsize = dh->size;
3427 if (!newsize)
3428 newsize = 1024;
3429 while (newsize < minsize) {
3430 if (newsize >= 0x80000000)
3431 newsize = 0xffffffff;
3432 else
3433 newsize *= 2;
3434 }
3435
3436 newptr = (char *) realloc(dh->contents, newsize);
3437 if (!newptr) {
3438 dh->error = -ENOMEM;
3439 return -1;
3440 }
3441 dh->contents = newptr;
3442 dh->size = newsize;
3443 }
3444 return 0;
3445}
3446
3447static int fuse_add_direntry_to_dh(struct fuse_dh *dh, const char *name,
3448 struct stat *st, enum fuse_fill_dir_flags flags)
3449{
3450 struct fuse_direntry *de;
3451
3452 de = malloc(sizeof(struct fuse_direntry));
3453 if (!de) {
3454 dh->error = -ENOMEM;
3455 return -1;
3456 }
3457 de->name = strdup(name);
3458 if (!de->name) {
3459 dh->error = -ENOMEM;
3460 free(de);
3461 return -1;
3462 }
3463 de->flags = flags;
3464 de->stat = *st;
3465 de->next = NULL;
3466
3467 *dh->last = de;
3468 dh->last = &de->next;
3469
3470 return 0;
3471}
3472
3473static fuse_ino_t lookup_nodeid(struct fuse *f, fuse_ino_t parent,
3474 const char *name)
3475{
3476 struct node *node;
3477 fuse_ino_t res = FUSE_UNKNOWN_INO;
3478
3479 pthread_mutex_lock(&f->lock);
3480 node = lookup_node(f, parent, name);
3481 if (node)
3482 res = node->nodeid;
3483 pthread_mutex_unlock(&f->lock);
3484
3485 return res;
3486}
3487
3488static int fill_dir(void *dh_, const char *name, const struct stat *statp,
3489 off_t off, enum fuse_fill_dir_flags flags)
3490{
3491 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3492 struct stat stbuf;
3493
3494 if ((flags & ~FUSE_FILL_DIR_PLUS) != 0) {
3495 dh->error = -EIO;
3496 return 1;
3497 }
3498
3499 if (statp)
3500 stbuf = *statp;
3501 else {
3502 memset(&stbuf, 0, sizeof(stbuf));
3503 stbuf.st_ino = FUSE_UNKNOWN_INO;
3504 }
3505
3506 if (!dh->fuse->conf.use_ino) {
3507 stbuf.st_ino = FUSE_UNKNOWN_INO;
3508 if (dh->fuse->conf.readdir_ino) {
3509 stbuf.st_ino = (ino_t)
3510 lookup_nodeid(dh->fuse, dh->nodeid, name);
3511 }
3512 }
3513
3514 if (off) {
3515 size_t newlen;
3516
3517 if (dh->filled) {
3518 dh->error = -EIO;
3519 return 1;
3520 }
3521
3522 if (dh->first) {
3523 dh->error = -EIO;
3524 return 1;
3525 }
3526
3527 if (extend_contents(dh, dh->needlen) == -1)
3528 return 1;
3529
3530 newlen = dh->len +
3531 fuse_add_direntry(dh->req, dh->contents + dh->len,
3532 dh->needlen - dh->len, name,
3533 &stbuf, off);
3534 if (newlen > dh->needlen)
3535 return 1;
3536
3537 dh->len = newlen;
3538 } else {
3539 dh->filled = 1;
3540
3541 if (fuse_add_direntry_to_dh(dh, name, &stbuf, flags) == -1)
3542 return 1;
3543 }
3544 return 0;
3545}
3546
3547static int is_dot_or_dotdot(const char *name)
3548{
3549 return name[0] == '.' && (name[1] == '\0' ||
3550 (name[1] == '.' && name[2] == '\0'));
3551}
3552
3553static int fill_dir_plus(void *dh_, const char *name, const struct stat *statp,
3554 off_t off, enum fuse_fill_dir_flags flags)
3555{
3556 struct fuse_dh *dh = (struct fuse_dh *) dh_;
3557 struct fuse_entry_param e = {
3558 /* ino=0 tells the kernel to ignore readdirplus stat info */
3559 .ino = 0,
3560 };
3561 struct fuse *f = dh->fuse;
3562 int res;
3563
3564 if ((flags & ~FUSE_FILL_DIR_PLUS) != 0) {
3565 dh->error = -EIO;
3566 return 1;
3567 }
3568
3569 if (statp && (flags & FUSE_FILL_DIR_PLUS)) {
3570 e.attr = *statp;
3571 }
3572
3573 e.attr.st_ino = FUSE_UNKNOWN_INO;
3574 if (statp) {
3575 e.attr.st_mode = statp->st_mode;
3576 if (f->conf.use_ino)
3577 e.attr.st_ino = statp->st_ino;
3578 }
3579 if (!f->conf.use_ino && f->conf.readdir_ino) {
3580 e.attr.st_ino = (ino_t)
3581 lookup_nodeid(f, dh->nodeid, name);
3582 }
3583
3584 if (off) {
3585 size_t newlen;
3586
3587 if (dh->filled) {
3588 dh->error = -EIO;
3589 return 1;
3590 }
3591
3592 if (dh->first) {
3593 dh->error = -EIO;
3594 return 1;
3595 }
3596 if (extend_contents(dh, dh->needlen) == -1)
3597 return 1;
3598
3599 if (statp && (flags & FUSE_FILL_DIR_PLUS)) {
3600 if (!is_dot_or_dotdot(name)) {
3601 res = do_lookup(f, dh->nodeid, name, &e);
3602 if (res) {
3603 dh->error = res;
3604 return 1;
3605 }
3606 }
3607 }
3608
3609 newlen = dh->len +
3610 fuse_add_direntry_plus(dh->req, dh->contents + dh->len,
3611 dh->needlen - dh->len, name,
3612 &e, off);
3613 if (newlen > dh->needlen)
3614 return 1;
3615 dh->len = newlen;
3616 } else {
3617 dh->filled = 1;
3618
3619 if (fuse_add_direntry_to_dh(dh, name, &e.attr, flags) == -1)
3620 return 1;
3621 }
3622
3623 return 0;
3624}
3625
3626static void free_direntries(struct fuse_direntry *de)
3627{
3628 while (de) {
3629 struct fuse_direntry *next = de->next;
3630 free(de->name);
3631 free(de);
3632 de = next;
3633 }
3634}
3635
3636static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3637 size_t size, off_t off, struct fuse_dh *dh,
3638 struct fuse_file_info *fi,
3639 enum fuse_readdir_flags flags)
3640{
3641 char *path;
3642 int err;
3643
3644 if (f->fs->op.readdir)
3645 err = get_path_nullok(f, ino, &path);
3646 else
3647 err = get_path(f, ino, &path);
3648 if (!err) {
3649 struct fuse_intr_data d;
3650 fuse_fill_dir_t filler = fill_dir;
3651
3652 if (flags & FUSE_READDIR_PLUS)
3653 filler = fill_dir_plus;
3654
3655 free_direntries(dh->first);
3656 dh->first = NULL;
3657 dh->last = &dh->first;
3658 dh->len = 0;
3659 dh->error = 0;
3660 dh->needlen = size;
3661 dh->filled = 0;
3662 dh->req = req;
3663 fuse_prepare_interrupt(f, req, &d);
3664 err = fuse_fs_readdir(f->fs, path, dh, filler, off, fi, flags);
3665 fuse_finish_interrupt(f, req, &d);
3666 dh->req = NULL;
3667 if (!err)
3668 err = dh->error;
3669 if (err)
3670 dh->filled = 0;
3671 free_path(f, ino, path);
3672 }
3673 return err;
3674}
3675
3676static int readdir_fill_from_list(fuse_req_t req, struct fuse_dh *dh,
3677 off_t off, enum fuse_readdir_flags flags)
3678{
3679 off_t pos;
3680 struct fuse_direntry *de = dh->first;
3681 int res;
3682
3683 dh->len = 0;
3684
3685 if (extend_contents(dh, dh->needlen) == -1)
3686 return dh->error;
3687
3688 for (pos = 0; pos < off; pos++) {
3689 if (!de)
3690 break;
3691
3692 de = de->next;
3693 }
3694 while (de) {
3695 char *p = dh->contents + dh->len;
3696 unsigned rem = dh->needlen - dh->len;
3697 unsigned thislen;
3698 unsigned newlen;
3699 pos++;
3700
3701 if (flags & FUSE_READDIR_PLUS) {
3702 struct fuse_entry_param e = {
3703 .ino = 0,
3704 .attr = de->stat,
3705 };
3706
3707 if (de->flags & FUSE_FILL_DIR_PLUS &&
3708 !is_dot_or_dotdot(de->name)) {
3709 res = do_lookup(dh->fuse, dh->nodeid,
3710 de->name, &e);
3711 if (res) {
3712 dh->error = res;
3713 return 1;
3714 }
3715 }
3716
3717 thislen = fuse_add_direntry_plus(req, p, rem,
3718 de->name, &e, pos);
3719 } else {
3720 thislen = fuse_add_direntry(req, p, rem,
3721 de->name, &de->stat, pos);
3722 }
3723 newlen = dh->len + thislen;
3724 if (newlen > dh->needlen)
3725 break;
3726 dh->len = newlen;
3727 de = de->next;
3728 }
3729 return 0;
3730}
3731
3732static void fuse_readdir_common(fuse_req_t req, fuse_ino_t ino, size_t size,
3733 off_t off, struct fuse_file_info *llfi,
3734 enum fuse_readdir_flags flags)
3735{
3736 struct fuse *f = req_fuse_prepare(req);
3737 struct fuse_file_info fi;
3738 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3739 int err;
3740
3741 pthread_mutex_lock(&dh->lock);
3742 /* According to SUS, directory contents need to be refreshed on
3743 rewinddir() */
3744 if (!off)
3745 dh->filled = 0;
3746
3747 if (!dh->filled) {
3748 err = readdir_fill(f, req, ino, size, off, dh, &fi, flags);
3749 if (err) {
3750 reply_err(req, err);
3751 goto out;
3752 }
3753 }
3754 if (dh->filled) {
3755 dh->needlen = size;
3756 err = readdir_fill_from_list(req, dh, off, flags);
3757 if (err) {
3758 reply_err(req, err);
3759 goto out;
3760 }
3761 }
3762 fuse_reply_buf(req, dh->contents, dh->len);
3763out:
3764 pthread_mutex_unlock(&dh->lock);
3765}
3766
3767static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
3768 off_t off, struct fuse_file_info *llfi)
3769{
3770 fuse_readdir_common(req, ino, size, off, llfi, 0);
3771}
3772
3773static void fuse_lib_readdirplus(fuse_req_t req, fuse_ino_t ino, size_t size,
3774 off_t off, struct fuse_file_info *llfi)
3775{
3776 fuse_readdir_common(req, ino, size, off, llfi, FUSE_READDIR_PLUS);
3777}
3778
3779static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
3780 struct fuse_file_info *llfi)
3781{
3782 struct fuse *f = req_fuse_prepare(req);
3783 struct fuse_intr_data d;
3784 struct fuse_file_info fi;
3785 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3786 char *path;
3787
3788 get_path_nullok(f, ino, &path);
3789
3790 fuse_prepare_interrupt(f, req, &d);
3791 fuse_fs_releasedir(f->fs, path, &fi);
3792 fuse_finish_interrupt(f, req, &d);
3793 free_path(f, ino, path);
3794
3795 pthread_mutex_lock(&dh->lock);
3796 pthread_mutex_unlock(&dh->lock);
3797 pthread_mutex_destroy(&dh->lock);
3798 free_direntries(dh->first);
3799 free(dh->contents);
3800 free(dh);
3801 reply_err(req, 0);
3802}
3803
3804static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
3805 struct fuse_file_info *llfi)
3806{
3807 struct fuse *f = req_fuse_prepare(req);
3808 struct fuse_file_info fi;
3809 char *path;
3810 int err;
3811
3812 get_dirhandle(llfi, &fi);
3813
3814 err = get_path_nullok(f, ino, &path);
3815 if (!err) {
3816 struct fuse_intr_data d;
3817 fuse_prepare_interrupt(f, req, &d);
3818 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3819 fuse_finish_interrupt(f, req, &d);
3820 free_path(f, ino, path);
3821 }
3822 reply_err(req, err);
3823}
3824
3825static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
3826{
3827 struct fuse *f = req_fuse_prepare(req);
3828 struct statvfs buf;
3829 char *path = NULL;
3830 int err = 0;
3831
3832 memset(&buf, 0, sizeof(buf));
3833 if (ino)
3834 err = get_path(f, ino, &path);
3835
3836 if (!err) {
3837 struct fuse_intr_data d;
3838 fuse_prepare_interrupt(f, req, &d);
3839 err = fuse_fs_statfs(f->fs, path ? path : "/", &buf);
3840 fuse_finish_interrupt(f, req, &d);
3841 free_path(f, ino, path);
3842 }
3843
3844 if (!err)
3845 fuse_reply_statfs(req, &buf);
3846 else
3847 reply_err(req, err);
3848}
3849
3850static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3851 const char *value, size_t size, int flags)
3852{
3853 struct fuse *f = req_fuse_prepare(req);
3854 char *path;
3855 int err;
3856
3857 err = get_path(f, ino, &path);
3858 if (!err) {
3859 struct fuse_intr_data d;
3860 fuse_prepare_interrupt(f, req, &d);
3861 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3862 fuse_finish_interrupt(f, req, &d);
3863 free_path(f, ino, path);
3864 }
3865 reply_err(req, err);
3866}
3867
3868static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3869 const char *name, char *value, size_t size)
3870{
3871 int err;
3872 char *path;
3873
3874 err = get_path(f, ino, &path);
3875 if (!err) {
3876 struct fuse_intr_data d;
3877 fuse_prepare_interrupt(f, req, &d);
3878 err = fuse_fs_getxattr(f->fs, path, name, value, size);
3879 fuse_finish_interrupt(f, req, &d);
3880 free_path(f, ino, path);
3881 }
3882 return err;
3883}
3884
3885static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3886 size_t size)
3887{
3888 struct fuse *f = req_fuse_prepare(req);
3889 int res;
3890
3891 if (size) {
3892 char *value = (char *) malloc(size);
3893 if (value == NULL) {
3894 reply_err(req, -ENOMEM);
3895 return;
3896 }
3897 res = common_getxattr(f, req, ino, name, value, size);
3898 if (res > 0)
3899 fuse_reply_buf(req, value, res);
3900 else
3901 reply_err(req, res);
3902 free(value);
3903 } else {
3904 res = common_getxattr(f, req, ino, name, NULL, 0);
3905 if (res >= 0)
3906 fuse_reply_xattr(req, res);
3907 else
3908 reply_err(req, res);
3909 }
3910}
3911
3912static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3913 char *list, size_t size)
3914{
3915 char *path;
3916 int err;
3917
3918 err = get_path(f, ino, &path);
3919 if (!err) {
3920 struct fuse_intr_data d;
3921 fuse_prepare_interrupt(f, req, &d);
3922 err = fuse_fs_listxattr(f->fs, path, list, size);
3923 fuse_finish_interrupt(f, req, &d);
3924 free_path(f, ino, path);
3925 }
3926 return err;
3927}
3928
3929static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
3930{
3931 struct fuse *f = req_fuse_prepare(req);
3932 int res;
3933
3934 if (size) {
3935 char *list = (char *) malloc(size);
3936 if (list == NULL) {
3937 reply_err(req, -ENOMEM);
3938 return;
3939 }
3940 res = common_listxattr(f, req, ino, list, size);
3941 if (res > 0)
3942 fuse_reply_buf(req, list, res);
3943 else
3944 reply_err(req, res);
3945 free(list);
3946 } else {
3947 res = common_listxattr(f, req, ino, NULL, 0);
3948 if (res >= 0)
3949 fuse_reply_xattr(req, res);
3950 else
3951 reply_err(req, res);
3952 }
3953}
3954
3955static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
3956 const char *name)
3957{
3958 struct fuse *f = req_fuse_prepare(req);
3959 char *path;
3960 int err;
3961
3962 err = get_path(f, ino, &path);
3963 if (!err) {
3964 struct fuse_intr_data d;
3965 fuse_prepare_interrupt(f, req, &d);
3966 err = fuse_fs_removexattr(f->fs, path, name);
3967 fuse_finish_interrupt(f, req, &d);
3968 free_path(f, ino, path);
3969 }
3970 reply_err(req, err);
3971}
3972
3973static struct lock *locks_conflict(struct node *node, const struct lock *lock)
3974{
3975 struct lock *l;
3976
3977 for (l = node->locks; l; l = l->next)
3978 if (l->owner != lock->owner &&
3979 lock->start <= l->end && l->start <= lock->end &&
3980 (l->type == F_WRLCK || lock->type == F_WRLCK))
3981 break;
3982
3983 return l;
3984}
3985
3986static void delete_lock(struct lock **lockp)
3987{
3988 struct lock *l = *lockp;
3989 *lockp = l->next;
3990 free(l);
3991}
3992
3993static void insert_lock(struct lock **pos, struct lock *lock)
3994{
3995 lock->next = *pos;
3996 *pos = lock;
3997}
3998
3999static int locks_insert(struct node *node, struct lock *lock)
4000{
4001 struct lock **lp;
4002 struct lock *newl1 = NULL;
4003 struct lock *newl2 = NULL;
4004
4005 if (lock->type != F_UNLCK || lock->start != 0 ||
4006 lock->end != OFFSET_MAX) {
4007 newl1 = malloc(sizeof(struct lock));
4008 newl2 = malloc(sizeof(struct lock));
4009
4010 if (!newl1 || !newl2) {
4011 free(newl1);
4012 free(newl2);
4013 return -ENOLCK;
4014 }
4015 }
4016
4017 for (lp = &node->locks; *lp;) {
4018 struct lock *l = *lp;
4019 if (l->owner != lock->owner)
4020 goto skip;
4021
4022 if (lock->type == l->type) {
4023 if (l->end < lock->start - 1)
4024 goto skip;
4025 if (lock->end < l->start - 1)
4026 break;
4027 if (l->start <= lock->start && lock->end <= l->end)
4028 goto out;
4029 if (l->start < lock->start)
4030 lock->start = l->start;
4031 if (lock->end < l->end)
4032 lock->end = l->end;
4033 goto delete;
4034 } else {
4035 if (l->end < lock->start)
4036 goto skip;
4037 if (lock->end < l->start)
4038 break;
4039 if (lock->start <= l->start && l->end <= lock->end)
4040 goto delete;
4041 if (l->end <= lock->end) {
4042 l->end = lock->start - 1;
4043 goto skip;
4044 }
4045 if (lock->start <= l->start) {
4046 l->start = lock->end + 1;
4047 break;
4048 }
4049 *newl2 = *l;
4050 newl2->start = lock->end + 1;
4051 l->end = lock->start - 1;
4052 insert_lock(&l->next, newl2);
4053 newl2 = NULL;
4054 }
4055 skip:
4056 lp = &l->next;
4057 continue;
4058
4059 delete:
4060 delete_lock(lp);
4061 }
4062 if (lock->type != F_UNLCK) {
4063 *newl1 = *lock;
4064 insert_lock(lp, newl1);
4065 newl1 = NULL;
4066 }
4067out:
4068 free(newl1);
4069 free(newl2);
4070 return 0;
4071}
4072
4073static void flock_to_lock(struct flock *flock, struct lock *lock)
4074{
4075 memset(lock, 0, sizeof(struct lock));
4076 lock->type = flock->l_type;
4077 lock->start = flock->l_start;
4078 lock->end =
4079 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
4080 lock->pid = flock->l_pid;
4081}
4082
4083static void lock_to_flock(struct lock *lock, struct flock *flock)
4084{
4085 flock->l_type = lock->type;
4086 flock->l_start = lock->start;
4087 flock->l_len =
4088 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
4089 flock->l_pid = lock->pid;
4090}
4091
4092static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
4093 const char *path, struct fuse_file_info *fi)
4094{
4095 struct fuse_intr_data d;
4096 struct flock lock;
4097 struct lock l;
4098 int err;
4099 int errlock;
4100
4101 fuse_prepare_interrupt(f, req, &d);
4102 memset(&lock, 0, sizeof(lock));
4103 lock.l_type = F_UNLCK;
4104 lock.l_whence = SEEK_SET;
4105 err = fuse_fs_flush(f->fs, path, fi);
4106 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
4107 fuse_finish_interrupt(f, req, &d);
4108
4109 if (errlock != -ENOSYS) {
4110 flock_to_lock(&lock, &l);
4111 l.owner = fi->lock_owner;
4112 pthread_mutex_lock(&f->lock);
4113 locks_insert(get_node(f, ino), &l);
4114 pthread_mutex_unlock(&f->lock);
4115
4116 /* if op.lock() is defined FLUSH is needed regardless
4117 of op.flush() */
4118 if (err == -ENOSYS)
4119 err = 0;
4120 }
4121 return err;
4122}
4123
4124static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
4125 struct fuse_file_info *fi)
4126{
4127 struct fuse *f = req_fuse_prepare(req);
4128 struct fuse_intr_data d;
4129 char *path;
4130 int err = 0;
4131
4132 get_path_nullok(f, ino, &path);
4133 if (fi->flush) {
4134 err = fuse_flush_common(f, req, ino, path, fi);
4135 if (err == -ENOSYS)
4136 err = 0;
4137 }
4138
4139 fuse_prepare_interrupt(f, req, &d);
4140 fuse_do_release(f, ino, path, fi);
4141 fuse_finish_interrupt(f, req, &d);
4142 free_path(f, ino, path);
4143
4144 reply_err(req, err);
4145}
4146
4147static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
4148 struct fuse_file_info *fi)
4149{
4150 struct fuse *f = req_fuse_prepare(req);
4151 char *path;
4152 int err;
4153
4154 get_path_nullok(f, ino, &path);
4155 err = fuse_flush_common(f, req, ino, path, fi);
4156 free_path(f, ino, path);
4157
4158 reply_err(req, err);
4159}
4160
4161static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
4162 struct fuse_file_info *fi, struct flock *lock,
4163 int cmd)
4164{
4165 struct fuse *f = req_fuse_prepare(req);
4166 char *path;
4167 int err;
4168
4169 err = get_path_nullok(f, ino, &path);
4170 if (!err) {
4171 struct fuse_intr_data d;
4172 fuse_prepare_interrupt(f, req, &d);
4173 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
4174 fuse_finish_interrupt(f, req, &d);
4175 free_path(f, ino, path);
4176 }
4177 return err;
4178}
4179
4180static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
4181 struct fuse_file_info *fi, struct flock *lock)
4182{
4183 int err;
4184 struct lock l;
4185 struct lock *conflict;
4186 struct fuse *f = req_fuse(req);
4187
4188 flock_to_lock(lock, &l);
4189 l.owner = fi->lock_owner;
4190 pthread_mutex_lock(&f->lock);
4191 conflict = locks_conflict(get_node(f, ino), &l);
4192 if (conflict)
4193 lock_to_flock(conflict, lock);
4194 pthread_mutex_unlock(&f->lock);
4195 if (!conflict)
4196 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
4197 else
4198 err = 0;
4199
4200 if (!err)
4201 fuse_reply_lock(req, lock);
4202 else
4203 reply_err(req, err);
4204}
4205
4206static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
4207 struct fuse_file_info *fi, struct flock *lock,
4208 int sleep)
4209{
4210 int err = fuse_lock_common(req, ino, fi, lock,
4211 sleep ? F_SETLKW : F_SETLK);
4212 if (!err) {
4213 struct fuse *f = req_fuse(req);
4214 struct lock l;
4215 flock_to_lock(lock, &l);
4216 l.owner = fi->lock_owner;
4217 pthread_mutex_lock(&f->lock);
4218 locks_insert(get_node(f, ino), &l);
4219 pthread_mutex_unlock(&f->lock);
4220 }
4221 reply_err(req, err);
4222}
4223
4224static void fuse_lib_flock(fuse_req_t req, fuse_ino_t ino,
4225 struct fuse_file_info *fi, int op)
4226{
4227 struct fuse *f = req_fuse_prepare(req);
4228 char *path;
4229 int err;
4230
4231 err = get_path_nullok(f, ino, &path);
4232 if (err == 0) {
4233 struct fuse_intr_data d;
4234 fuse_prepare_interrupt(f, req, &d);
4235 err = fuse_fs_flock(f->fs, path, fi, op);
4236 fuse_finish_interrupt(f, req, &d);
4237 free_path(f, ino, path);
4238 }
4239 reply_err(req, err);
4240}
4241
4242static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
4243 uint64_t idx)
4244{
4245 struct fuse *f = req_fuse_prepare(req);
4246 struct fuse_intr_data d;
4247 char *path;
4248 int err;
4249
4250 err = get_path(f, ino, &path);
4251 if (!err) {
4252 fuse_prepare_interrupt(f, req, &d);
4253 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
4254 fuse_finish_interrupt(f, req, &d);
4255 free_path(f, ino, path);
4256 }
4257 if (!err)
4258 fuse_reply_bmap(req, idx);
4259 else
4260 reply_err(req, err);
4261}
4262
4263static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, unsigned int cmd,
4264 void *arg, struct fuse_file_info *llfi,
4265 unsigned int flags, const void *in_buf,
4266 size_t in_bufsz, size_t out_bufsz)
4267{
4268 struct fuse *f = req_fuse_prepare(req);
4269 struct fuse_intr_data d;
4270 struct fuse_file_info fi;
4271 char *path, *out_buf = NULL;
4272 int err;
4273
4274 err = -EPERM;
4275 if (flags & FUSE_IOCTL_UNRESTRICTED)
4276 goto err;
4277
4278 if (flags & FUSE_IOCTL_DIR)
4279 get_dirhandle(llfi, &fi);
4280 else
4281 fi = *llfi;
4282
4283 if (out_bufsz) {
4284 err = -ENOMEM;
4285 out_buf = malloc(out_bufsz);
4286 if (!out_buf)
4287 goto err;
4288 }
4289
4290 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
4291 if (out_buf && in_bufsz)
4292 memcpy(out_buf, in_buf, in_bufsz);
4293
4294 err = get_path_nullok(f, ino, &path);
4295 if (err)
4296 goto err;
4297
4298 fuse_prepare_interrupt(f, req, &d);
4299
4300 err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
4301 out_buf ? out_buf : (void *)in_buf);
4302
4303 fuse_finish_interrupt(f, req, &d);
4304 free_path(f, ino, path);
4305
4306 if (err < 0)
4307 goto err;
4308 fuse_reply_ioctl(req, err, out_buf, out_bufsz);
4309 goto out;
4310err:
4311 reply_err(req, err);
4312out:
4313 free(out_buf);
4314}
4315
4316static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
4317 struct fuse_file_info *fi, struct fuse_pollhandle *ph)
4318{
4319 struct fuse *f = req_fuse_prepare(req);
4320 struct fuse_intr_data d;
4321 char *path;
4322 int err;
4323 unsigned revents = 0;
4324
4325 err = get_path_nullok(f, ino, &path);
4326 if (!err) {
4327 fuse_prepare_interrupt(f, req, &d);
4328 err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4329 fuse_finish_interrupt(f, req, &d);
4330 free_path(f, ino, path);
4331 }
4332 if (!err)
4333 fuse_reply_poll(req, revents);
4334 else
4335 reply_err(req, err);
4336}
4337
4338static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode,
4339 off_t offset, off_t length, struct fuse_file_info *fi)
4340{
4341 struct fuse *f = req_fuse_prepare(req);
4342 struct fuse_intr_data d;
4343 char *path;
4344 int err;
4345
4346 err = get_path_nullok(f, ino, &path);
4347 if (!err) {
4348 fuse_prepare_interrupt(f, req, &d);
4349 err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4350 fuse_finish_interrupt(f, req, &d);
4351 free_path(f, ino, path);
4352 }
4353 reply_err(req, err);
4354}
4355
4356static void fuse_lib_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in,
4357 off_t off_in, struct fuse_file_info *fi_in,
4358 fuse_ino_t nodeid_out, off_t off_out,
4359 struct fuse_file_info *fi_out, size_t len,
4360 int flags)
4361{
4362 struct fuse *f = req_fuse_prepare(req);
4363 struct fuse_intr_data d;
4364 char *path_in, *path_out;
4365 int err;
4366 ssize_t res;
4367
4368 err = get_path_nullok(f, nodeid_in, &path_in);
4369 if (err) {
4370 reply_err(req, err);
4371 return;
4372 }
4373
4374 err = get_path_nullok(f, nodeid_out, &path_out);
4375 if (err) {
4376 free_path(f, nodeid_in, path_in);
4377 reply_err(req, err);
4378 return;
4379 }
4380
4381 fuse_prepare_interrupt(f, req, &d);
4382 res = fuse_fs_copy_file_range(f->fs, path_in, fi_in, off_in, path_out,
4383 fi_out, off_out, len, flags);
4384 fuse_finish_interrupt(f, req, &d);
4385
4386 if (res >= 0)
4387 fuse_reply_write(req, res);
4388 else
4389 reply_err(req, res);
4390
4391 free_path(f, nodeid_in, path_in);
4392 free_path(f, nodeid_out, path_out);
4393}
4394
4395static void fuse_lib_lseek(fuse_req_t req, fuse_ino_t ino, off_t off, int whence,
4396 struct fuse_file_info *fi)
4397{
4398 struct fuse *f = req_fuse_prepare(req);
4399 struct fuse_intr_data d;
4400 char *path;
4401 int err;
4402 off_t res;
4403
4404 err = get_path(f, ino, &path);
4405 if (err) {
4406 reply_err(req, err);
4407 return;
4408 }
4409
4410 fuse_prepare_interrupt(f, req, &d);
4411 res = fuse_fs_lseek(f->fs, path, off, whence, fi);
4412 fuse_finish_interrupt(f, req, &d);
4413 free_path(f, ino, path);
4414 if (res >= 0)
4415 fuse_reply_lseek(req, res);
4416 else
4417 reply_err(req, res);
4418}
4419
4420#ifdef HAVE_STATX
4421static void fuse_lib_statx(fuse_req_t req, fuse_ino_t ino, int flags, int mask,
4422 struct fuse_file_info *fi)
4423{
4424 struct fuse *f = req_fuse_prepare(req);
4425 struct statx stxbuf;
4426 char *path;
4427 int err;
4428
4429 memset(&stxbuf, 0, sizeof(stxbuf));
4430
4431 if (fi != NULL)
4432 err = get_path_nullok(f, ino, &path);
4433 else
4434 err = get_path(f, ino, &path);
4435
4436 if (!err) {
4437 struct fuse_intr_data d;
4438
4439 if (!path)
4440 flags |= AT_EMPTY_PATH;
4441 fuse_prepare_interrupt(f, req, &d);
4442 err = fuse_fs_statx(f->fs, path, flags, mask, &stxbuf, fi);
4443 fuse_finish_interrupt(f, req, &d);
4444 free_path(f, ino, path);
4445 }
4446 if (!err) {
4447 struct node *node;
4448
4449 pthread_mutex_lock(&f->lock);
4450 node = get_node(f, ino);
4451 if (node->is_hidden && stxbuf.stx_nlink > 0)
4452 stxbuf.stx_nlink--;
4453 if (f->conf.auto_cache) {
4454 struct stat stbuf;
4455
4456 stbuf.st_mtime = stxbuf.stx_mtime.tv_nsec;
4457 ST_MTIM_NSEC(&stbuf) = stxbuf.stx_mtime.tv_nsec;
4458 stbuf.st_size = stxbuf.stx_size;
4459 update_stat(node, &stbuf);
4460 }
4461 pthread_mutex_unlock(&f->lock);
4462 set_statx(f, ino, &stxbuf);
4463 fuse_reply_statx(req, 0, &stxbuf, f->conf.attr_timeout);
4464 } else
4465 reply_err(req, err);
4466}
4467#endif
4468
4469static int clean_delay(struct fuse *f)
4470{
4471 /*
4472 * This is calculating the delay between clean runs. To
4473 * reduce the number of cleans we are doing them 10 times
4474 * within the remember window.
4475 */
4476 int min_sleep = 60;
4477 int max_sleep = 3600;
4478 int sleep_time = f->conf.remember / 10;
4479
4480 if (sleep_time > max_sleep)
4481 return max_sleep;
4482 if (sleep_time < min_sleep)
4483 return min_sleep;
4484 return sleep_time;
4485}
4486
4487int fuse_clean_cache(struct fuse *f)
4488{
4489 struct node_lru *lnode;
4490 struct list_head *curr, *next;
4491 struct node *node;
4492 struct timespec now;
4493
4494 pthread_mutex_lock(&f->lock);
4495
4496 curr_time(&now);
4497
4498 for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4499 double age;
4500
4501 next = curr->next;
4502 lnode = list_entry(curr, struct node_lru, lru);
4503 node = &lnode->node;
4504
4505 age = diff_timespec(&now, &lnode->forget_time);
4506 if (age <= f->conf.remember)
4507 break;
4508
4509 assert(node->nlookup == 1);
4510
4511 /* Don't forget active directories */
4512 if (node->refctr > 1)
4513 continue;
4514
4515 node->nlookup = 0;
4516 unhash_name(f, node);
4517 unref_node(f, node);
4518 }
4519 pthread_mutex_unlock(&f->lock);
4520
4521 return clean_delay(f);
4522}
4523
4524static struct fuse_lowlevel_ops fuse_path_ops = {
4525 .init = fuse_lib_init,
4526 .destroy = fuse_lib_destroy,
4527 .lookup = fuse_lib_lookup,
4528 .forget = fuse_lib_forget,
4529 .forget_multi = fuse_lib_forget_multi,
4530 .getattr = fuse_lib_getattr,
4531 .setattr = fuse_lib_setattr,
4532 .access = fuse_lib_access,
4533 .readlink = fuse_lib_readlink,
4534 .mknod = fuse_lib_mknod,
4535 .mkdir = fuse_lib_mkdir,
4536 .unlink = fuse_lib_unlink,
4537 .rmdir = fuse_lib_rmdir,
4538 .symlink = fuse_lib_symlink,
4539 .rename = fuse_lib_rename,
4540 .link = fuse_lib_link,
4541 .create = fuse_lib_create,
4542 .open = fuse_lib_open,
4543 .read = fuse_lib_read,
4544 .write_buf = fuse_lib_write_buf,
4545 .flush = fuse_lib_flush,
4546 .release = fuse_lib_release,
4547 .fsync = fuse_lib_fsync,
4548 .opendir = fuse_lib_opendir,
4549 .readdir = fuse_lib_readdir,
4550 .readdirplus = fuse_lib_readdirplus,
4551 .releasedir = fuse_lib_releasedir,
4552 .fsyncdir = fuse_lib_fsyncdir,
4553 .statfs = fuse_lib_statfs,
4554 .setxattr = fuse_lib_setxattr,
4555 .getxattr = fuse_lib_getxattr,
4556 .listxattr = fuse_lib_listxattr,
4557 .removexattr = fuse_lib_removexattr,
4558 .getlk = fuse_lib_getlk,
4559 .setlk = fuse_lib_setlk,
4560 .flock = fuse_lib_flock,
4561 .bmap = fuse_lib_bmap,
4562 .ioctl = fuse_lib_ioctl,
4563 .poll = fuse_lib_poll,
4564 .fallocate = fuse_lib_fallocate,
4565 .copy_file_range = fuse_lib_copy_file_range,
4566 .lseek = fuse_lib_lseek,
4567#ifdef HAVE_STATX
4568 .statx = fuse_lib_statx,
4569#endif
4570};
4571
4572int fuse_notify_poll(struct fuse_pollhandle *ph)
4573{
4574 return fuse_lowlevel_notify_poll(ph);
4575}
4576
4577struct fuse_session *fuse_get_session(struct fuse *f)
4578{
4579 return f->se;
4580}
4581
4582static int fuse_session_loop_remember(struct fuse *f)
4583{
4584 struct fuse_session *se = f->se;
4585 int res = 0;
4586 struct timespec now;
4587 time_t next_clean;
4588 struct pollfd fds = {
4589 .fd = se->fd,
4590 .events = POLLIN
4591 };
4592 struct fuse_buf fbuf = {
4593 .mem = NULL,
4594 };
4595
4596 curr_time(&now);
4597 next_clean = now.tv_sec;
4598 while (!fuse_session_exited(se)) {
4599 unsigned timeout;
4600
4601 curr_time(&now);
4602 if (now.tv_sec < next_clean)
4603 timeout = next_clean - now.tv_sec;
4604 else
4605 timeout = 0;
4606
4607 res = poll(&fds, 1, timeout * 1000);
4608 if (res == -1) {
4609 if (errno == EINTR)
4610 continue;
4611 else
4612 break;
4613 } else if (res > 0) {
4614 res = fuse_session_receive_buf_internal(se, &fbuf,
4615 NULL);
4616 if (res == -EINTR)
4617 continue;
4618 if (res <= 0)
4619 break;
4620
4621 fuse_session_process_buf_internal(se, &fbuf, NULL);
4622 } else {
4623 timeout = fuse_clean_cache(f);
4624 curr_time(&now);
4625 next_clean = now.tv_sec + timeout;
4626 }
4627 }
4628
4629 fuse_buf_free(&fbuf);
4630 return res < 0 ? -1 : 0;
4631}
4632
4633int fuse_loop(struct fuse *f)
4634{
4635 if (!f)
4636 return -1;
4637
4638 if (lru_enabled(f))
4639 return fuse_session_loop_remember(f);
4640
4641 return fuse_session_loop(f->se);
4642}
4643
4644FUSE_SYMVER("fuse_loop_mt_312", "fuse_loop_mt@@FUSE_3.12")
4645int fuse_loop_mt_312(struct fuse *f, struct fuse_loop_config *config)
4646{
4647 if (f == NULL)
4648 return -1;
4649
4650 int res = fuse_start_cleanup_thread(f);
4651 if (res)
4652 return -1;
4653
4654 res = fuse_session_loop_mt_312(fuse_get_session(f), config);
4656 return res;
4657}
4658
4659int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config_v1 *config_v1);
4660FUSE_SYMVER("fuse_loop_mt_32", "fuse_loop_mt@FUSE_3.2")
4661int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config_v1 *config_v1)
4662{
4663 struct fuse_loop_config *config = fuse_loop_cfg_create();
4664 if (config == NULL)
4665 return ENOMEM;
4666
4667 fuse_loop_cfg_convert(config, config_v1);
4668
4669 int res = fuse_loop_mt_312(f, config);
4670
4671 fuse_loop_cfg_destroy(config);
4672
4673 return res;
4674}
4675
4676int fuse_loop_mt_31(struct fuse *f, int clone_fd);
4677FUSE_SYMVER("fuse_loop_mt_31", "fuse_loop_mt@FUSE_3.0")
4678int fuse_loop_mt_31(struct fuse *f, int clone_fd)
4679{
4680 int err;
4681 struct fuse_loop_config *config = fuse_loop_cfg_create();
4682
4683 if (config == NULL)
4684 return ENOMEM;
4685
4686 fuse_loop_cfg_set_clone_fd(config, clone_fd);
4687
4688 err = fuse_loop_mt_312(f, config);
4689
4690 fuse_loop_cfg_destroy(config);
4691
4692 return err;
4693}
4694
4695void fuse_exit(struct fuse *f)
4696{
4697 fuse_session_exit(f->se);
4698}
4699
4700struct fuse_context *fuse_get_context(void)
4701{
4702 struct fuse_context_i *c = fuse_get_context_internal();
4703
4704 if (c)
4705 return &c->ctx;
4706 else
4707 return NULL;
4708}
4709
4710int fuse_getgroups(int size, gid_t list[])
4711{
4712 struct fuse_context_i *c = fuse_get_context_internal();
4713 if (!c)
4714 return -EINVAL;
4715
4716 return fuse_req_getgroups(c->req, size, list);
4717}
4718
4719int fuse_interrupted(void)
4720{
4721 struct fuse_context_i *c = fuse_get_context_internal();
4722
4723 if (c)
4724 return fuse_req_interrupted(c->req);
4725 else
4726 return 0;
4727}
4728
4729int fuse_invalidate_path(struct fuse *f, const char *path) {
4730 fuse_ino_t ino;
4731 int err = lookup_path_in_cache(f, path, &ino);
4732 if (err) {
4733 return err;
4734 }
4735
4736 return fuse_lowlevel_notify_inval_inode(f->se, ino, 0, 0);
4737}
4738
4739#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4740
4741static const struct fuse_opt fuse_lib_opts[] = {
4744 FUSE_LIB_OPT("debug", debug, 1),
4745 FUSE_LIB_OPT("-d", debug, 1),
4746 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
4747 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
4748 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
4749 FUSE_LIB_OPT("no_rofd_flush", no_rofd_flush, 1),
4750 FUSE_LIB_OPT("umask=", set_mode, 1),
4751 FUSE_LIB_OPT("umask=%o", umask, 0),
4752 FUSE_LIB_OPT("fmask=", set_mode, 1),
4753 FUSE_LIB_OPT("fmask=%o", fmask, 0),
4754 FUSE_LIB_OPT("dmask=", set_mode, 1),
4755 FUSE_LIB_OPT("dmask=%o", dmask, 0),
4756 FUSE_LIB_OPT("uid=", set_uid, 1),
4757 FUSE_LIB_OPT("uid=%d", uid, 0),
4758 FUSE_LIB_OPT("gid=", set_gid, 1),
4759 FUSE_LIB_OPT("gid=%d", gid, 0),
4760 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
4761 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
4762 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
4763 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
4764 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
4765 FUSE_LIB_OPT("noforget", remember, -1),
4766 FUSE_LIB_OPT("remember=%u", remember, 0),
4767 FUSE_LIB_OPT("modules=%s", modules, 0),
4768 FUSE_LIB_OPT("parallel_direct_write=%d", parallel_direct_writes, 0),
4770};
4771
4772static int fuse_lib_opt_proc(void *data, const char *arg, int key,
4773 struct fuse_args *outargs)
4774{
4775 (void) arg; (void) outargs; (void) data; (void) key;
4776
4777 /* Pass through unknown options */
4778 return 1;
4779}
4780
4781
4782static const struct fuse_opt fuse_help_opts[] = {
4783 FUSE_LIB_OPT("modules=%s", modules, 1),
4784 FUSE_OPT_KEY("modules=%s", FUSE_OPT_KEY_KEEP),
4786};
4787
4788static void print_module_help(const char *name,
4790{
4791 struct fuse_args a = FUSE_ARGS_INIT(0, NULL);
4792 if (fuse_opt_add_arg(&a, "") == -1 ||
4793 fuse_opt_add_arg(&a, "-h") == -1)
4794 return;
4795 printf("\nOptions for %s module:\n", name);
4796 (*fac)(&a, NULL);
4798}
4799
4800void fuse_lib_help(struct fuse_args *args)
4801{
4802 /* These are not all options, but only the ones that
4803 may be of interest to an end-user */
4804 printf(
4805" -o kernel_cache cache files in kernel\n"
4806" -o [no]auto_cache enable caching based on modification times (off)\n"
4807" -o no_rofd_flush disable flushing of read-only fd on close (off)\n"
4808" -o umask=M set file permissions (octal)\n"
4809" -o fmask=M set file permissions (octal)\n"
4810" -o dmask=M set dir permissions (octal)\n"
4811" -o uid=N set file owner\n"
4812" -o gid=N set file group\n"
4813" -o entry_timeout=T cache timeout for names (1.0s)\n"
4814" -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
4815" -o attr_timeout=T cache timeout for attributes (1.0s)\n"
4816" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
4817" -o noforget never forget cached inodes\n"
4818" -o remember=T remember cached inodes for T seconds (0s)\n"
4819" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n");
4820
4821
4822 /* Print low-level help */
4824
4825 /* Print help for builtin modules */
4826 print_module_help("subdir", &fuse_module_subdir_factory);
4827#ifdef HAVE_ICONV
4828 print_module_help("iconv", &fuse_module_iconv_factory);
4829#endif
4830
4831 /* Parse command line options in case we need to
4832 activate more modules */
4833 struct fuse_config conf = { .modules = NULL };
4834 if (fuse_opt_parse(args, &conf, fuse_help_opts,
4835 fuse_lib_opt_proc) == -1
4836 || !conf.modules)
4837 return;
4838
4839 char *module;
4840 char *next;
4841 struct fuse_module *m;
4842
4843 // Iterate over all modules
4844 for (module = conf.modules; module; module = next) {
4845 char *p;
4846 for (p = module; *p && *p != ':'; p++);
4847 next = *p ? p + 1 : NULL;
4848 *p = '\0';
4849
4850 m = fuse_get_module(module);
4851 if (m)
4852 print_module_help(module, &m->factory);
4853 }
4854}
4855
4856static int fuse_init_intr_signal(int signum, int *installed)
4857{
4858 struct sigaction old_sa;
4859
4860 if (sigaction(signum, NULL, &old_sa) == -1) {
4861 perror("fuse: cannot get old signal handler");
4862 return -1;
4863 }
4864
4865 if (old_sa.sa_handler == SIG_DFL) {
4866 struct sigaction sa;
4867
4868 memset(&sa, 0, sizeof(struct sigaction));
4869 sa.sa_handler = fuse_intr_sighandler;
4870 sigemptyset(&sa.sa_mask);
4871
4872 if (sigaction(signum, &sa, NULL) == -1) {
4873 perror("fuse: cannot set interrupt signal handler");
4874 return -1;
4875 }
4876 *installed = 1;
4877 }
4878 return 0;
4879}
4880
4881static void fuse_restore_intr_signal(int signum)
4882{
4883 struct sigaction sa;
4884
4885 memset(&sa, 0, sizeof(struct sigaction));
4886 sa.sa_handler = SIG_DFL;
4887 sigaction(signum, &sa, NULL);
4888}
4889
4890
4891static int fuse_push_module(struct fuse *f, const char *module,
4892 struct fuse_args *args)
4893{
4894 struct fuse_fs *fs[2] = { f->fs, NULL };
4895 struct fuse_fs *newfs;
4896 struct fuse_module *m = fuse_get_module(module);
4897
4898 if (!m)
4899 return -1;
4900
4901 newfs = m->factory(args, fs);
4902 if (!newfs) {
4903 fuse_put_module(m);
4904 return -1;
4905 }
4906 f->fs = newfs;
4907 return 0;
4908}
4909
4910struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
4911 void *user_data)
4912{
4913 struct fuse_fs *fs;
4914
4915 if (sizeof(struct fuse_operations) < op_size) {
4916 fuse_log(FUSE_LOG_ERR, "fuse: warning: library too old, some operations may not not work\n");
4917 op_size = sizeof(struct fuse_operations);
4918 }
4919
4920 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
4921 if (!fs) {
4922 fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate fuse_fs object\n");
4923 return NULL;
4924 }
4925
4926 fs->user_data = user_data;
4927 if (op)
4928 memcpy(&fs->op, op, op_size);
4929 return fs;
4930}
4931
4932static int node_table_init(struct node_table *t)
4933{
4934 t->size = NODE_TABLE_MIN_SIZE;
4935 t->array = (struct node **) calloc(1, sizeof(struct node *) * t->size);
4936 if (t->array == NULL) {
4937 fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
4938 return -1;
4939 }
4940 t->use = 0;
4941 t->split = 0;
4942
4943 return 0;
4944}
4945
4946static void *fuse_prune_nodes(void *fuse)
4947{
4948 struct fuse *f = fuse;
4949 int sleep_time;
4950
4951 fuse_set_thread_name("fuse_prune_nodes");
4952
4953 while(1) {
4954 sleep_time = fuse_clean_cache(f);
4955 sleep(sleep_time);
4956 }
4957 return NULL;
4958}
4959
4960int fuse_start_cleanup_thread(struct fuse *f)
4961{
4962 if (lru_enabled(f))
4963 return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4964
4965 return 0;
4966}
4967
4968void fuse_stop_cleanup_thread(struct fuse *f)
4969{
4970 if (lru_enabled(f)) {
4971 pthread_mutex_lock(&f->lock);
4972 pthread_cancel(f->prune_thread);
4973 pthread_mutex_unlock(&f->lock);
4974 pthread_join(f->prune_thread, NULL);
4975 }
4976}
4977
4978/*
4979 * Not supposed to be called directly, but supposed to be called
4980 * through the fuse_new macro
4981 */
4982struct fuse *_fuse_new_31(struct fuse_args *args,
4983 const struct fuse_operations *op, size_t op_size,
4984 struct libfuse_version *version, void *user_data)
4985{
4986 struct fuse *f;
4987 struct node *root;
4988 struct fuse_fs *fs;
4989 struct fuse_lowlevel_ops llop = fuse_path_ops;
4990
4991 f = (struct fuse *) calloc(1, sizeof(struct fuse));
4992 if (f == NULL) {
4993 fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate fuse object\n");
4994 goto out;
4995 }
4996
4997 f->conf.entry_timeout = 1.0;
4998 f->conf.attr_timeout = 1.0;
4999 f->conf.negative_timeout = 0.0;
5000 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
5001
5002 /* Parse options */
5003 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
5004 fuse_lib_opt_proc) == -1)
5005 goto out_free;
5006
5007 pthread_mutex_lock(&fuse_context_lock);
5008 static int builtin_modules_registered = 0;
5009 /* Have the builtin modules already been registered? */
5010 if (builtin_modules_registered == 0) {
5011 /* If not, register them. */
5012 fuse_register_module("subdir", fuse_module_subdir_factory, NULL);
5013#ifdef HAVE_ICONV
5014 fuse_register_module("iconv", fuse_module_iconv_factory, NULL);
5015#endif
5016 builtin_modules_registered= 1;
5017 }
5018 pthread_mutex_unlock(&fuse_context_lock);
5019
5020 if (fuse_create_context_key() == -1)
5021 goto out_free;
5022
5023 fs = fuse_fs_new(op, op_size, user_data);
5024 if (!fs)
5025 goto out_delete_context_key;
5026
5027 f->fs = fs;
5028
5029 /* Oh f**k, this is ugly! */
5030 if (!fs->op.lock) {
5031 llop.getlk = NULL;
5032 llop.setlk = NULL;
5033 }
5034
5035 f->pagesize = getpagesize();
5036 init_list_head(&f->partial_slabs);
5037 init_list_head(&f->full_slabs);
5038 init_list_head(&f->lru_table);
5039
5040 if (f->conf.modules) {
5041 char *module;
5042 char *next;
5043
5044 for (module = f->conf.modules; module; module = next) {
5045 char *p;
5046 for (p = module; *p && *p != ':'; p++);
5047 next = *p ? p + 1 : NULL;
5048 *p = '\0';
5049 if (module[0] &&
5050 fuse_push_module(f, module, args) == -1)
5051 goto out_free_fs;
5052 }
5053 }
5054
5055 if (!f->conf.ac_attr_timeout_set)
5056 f->conf.ac_attr_timeout = f->conf.attr_timeout;
5057
5058#if defined(__FreeBSD__) || defined(__NetBSD__)
5059 /*
5060 * In FreeBSD, we always use these settings as inode numbers
5061 * are needed to make getcwd(3) work.
5062 */
5063 f->conf.readdir_ino = 1;
5064#endif
5065
5066 /* not declared globally, to restrict usage of this function */
5067 struct fuse_session *fuse_session_new_versioned(
5068 struct fuse_args *args, const struct fuse_lowlevel_ops *op,
5069 size_t op_size, struct libfuse_version *version,
5070 void *userdata);
5071 f->se = fuse_session_new_versioned(args, &llop, sizeof(llop), version,
5072 f);
5073 if (f->se == NULL)
5074 goto out_free_fs;
5075
5076 /* Trace topmost layer by default */
5077 f->fs->debug = f->conf.debug;
5078 f->ctr = 0;
5079 f->generation = 0;
5080 if (node_table_init(&f->name_table) == -1)
5081 goto out_free_session;
5082
5083 if (node_table_init(&f->id_table) == -1)
5084 goto out_free_name_table;
5085
5086 pthread_mutex_init(&f->lock, NULL);
5087
5088 root = alloc_node(f);
5089 if (root == NULL) {
5090 fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
5091 goto out_free_id_table;
5092 }
5093 if (lru_enabled(f)) {
5094 struct node_lru *lnode = node_lru(root);
5095 init_list_head(&lnode->lru);
5096 }
5097
5098 strcpy(root->inline_name, "/");
5099 root->name = root->inline_name;
5100 root->parent = NULL;
5101 root->nodeid = FUSE_ROOT_ID;
5102 inc_nlookup(root);
5103 hash_id(f, root);
5104
5105 return f;
5106
5107out_free_id_table:
5108 free(f->id_table.array);
5109out_free_name_table:
5110 free(f->name_table.array);
5111out_free_session:
5112 fuse_session_destroy(f->se);
5113out_free_fs:
5114 free(f->fs);
5115 free(f->conf.modules);
5116out_delete_context_key:
5117 fuse_delete_context_key();
5118out_free:
5119 free(f);
5120out:
5121 return NULL;
5122}
5123
5124/* Emulates 3.0-style fuse_new(), which processes --help */
5125FUSE_SYMVER("_fuse_new_30", "_fuse_new@FUSE_3.0")
5126struct fuse *_fuse_new_30(struct fuse_args *args,
5127 const struct fuse_operations *op,
5128 size_t op_size,
5129 struct libfuse_version *version,
5130 void *user_data)
5131{
5132 struct fuse_config conf = {0};
5133
5134 const struct fuse_opt opts[] = {
5135 FUSE_LIB_OPT("-h", show_help, 1),
5136 FUSE_LIB_OPT("--help", show_help, 1),
5138 };
5139
5140 if (fuse_opt_parse(args, &conf, opts,
5141 fuse_lib_opt_proc) == -1)
5142 return NULL;
5143
5144 if (conf.show_help) {
5145 fuse_lib_help(args);
5146 return NULL;
5147 } else
5148 return _fuse_new_31(args, op, op_size, version, user_data);
5149}
5150
5151/* ABI compat version */
5152struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *op,
5153 size_t op_size, void *user_data);
5154FUSE_SYMVER("fuse_new_31", "fuse_new@FUSE_3.1")
5155struct fuse *fuse_new_31(struct fuse_args *args,
5156 const struct fuse_operations *op,
5157 size_t op_size, void *user_data)
5158{
5159 /* unknown version */
5160 struct libfuse_version version = { 0 };
5161
5162 return _fuse_new_31(args, op, op_size, &version, user_data);
5163}
5164
5165/*
5166 * ABI compat version
5167 * Emulates 3.0-style fuse_new(), which processes --help
5168 */
5169struct fuse *fuse_new_30(struct fuse_args *args, const struct fuse_operations *op,
5170 size_t op_size, void *user_data);
5171FUSE_SYMVER("fuse_new_30", "fuse_new@FUSE_3.0")
5172struct fuse *fuse_new_30(struct fuse_args *args,
5173 const struct fuse_operations *op,
5174 size_t op_size, void *user_data)
5175{
5176 struct fuse_config conf = {0};
5177
5178 const struct fuse_opt opts[] = {
5179 FUSE_LIB_OPT("-h", show_help, 1),
5180 FUSE_LIB_OPT("--help", show_help, 1),
5182 };
5183
5184 if (fuse_opt_parse(args, &conf, opts,
5185 fuse_lib_opt_proc) == -1)
5186 return NULL;
5187
5188 if (conf.show_help) {
5189 fuse_lib_help(args);
5190 return NULL;
5191 } else
5192 return fuse_new_31(args, op, op_size, user_data);
5193}
5194
5195
5196void fuse_destroy(struct fuse *f)
5197{
5198 size_t i;
5199
5200 if (f->conf.intr && f->intr_installed)
5201 fuse_restore_intr_signal(f->conf.intr_signal);
5202
5203 if (f->fs) {
5204 fuse_create_context(f);
5205
5206 for (i = 0; i < f->id_table.size; i++) {
5207 struct node *node;
5208
5209 for (node = f->id_table.array[i]; node != NULL;
5210 node = node->id_next) {
5211 if (node->is_hidden) {
5212 char *path;
5213 if (try_get_path(f, node->nodeid, NULL, &path, NULL, false) == 0) {
5214 fuse_fs_unlink(f->fs, path);
5215 free(path);
5216 }
5217 }
5218 }
5219 }
5220 }
5221 for (i = 0; i < f->id_table.size; i++) {
5222 struct node *node;
5223 struct node *next;
5224
5225 for (node = f->id_table.array[i]; node != NULL; node = next) {
5226 next = node->id_next;
5227 free_node(f, node);
5228 f->id_table.use--;
5229 }
5230 }
5231 assert(list_empty(&f->partial_slabs));
5232 assert(list_empty(&f->full_slabs));
5233
5234 while (fuse_modules) {
5235 fuse_put_module(fuse_modules);
5236 }
5237 free(f->id_table.array);
5238 free(f->name_table.array);
5239 pthread_mutex_destroy(&f->lock);
5240 fuse_session_destroy(f->se);
5241 free(f->fs);
5242 free(f->conf.modules);
5243 free(f);
5244 fuse_delete_context_key();
5245}
5246
5247int fuse_mount(struct fuse *f, const char *mountpoint) {
5248 return fuse_session_mount(fuse_get_session(f), mountpoint);
5249}
5250
5251
5252void fuse_unmount(struct fuse *f) {
5254}
5255
5256int fuse_version(void)
5257{
5258 return FUSE_VERSION;
5259}
5260
5261const char *fuse_pkgversion(void)
5262{
5263 return PACKAGE_VERSION;
5264}
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)
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
struct fuse_context * fuse_get_context(void)
Definition fuse.c:4644
int fuse_reply_statx(fuse_req_t req, int flags, struct statx *statx, double attr_timeout)
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(* getlk)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock)
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)