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