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