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