libfuse: lib/fuse_29.c Source File

libfuse

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