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