libfuse: lib/fuse.c Source File

libfuse

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