blob: 98170cf9af77a8bf5b1a5f5200f7ecc171b12b90 [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
13#include "fuse_i.h"
14#include "fuse_lowlevel.h"
15#include "fuse_opt.h"
16#include "fuse_misc.h"
17#include "fuse_common_compat.h"
18#include "fuse_compat.h"
19#include "fuse_kernel.h"
20
21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24#include <stddef.h>
25#include <unistd.h>
26#include <time.h>
27#include <fcntl.h>
28#include <limits.h>
29#include <errno.h>
30#include <signal.h>
31#include <dlfcn.h>
32#include <assert.h>
33#include <sys/param.h>
34#include <sys/uio.h>
35#include <sys/time.h>
36
37#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
38
39#define FUSE_UNKNOWN_INO 0xffffffff
40#define OFFSET_MAX 0x7fffffffffffffffLL
41
42struct fuse_config {
43 unsigned int uid;
44 unsigned int gid;
45 unsigned int umask;
46 double entry_timeout;
47 double negative_timeout;
48 double attr_timeout;
49 double ac_attr_timeout;
50 int ac_attr_timeout_set;
51 int noforget;
52 int debug;
53 int hard_remove;
54 int use_ino;
55 int readdir_ino;
56 int set_mode;
57 int set_uid;
58 int set_gid;
59 int direct_io;
60 int kernel_cache;
61 int auto_cache;
62 int intr;
63 int intr_signal;
64 int help;
65 char *modules;
66};
67
68struct fuse_fs {
69 struct fuse_operations op;
70 struct fuse_module *m;
71 void *user_data;
72 int compat;
73 int debug;
74};
75
76struct fusemod_so {
77 void *handle;
78 int ctr;
79};
80
81struct lock_queue_element {
82 struct lock_queue_element *next;
83 pthread_cond_t cond;
84};
85
86struct fuse {
87 struct fuse_session *se;
88 struct node **name_table;
89 size_t name_table_size;
90 struct node **id_table;
91 size_t id_table_size;
92 fuse_ino_t ctr;
93 unsigned int generation;
94 unsigned int hidectr;
95 pthread_mutex_t lock;
96 struct fuse_config conf;
97 int intr_installed;
98 struct fuse_fs *fs;
99 int nullpath_ok;
100 int curr_ticket;
101 struct lock_queue_element *lockq;
102};
103
104struct lock {
105 int type;
106 off64_t start;
107 off64_t end;
108 pid_t pid;
109 uint64_t owner;
110 struct lock *next;
111};
112
113struct node {
114 struct node *name_next;
115 struct node *id_next;
116 fuse_ino_t nodeid;
117 unsigned int generation;
118 int refctr;
119 struct node *parent;
120 char *name;
121 uint64_t nlookup;
122 int open_count;
123 struct timespec stat_updated;
124 struct timespec mtime;
125 off64_t size;
126 struct lock *locks;
127 unsigned int is_hidden : 1;
128 unsigned int cache_valid : 1;
129 int treelock;
130 int ticket;
131};
132
133struct fuse_dh {
134 pthread_mutex_t lock;
135 struct fuse *fuse;
136 fuse_req_t req;
137 char *contents;
138 int allocated;
139 unsigned len;
140 unsigned size;
141 unsigned needlen;
142 int filled;
143 uint64_t fh;
144 int error;
145 fuse_ino_t nodeid;
146};
147
148/* old dir handle */
149struct fuse_dirhandle {
150 fuse_fill_dir_t filler;
151 void *buf;
152};
153
154struct fuse_context_i {
155 struct fuse_context ctx;
156 fuse_req_t req;
157};
158
159static pthread_key_t fuse_context_key;
160static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
161static int fuse_context_ref;
162static struct fusemod_so *fuse_current_so;
163static struct fuse_module *fuse_modules;
164
165static int fuse_load_so_name(const char *soname)
166{
167 struct fusemod_so *so;
168
169 so = calloc(1, sizeof(struct fusemod_so));
170 if (!so) {
171 fprintf(stderr, "fuse: memory allocation failed\n");
172 return -1;
173 }
174
175 fuse_current_so = so;
176 so->handle = dlopen(soname, RTLD_NOW);
177 fuse_current_so = NULL;
178 if (!so->handle) {
179 fprintf(stderr, "fuse: %s\n", dlerror());
180 goto err;
181 }
182 if (!so->ctr) {
183 fprintf(stderr, "fuse: %s did not register any modules\n",
184 soname);
185 goto err;
186 }
187 return 0;
188
189err:
190 if (so->handle)
191 dlclose(so->handle);
192 free(so);
193 return -1;
194}
195
196static int fuse_load_so_module(const char *module)
197{
198 int res;
199 char *soname = malloc(strlen(module) + 64);
200 if (!soname) {
201 fprintf(stderr, "fuse: memory allocation failed\n");
202 return -1;
203 }
204 sprintf(soname, "libfusemod_%s.so", module);
205 res = fuse_load_so_name(soname);
206 free(soname);
207 return res;
208}
209
210static struct fuse_module *fuse_find_module(const char *module)
211{
212 struct fuse_module *m;
213 for (m = fuse_modules; m; m = m->next) {
214 if (strcmp(module, m->name) == 0) {
215 m->ctr++;
216 break;
217 }
218 }
219 return m;
220}
221
222static struct fuse_module *fuse_get_module(const char *module)
223{
224 struct fuse_module *m;
225
226 pthread_mutex_lock(&fuse_context_lock);
227 m = fuse_find_module(module);
228 if (!m) {
229 int err = fuse_load_so_module(module);
230 if (!err)
231 m = fuse_find_module(module);
232 }
233 pthread_mutex_unlock(&fuse_context_lock);
234 return m;
235}
236
237static void fuse_put_module(struct fuse_module *m)
238{
239 pthread_mutex_lock(&fuse_context_lock);
240 assert(m->ctr > 0);
241 m->ctr--;
242 if (!m->ctr && m->so) {
243 struct fusemod_so *so = m->so;
244 assert(so->ctr > 0);
245 so->ctr--;
246 if (!so->ctr) {
247 struct fuse_module **mp;
248 for (mp = &fuse_modules; *mp;) {
249 if ((*mp)->so == so)
250 *mp = (*mp)->next;
251 else
252 mp = &(*mp)->next;
253 }
254 dlclose(so->handle);
255 free(so);
256 }
257 }
258 pthread_mutex_unlock(&fuse_context_lock);
259}
260
261static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
262{
263 size_t hash = nodeid % f->id_table_size;
264 struct node *node;
265
266 for (node = f->id_table[hash]; node != NULL; node = node->id_next)
267 if (node->nodeid == nodeid)
268 return node;
269
270 return NULL;
271}
272
273static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
274{
275 struct node *node = get_node_nocheck(f, nodeid);
276 if (!node) {
277 fprintf(stderr, "fuse internal error: node %llu not found\n",
278 (unsigned long long) nodeid);
279 abort();
280 }
281 return node;
282}
283
284static void free_node(struct node *node)
285{
286 free(node->name);
287 free(node);
288}
289
290static void unhash_id(struct fuse *f, struct node *node)
291{
292 size_t hash = node->nodeid % f->id_table_size;
293 struct node **nodep = &f->id_table[hash];
294
295 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
296 if (*nodep == node) {
297 *nodep = node->id_next;
298 return;
299 }
300}
301
302static void hash_id(struct fuse *f, struct node *node)
303{
304 size_t hash = node->nodeid % f->id_table_size;
305 node->id_next = f->id_table[hash];
306 f->id_table[hash] = node;
307}
308
309static unsigned int name_hash(struct fuse *f, fuse_ino_t parent,
310 const char *name)
311{
312 unsigned int hash = *name;
313
314 if (hash)
315 for (name += 1; *name != '\0'; name++)
316 hash = (hash << 5) - hash + *name;
317
318 return (hash + parent) % f->name_table_size;
319}
320
321static void unref_node(struct fuse *f, struct node *node);
322
323static void unhash_name(struct fuse *f, struct node *node)
324{
325 if (node->name) {
326 size_t hash = name_hash(f, node->parent->nodeid, node->name);
327 struct node **nodep = &f->name_table[hash];
328
329 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
330 if (*nodep == node) {
331 *nodep = node->name_next;
332 node->name_next = NULL;
333 unref_node(f, node->parent);
334 free(node->name);
335 node->name = NULL;
336 node->parent = NULL;
337 return;
338 }
339 fprintf(stderr,
340 "fuse internal error: unable to unhash node: %llu\n",
341 (unsigned long long) node->nodeid);
342 abort();
343 }
344}
345
346static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
347 const char *name)
348{
349 size_t hash = name_hash(f, parentid, name);
350 struct node *parent = get_node(f, parentid);
351 node->name = strdup(name);
352 if (node->name == NULL)
353 return -1;
354
355 parent->refctr ++;
356 node->parent = parent;
357 node->name_next = f->name_table[hash];
358 f->name_table[hash] = node;
359 return 0;
360}
361
362static void delete_node(struct fuse *f, struct node *node)
363{
364 if (f->conf.debug)
365 fprintf(stderr, "DELETE: %llu\n",
366 (unsigned long long) node->nodeid);
367
368 assert(node->treelock == 0);
369 assert(!node->name);
370 unhash_id(f, node);
371 free_node(node);
372}
373
374static void unref_node(struct fuse *f, struct node *node)
375{
376 assert(node->refctr > 0);
377 node->refctr --;
378 if (!node->refctr)
379 delete_node(f, node);
380}
381
382static fuse_ino_t next_id(struct fuse *f)
383{
384 do {
385 f->ctr = (f->ctr + 1) & 0xffffffff;
386 if (!f->ctr)
387 f->generation ++;
388 } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
389 get_node_nocheck(f, f->ctr) != NULL);
390 return f->ctr;
391}
392
393static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
394 const char *name)
395{
396 size_t hash = name_hash(f, parent, name);
397 struct node *node;
398
399 for (node = f->name_table[hash]; node != NULL; node = node->name_next)
400 if (node->parent->nodeid == parent &&
401 strcmp(node->name, name) == 0)
402 return node;
403
404 return NULL;
405}
406
407static struct node *find_node(struct fuse *f, fuse_ino_t parent,
408 const char *name)
409{
410 struct node *node;
411
412 pthread_mutex_lock(&f->lock);
413 if (!name)
414 node = get_node(f, parent);
415 else
416 node = lookup_node(f, parent, name);
417 if (node == NULL) {
418 node = (struct node *) calloc(1, sizeof(struct node));
419 if (node == NULL)
420 goto out_err;
421
422 if (f->conf.noforget)
423 node->nlookup = 1;
424 node->refctr = 1;
425 node->nodeid = next_id(f);
426 node->generation = f->generation;
427 node->open_count = 0;
428 node->is_hidden = 0;
429 node->treelock = 0;
430 node->ticket = 0;
431 if (hash_name(f, node, parent, name) == -1) {
432 free(node);
433 node = NULL;
434 goto out_err;
435 }
436 hash_id(f, node);
437 }
438 node->nlookup ++;
439out_err:
440 pthread_mutex_unlock(&f->lock);
441 return node;
442}
443
444static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
445{
446 size_t len = strlen(name);
447
448 if (s - len <= *buf) {
449 unsigned pathlen = *bufsize - (s - *buf);
450 unsigned newbufsize = *bufsize;
451 char *newbuf;
452
453 while (newbufsize < pathlen + len + 1) {
454 if (newbufsize >= 0x80000000)
455 newbufsize = 0xffffffff;
456 else
457 newbufsize *= 2;
458 }
459
460 newbuf = realloc(*buf, newbufsize);
461 if (newbuf == NULL)
462 return NULL;
463
464 *buf = newbuf;
465 s = newbuf + newbufsize - pathlen;
466 memmove(s, newbuf + *bufsize - pathlen, pathlen);
467 *bufsize = newbufsize;
468 }
469 s -= len;
470 strncpy(s, name, len);
471 s--;
472 *s = '/';
473
474 return s;
475}
476
477static void unlock_path(struct fuse *f, fuse_ino_t nodeid, struct node *wnode,
478 struct node *end, int ticket)
479{
480 struct node *node;
481
482 if (wnode) {
483 assert(wnode->treelock == -1);
484 wnode->treelock = 0;
485 if (!wnode->ticket)
486 wnode->ticket = ticket;
487 }
488
489 for (node = get_node(f, nodeid);
490 node != end && node->nodeid != FUSE_ROOT_ID; node = node->parent) {
491 assert(node->treelock > 0);
492 node->treelock--;
493 if (!node->ticket)
494 node->ticket = ticket;
495 }
496}
497
498static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name,
499 char **path, struct node **wnodep, int ticket)
500{
501 unsigned bufsize = 256;
502 char *buf;
503 char *s;
504 struct node *node;
505 struct node *wnode = NULL;
506 int err;
507
508 *path = NULL;
509
510 buf = malloc(bufsize);
511 if (buf == NULL)
512 return -ENOMEM;
513
514 s = buf + bufsize - 1;
515 *s = '\0';
516
517 if (name != NULL) {
518 s = add_name(&buf, &bufsize, s, name);
519 err = -ENOMEM;
bigbiff bigbiff31f0e5f2013-01-19 10:23:42 -0500520 printf("setting err to ENOMEM\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500521 if (s == NULL)
522 goto out_free;
523 }
524
525 if (wnodep) {
526 assert(ticket);
527 wnode = lookup_node(f, nodeid, name);
528 if (wnode) {
529 if (wnode->treelock != 0 ||
530 (wnode->ticket && wnode->ticket != ticket)) {
531 if (!wnode->ticket)
532 wnode->ticket = ticket;
533 err = -EAGAIN;
bigbiff bigbiff31f0e5f2013-01-19 10:23:42 -0500534 printf("setting err to EAGAIN\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500535 goto out_free;
536 }
537 wnode->treelock = -1;
538 wnode->ticket = 0;
539 }
540 }
541
542 err = 0;
543 for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID;
544 node = node->parent) {
545 err = -ENOENT;
bigbiff bigbiff31f0e5f2013-01-19 10:23:42 -0500546 printf("setting err to ENOENT\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500547 if (node->name == NULL || node->parent == NULL)
548 goto out_unlock;
549
550 err = -ENOMEM;
bigbiff bigbiff31f0e5f2013-01-19 10:23:42 -0500551 printf("setting err to ENOMEM\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500552 s = add_name(&buf, &bufsize, s, node->name);
553 if (s == NULL)
554 goto out_unlock;
555
556 if (ticket) {
557 err = -EAGAIN;
bigbiff bigbiff31f0e5f2013-01-19 10:23:42 -0500558 printf("setting err to EAGAIN\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500559 if (node->treelock == -1 ||
560 (node->ticket && node->ticket != ticket))
561 goto out_unlock;
562
563 node->treelock++;
564 node->ticket = 0;
565 }
566 }
567
568 if (s[0])
569 memmove(buf, s, bufsize - (s - buf));
570 else
571 strcpy(buf, "/");
572
573 *path = buf;
574 if (wnodep)
575 *wnodep = wnode;
576
577 return 0;
578
579 out_unlock:
580 if (ticket)
581 unlock_path(f, nodeid, wnode, node, ticket);
582 out_free:
583 free(buf);
584
585 return err;
586}
587
588static void wake_up_first(struct fuse *f)
589{
590 if (f->lockq)
591 pthread_cond_signal(&f->lockq->cond);
592}
593
594static void wake_up_next(struct lock_queue_element *qe)
595{
596 if (qe->next)
597 pthread_cond_signal(&qe->next->cond);
598}
599
600static int get_ticket(struct fuse *f)
601{
602 do f->curr_ticket++;
603 while (f->curr_ticket == 0);
604
605 return f->curr_ticket;
606}
607
608static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid,
609 const char *name, int wr)
610{
611 if (f->conf.debug) {
612 struct node *wnode = NULL;
613
614 if (wr)
615 wnode = lookup_node(f, nodeid, name);
616
617 if (wnode)
618 fprintf(stderr, "%s %li (w)\n", msg, wnode->nodeid);
619 else
620 fprintf(stderr, "%s %li\n", msg, nodeid);
621 }
622}
623
624static void queue_path(struct fuse *f, struct lock_queue_element *qe,
625 fuse_ino_t nodeid, const char *name, int wr)
626{
627 struct lock_queue_element **qp;
628
629 debug_path(f, "QUEUE PATH", nodeid, name, wr);
630 pthread_cond_init(&qe->cond, NULL);
631 qe->next = NULL;
632 for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next);
633 *qp = qe;
634}
635
636static void dequeue_path(struct fuse *f, struct lock_queue_element *qe,
637 fuse_ino_t nodeid, const char *name, int wr)
638{
639 struct lock_queue_element **qp;
640
641 debug_path(f, "DEQUEUE PATH", nodeid, name, wr);
642 pthread_cond_destroy(&qe->cond);
643 for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next);
644 *qp = qe->next;
645}
646
647static void wait_on_path(struct fuse *f, struct lock_queue_element *qe,
648 fuse_ino_t nodeid, const char *name, int wr)
649{
650 debug_path(f, "WAIT ON PATH", nodeid, name, wr);
651 pthread_cond_wait(&qe->cond, &f->lock);
652}
653
654static int get_path_common(struct fuse *f, fuse_ino_t nodeid, const char *name,
655 char **path, struct node **wnode)
656{
657 int err;
658 int ticket;
659
660 pthread_mutex_lock(&f->lock);
661 ticket = get_ticket(f);
662 err = try_get_path(f, nodeid, name, path, wnode, ticket);
663 if (err == -EAGAIN) {
664 struct lock_queue_element qe;
665
666 queue_path(f, &qe, nodeid, name, !!wnode);
667 do {
668 wait_on_path(f, &qe, nodeid, name, !!wnode);
669 err = try_get_path(f, nodeid, name, path, wnode,
670 ticket);
671 wake_up_next(&qe);
672 } while (err == -EAGAIN);
673 dequeue_path(f, &qe, nodeid, name, !!wnode);
674 }
675 pthread_mutex_unlock(&f->lock);
676
677 return err;
678}
679
680static int get_path(struct fuse *f, fuse_ino_t nodeid, char **path)
681{
682 return get_path_common(f, nodeid, NULL, path, NULL);
683}
684
685static int get_path_nullok(struct fuse *f, fuse_ino_t nodeid, char **path)
686{
687 int err = get_path_common(f, nodeid, NULL, path, NULL);
688
689 if (err == -ENOENT && f->nullpath_ok)
690 err = 0;
691
692 return err;
693}
694
695static int get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name,
696 char **path)
697{
698 return get_path_common(f, nodeid, name, path, NULL);
699}
700
701static int get_path_wrlock(struct fuse *f, fuse_ino_t nodeid, const char *name,
702 char **path, struct node **wnode)
703{
704 return get_path_common(f, nodeid, name, path, wnode);
705}
706
707static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
708 fuse_ino_t nodeid2, const char *name2,
709 char **path1, char **path2,
710 struct node **wnode1, struct node **wnode2,
711 int ticket)
712{
713 int err;
714
715 /* FIXME: locking two paths needs deadlock checking */
716 err = try_get_path(f, nodeid1, name1, path1, wnode1, ticket);
717 if (!err) {
718 err = try_get_path(f, nodeid2, name2, path2, wnode2, ticket);
719 if (err)
720 unlock_path(f, nodeid1, wnode1 ? *wnode1 : NULL, NULL,
721 ticket);
722 }
723 return err;
724}
725
726static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
727 fuse_ino_t nodeid2, const char *name2,
728 char **path1, char **path2,
729 struct node **wnode1, struct node **wnode2)
730{
731 int err;
732 int ticket;
733
734 pthread_mutex_lock(&f->lock);
735 ticket = get_ticket(f);
736 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
737 path1, path2, wnode1, wnode2, ticket);
738 if (err == -EAGAIN) {
739 struct lock_queue_element qe;
740
741 queue_path(f, &qe, nodeid1, name1, !!wnode1);
742 debug_path(f, " path2", nodeid2, name2, !!wnode2);
743 do {
744 wait_on_path(f, &qe, nodeid1, name1, !!wnode1);
745 debug_path(f, " path2", nodeid2, name2, !!wnode2);
746 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
747 path1, path2, wnode1, wnode2,
748 ticket);
749 wake_up_next(&qe);
750 } while (err == -EAGAIN);
751 dequeue_path(f, &qe, nodeid1, name1, !!wnode1);
752 debug_path(f, " path2", nodeid2, name2, !!wnode2);
753 }
754 pthread_mutex_unlock(&f->lock);
755
756 return err;
757}
758
759static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid,
760 struct node *wnode, char *path)
761{
762 pthread_mutex_lock(&f->lock);
763 unlock_path(f, nodeid, wnode, NULL, 0);
764 wake_up_first(f);
765 pthread_mutex_unlock(&f->lock);
766 free(path);
767}
768
769static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path)
770{
771 if (path)
772 free_path_wrlock(f, nodeid, NULL, path);
773}
774
775static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2,
776 struct node *wnode1, struct node *wnode2,
777 char *path1, char *path2)
778{
779 pthread_mutex_lock(&f->lock);
780 unlock_path(f, nodeid1, wnode1, NULL, 0);
781 unlock_path(f, nodeid2, wnode2, NULL, 0);
782 wake_up_first(f);
783 pthread_mutex_unlock(&f->lock);
784 free(path1);
785 free(path2);
786}
787
788static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
789{
790 struct node *node;
791 if (nodeid == FUSE_ROOT_ID)
792 return;
793 pthread_mutex_lock(&f->lock);
794 node = get_node(f, nodeid);
795
796 /*
797 * Node may still be locked due to interrupt idiocy in open,
798 * create and opendir
799 */
800 while (node->nlookup == nlookup && node->treelock) {
801 struct lock_queue_element qe;
802
803 queue_path(f, &qe, node->nodeid, NULL, 0);
804 do {
805 wait_on_path(f, &qe, node->nodeid, NULL, 0);
806 wake_up_next(&qe);
807
808 } while (node->nlookup == nlookup && node->treelock);
809 dequeue_path(f, &qe, node->nodeid, NULL, 0);
810 }
811
812 assert(node->nlookup >= nlookup);
813 node->nlookup -= nlookup;
814 if (!node->nlookup) {
815 unhash_name(f, node);
816 unref_node(f, node);
817 }
818 pthread_mutex_unlock(&f->lock);
819}
820
821static void unlink_node(struct fuse *f, struct node *node)
822{
823 if (f->conf.noforget) {
824 assert(node->nlookup > 1);
825 node->nlookup--;
826 }
827 unhash_name(f, node);
828}
829
830static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
831{
832 struct node *node;
833
834 pthread_mutex_lock(&f->lock);
835 node = lookup_node(f, dir, name);
836 if (node != NULL)
837 unlink_node(f, node);
838 pthread_mutex_unlock(&f->lock);
839}
840
841static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
842 fuse_ino_t newdir, const char *newname, int hide)
843{
844 struct node *node;
845 struct node *newnode;
846 int err = 0;
847
848 pthread_mutex_lock(&f->lock);
849 node = lookup_node(f, olddir, oldname);
850 newnode = lookup_node(f, newdir, newname);
851 if (node == NULL)
852 goto out;
853
854 if (newnode != NULL) {
855 if (hide) {
856 fprintf(stderr, "fuse: hidden file got created during hiding\n");
857 err = -EBUSY;
858 goto out;
859 }
860 unlink_node(f, newnode);
861 }
862
863 unhash_name(f, node);
864 if (hash_name(f, node, newdir, newname) == -1) {
865 err = -ENOMEM;
866 goto out;
867 }
868
869 if (hide)
870 node->is_hidden = 1;
871
872out:
873 pthread_mutex_unlock(&f->lock);
874 return err;
875}
876
877static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
878{
879 if (!f->conf.use_ino)
880 stbuf->st_ino = nodeid;
881 if (f->conf.set_mode)
882 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
883 (0777 & ~f->conf.umask);
884 if (f->conf.set_uid)
885 stbuf->st_uid = f->conf.uid;
886 if (f->conf.set_gid)
887 stbuf->st_gid = f->conf.gid;
888}
889
890static struct fuse *req_fuse(fuse_req_t req)
891{
892 return (struct fuse *) fuse_req_userdata(req);
893}
894
895static void fuse_intr_sighandler(int sig)
896{
897 (void) sig;
898 /* Nothing to do */
899}
900
901struct fuse_intr_data {
902 pthread_t id;
903 pthread_cond_t cond;
904 int finished;
905};
906
907static void fuse_interrupt(fuse_req_t req, void *d_)
908{
909 struct fuse_intr_data *d = d_;
910 struct fuse *f = req_fuse(req);
911
912 if (d->id == pthread_self())
913 return;
914
915 pthread_mutex_lock(&f->lock);
916 while (!d->finished) {
917 struct timeval now;
918 struct timespec timeout;
919
920 pthread_kill(d->id, f->conf.intr_signal);
921 gettimeofday(&now, NULL);
922 timeout.tv_sec = now.tv_sec + 1;
923 timeout.tv_nsec = now.tv_usec * 1000;
924 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
925 }
926 pthread_mutex_unlock(&f->lock);
927}
928
929static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
930 struct fuse_intr_data *d)
931{
932 pthread_mutex_lock(&f->lock);
933 d->finished = 1;
934 pthread_cond_broadcast(&d->cond);
935 pthread_mutex_unlock(&f->lock);
936 fuse_req_interrupt_func(req, NULL, NULL);
937 pthread_cond_destroy(&d->cond);
938}
939
940static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
941{
942 d->id = pthread_self();
943 pthread_cond_init(&d->cond, NULL);
944 d->finished = 0;
945 fuse_req_interrupt_func(req, fuse_interrupt, d);
946}
947
948static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
949 struct fuse_intr_data *d)
950{
951 if (f->conf.intr)
952 fuse_do_finish_interrupt(f, req, d);
953}
954
955static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
956 struct fuse_intr_data *d)
957{
958 if (f->conf.intr)
959 fuse_do_prepare_interrupt(req, d);
960}
961
962#ifndef __FreeBSD__
963
964static int fuse_compat_open(struct fuse_fs *fs, const char *path,
965 struct fuse_file_info *fi)
966{
967 int err;
968 if (!fs->compat || fs->compat >= 25)
969 err = fs->op.open(path, fi);
970 else if (fs->compat == 22) {
971 struct fuse_file_info_compat tmp;
972 memcpy(&tmp, fi, sizeof(tmp));
973 err = ((struct fuse_operations_compat22 *) &fs->op)->open(path,
974 &tmp);
975 memcpy(fi, &tmp, sizeof(tmp));
976 fi->fh = tmp.fh;
977 } else
978 err = ((struct fuse_operations_compat2 *) &fs->op)
979 ->open(path, fi->flags);
980 return err;
981}
982
983static int fuse_compat_release(struct fuse_fs *fs, const char *path,
984 struct fuse_file_info *fi)
985{
986 if (!fs->compat || fs->compat >= 22)
987 return fs->op.release(path, fi);
988 else
989 return ((struct fuse_operations_compat2 *) &fs->op)
990 ->release(path, fi->flags);
991}
992
993static int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
994 struct fuse_file_info *fi)
995{
996 if (!fs->compat || fs->compat >= 25)
997 return fs->op.opendir(path, fi);
998 else {
999 int err;
1000 struct fuse_file_info_compat tmp;
1001 memcpy(&tmp, fi, sizeof(tmp));
1002 err = ((struct fuse_operations_compat22 *) &fs->op)
1003 ->opendir(path, &tmp);
1004 memcpy(fi, &tmp, sizeof(tmp));
1005 fi->fh = tmp.fh;
1006 return err;
1007 }
1008}
1009
1010static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,
1011 struct statvfs *stbuf)
1012{
1013 stbuf->f_bsize = compatbuf->block_size;
1014 stbuf->f_blocks = compatbuf->blocks;
1015 stbuf->f_bfree = compatbuf->blocks_free;
1016 stbuf->f_bavail = compatbuf->blocks_free;
1017 stbuf->f_files = compatbuf->files;
1018 stbuf->f_ffree = compatbuf->files_free;
1019 stbuf->f_namemax = compatbuf->namelen;
1020}
1021
1022static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf)
1023{
1024 stbuf->f_bsize = oldbuf->f_bsize;
1025 stbuf->f_blocks = oldbuf->f_blocks;
1026 stbuf->f_bfree = oldbuf->f_bfree;
1027 stbuf->f_bavail = oldbuf->f_bavail;
1028 stbuf->f_files = oldbuf->f_files;
1029 stbuf->f_ffree = oldbuf->f_ffree;
1030 stbuf->f_namemax = oldbuf->f_namelen;
1031}
1032
1033static int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1034 struct statvfs *buf)
1035{
1036 int err;
1037
1038 if (!fs->compat || fs->compat >= 25) {
1039 err = fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1040 } else if (fs->compat > 11) {
1041 struct statfs oldbuf;
1042 err = ((struct fuse_operations_compat22 *) &fs->op)
1043 ->statfs("/", &oldbuf);
1044 if (!err)
1045 convert_statfs_old(&oldbuf, buf);
1046 } else {
1047 struct fuse_statfs_compat1 compatbuf;
1048 memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));
1049 err = ((struct fuse_operations_compat1 *) &fs->op)
1050 ->statfs(&compatbuf);
1051 if (!err)
1052 convert_statfs_compat(&compatbuf, buf);
1053 }
1054 return err;
1055}
1056
1057#else /* __FreeBSD__ */
1058
1059static inline int fuse_compat_open(struct fuse_fs *fs, char *path,
1060 struct fuse_file_info *fi)
1061{
1062 return fs->op.open(path, fi);
1063}
1064
1065static inline int fuse_compat_release(struct fuse_fs *fs, const char *path,
1066 struct fuse_file_info *fi)
1067{
1068 return fs->op.release(path, fi);
1069}
1070
1071static inline int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1072 struct fuse_file_info *fi)
1073{
1074 return fs->op.opendir(path, fi);
1075}
1076
1077static inline int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1078 struct statvfs *buf)
1079{
1080 return fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1081}
1082
1083#endif /* __FreeBSD__ */
1084
1085int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
1086{
1087 fuse_get_context()->private_data = fs->user_data;
1088 if (fs->op.getattr) {
1089 if (fs->debug)
1090 fprintf(stderr, "getattr %s\n", path);
1091
1092 return fs->op.getattr(path, buf);
1093 } else {
1094 return -ENOSYS;
1095 }
1096}
1097
1098int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
1099 struct fuse_file_info *fi)
1100{
1101 fuse_get_context()->private_data = fs->user_data;
1102 if (fs->op.fgetattr) {
1103 if (fs->debug)
1104 fprintf(stderr, "fgetattr[%llu] %s\n",
1105 (unsigned long long) fi->fh, path);
1106
1107 return fs->op.fgetattr(path, buf, fi);
1108 } else if (path && fs->op.getattr) {
1109 if (fs->debug)
1110 fprintf(stderr, "getattr %s\n", path);
1111
1112 return fs->op.getattr(path, buf);
1113 } else {
1114 return -ENOSYS;
1115 }
1116}
1117
1118int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
1119 const char *newpath)
1120{
1121 fuse_get_context()->private_data = fs->user_data;
1122 if (fs->op.rename) {
1123 if (fs->debug)
1124 fprintf(stderr, "rename %s %s\n", oldpath, newpath);
1125
1126 return fs->op.rename(oldpath, newpath);
1127 } else {
1128 return -ENOSYS;
1129 }
1130}
1131
1132int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
1133{
1134 fuse_get_context()->private_data = fs->user_data;
1135 if (fs->op.unlink) {
1136 if (fs->debug)
1137 fprintf(stderr, "unlink %s\n", path);
1138
1139 return fs->op.unlink(path);
1140 } else {
1141 return -ENOSYS;
1142 }
1143}
1144
1145int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
1146{
1147 fuse_get_context()->private_data = fs->user_data;
1148 if (fs->op.rmdir) {
1149 if (fs->debug)
1150 fprintf(stderr, "rmdir %s\n", path);
1151
1152 return fs->op.rmdir(path);
1153 } else {
1154 return -ENOSYS;
1155 }
1156}
1157
1158int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
1159{
1160 fuse_get_context()->private_data = fs->user_data;
1161 if (fs->op.symlink) {
1162 if (fs->debug)
1163 fprintf(stderr, "symlink %s %s\n", linkname, path);
1164
1165 return fs->op.symlink(linkname, path);
1166 } else {
1167 return -ENOSYS;
1168 }
1169}
1170
1171int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
1172{
1173 fuse_get_context()->private_data = fs->user_data;
1174 if (fs->op.link) {
1175 if (fs->debug)
1176 fprintf(stderr, "link %s %s\n", oldpath, newpath);
1177
1178 return fs->op.link(oldpath, newpath);
1179 } else {
1180 return -ENOSYS;
1181 }
1182}
1183
1184int fuse_fs_release(struct fuse_fs *fs, const char *path,
1185 struct fuse_file_info *fi)
1186{
1187 fuse_get_context()->private_data = fs->user_data;
1188 if (fs->op.release) {
1189 if (fs->debug)
1190 fprintf(stderr, "release%s[%llu] flags: 0x%x\n",
1191 fi->flush ? "+flush" : "",
1192 (unsigned long long) fi->fh, fi->flags);
1193
1194 return fuse_compat_release(fs, path, fi);
1195 } else {
1196 return 0;
1197 }
1198}
1199
1200int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
1201 struct fuse_file_info *fi)
1202{
1203 fuse_get_context()->private_data = fs->user_data;
1204 if (fs->op.opendir) {
1205 int err;
1206
1207 if (fs->debug)
1208 fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags,
1209 path);
1210
1211 err = fuse_compat_opendir(fs, path, fi);
1212
1213 if (fs->debug && !err)
1214 fprintf(stderr, " opendir[%lli] flags: 0x%x %s\n",
1215 (unsigned long long) fi->fh, fi->flags, path);
1216
1217 return err;
1218 } else {
1219 return 0;
1220 }
1221}
1222
1223int fuse_fs_open(struct fuse_fs *fs, const char *path,
1224 struct fuse_file_info *fi)
1225{
1226 fuse_get_context()->private_data = fs->user_data;
1227 if (fs->op.open) {
1228 int err;
1229
1230 if (fs->debug)
1231 fprintf(stderr, "open flags: 0x%x %s\n", fi->flags,
1232 path);
1233
1234 err = fuse_compat_open(fs, path, fi);
1235
1236 if (fs->debug && !err)
1237 fprintf(stderr, " open[%lli] flags: 0x%x %s\n",
1238 (unsigned long long) fi->fh, fi->flags, path);
1239
1240 return err;
1241 } else {
1242 return 0;
1243 }
1244}
1245
1246int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
1247 off64_t off, struct fuse_file_info *fi)
1248{
1249 fuse_get_context()->private_data = fs->user_data;
1250 if (fs->op.read) {
1251 int res;
1252
1253 if (fs->debug)
1254 fprintf(stderr,
1255 "read[%llu] %lu bytes from %llu flags: 0x%x\n",
1256 (unsigned long long) fi->fh,
1257 (unsigned long) size, (unsigned long long) off,
1258 fi->flags);
1259
1260 res = fs->op.read(path, buf, size, off, fi);
1261
1262 if (fs->debug && res >= 0)
1263 fprintf(stderr, " read[%llu] %u bytes from %llu\n",
1264 (unsigned long long) fi->fh, res,
1265 (unsigned long long) off);
1266 if (res > (int) size)
1267 fprintf(stderr, "fuse: read too many bytes\n");
1268
1269 return res;
1270 } else {
1271 return -ENOSYS;
1272 }
1273}
1274
1275int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf,
1276 size_t size, off64_t off, struct fuse_file_info *fi)
1277{
1278 fuse_get_context()->private_data = fs->user_data;
1279 if (fs->op.write) {
1280 int res;
1281
1282 if (fs->debug)
1283 fprintf(stderr,
1284 "write%s[%llu] %lu bytes to %llu flags: 0x%x\n",
1285 fi->writepage ? "page" : "",
1286 (unsigned long long) fi->fh,
1287 (unsigned long) size, (unsigned long long) off,
1288 fi->flags);
1289
1290 res = fs->op.write(path, buf, size, off, fi);
1291
1292 if (fs->debug && res >= 0)
1293 fprintf(stderr, " write%s[%llu] %u bytes to %llu\n",
1294 fi->writepage ? "page" : "",
1295 (unsigned long long) fi->fh, res,
1296 (unsigned long long) off);
1297 if (res > (int) size)
1298 fprintf(stderr, "fuse: wrote too many bytes\n");
1299
1300 return res;
1301 } else {
1302 return -ENOSYS;
1303 }
1304}
1305
1306int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
1307 struct fuse_file_info *fi)
1308{
1309 fuse_get_context()->private_data = fs->user_data;
1310 if (fs->op.fsync) {
1311 if (fs->debug)
1312 fprintf(stderr, "fsync[%llu] datasync: %i\n",
1313 (unsigned long long) fi->fh, datasync);
1314
1315 return fs->op.fsync(path, datasync, fi);
1316 } else {
1317 return -ENOSYS;
1318 }
1319}
1320
1321int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
1322 struct fuse_file_info *fi)
1323{
1324 fuse_get_context()->private_data = fs->user_data;
1325 if (fs->op.fsyncdir) {
1326 if (fs->debug)
1327 fprintf(stderr, "fsyncdir[%llu] datasync: %i\n",
1328 (unsigned long long) fi->fh, datasync);
1329
1330 return fs->op.fsyncdir(path, datasync, fi);
1331 } else {
1332 return -ENOSYS;
1333 }
1334}
1335
1336int fuse_fs_flush(struct fuse_fs *fs, const char *path,
1337 struct fuse_file_info *fi)
1338{
1339 fuse_get_context()->private_data = fs->user_data;
1340 if (fs->op.flush) {
1341 if (fs->debug)
1342 fprintf(stderr, "flush[%llu]\n",
1343 (unsigned long long) fi->fh);
1344
1345 return fs->op.flush(path, fi);
1346 } else {
1347 return -ENOSYS;
1348 }
1349}
1350
1351int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
1352{
1353 fuse_get_context()->private_data = fs->user_data;
1354 if (fs->op.statfs) {
1355 if (fs->debug)
1356 fprintf(stderr, "statfs %s\n", path);
1357
1358 return fuse_compat_statfs(fs, path, buf);
1359 } else {
1360 buf->f_namemax = 255;
1361 buf->f_bsize = 512;
1362 return 0;
1363 }
1364}
1365
1366int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
1367 struct fuse_file_info *fi)
1368{
1369 fuse_get_context()->private_data = fs->user_data;
1370 if (fs->op.releasedir) {
1371 if (fs->debug)
1372 fprintf(stderr, "releasedir[%llu] flags: 0x%x\n",
1373 (unsigned long long) fi->fh, fi->flags);
1374
1375 return fs->op.releasedir(path, fi);
1376 } else {
1377 return 0;
1378 }
1379}
1380
1381static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
1382 ino_t ino)
1383{
1384 int res;
1385 struct stat stbuf;
1386
1387 memset(&stbuf, 0, sizeof(stbuf));
1388 stbuf.st_mode = type << 12;
1389 stbuf.st_ino = ino;
1390
1391 res = dh->filler(dh->buf, name, &stbuf, 0);
1392 return res ? -ENOMEM : 0;
1393}
1394
1395int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
1396 fuse_fill_dir_t filler, off64_t off,
1397 struct fuse_file_info *fi)
1398{
1399 fuse_get_context()->private_data = fs->user_data;
1400 if (fs->op.readdir) {
1401 if (fs->debug)
1402 fprintf(stderr, "readdir[%llu] from %llu\n",
1403 (unsigned long long) fi->fh,
1404 (unsigned long long) off);
1405
1406 return fs->op.readdir(path, buf, filler, off, fi);
1407 } else if (fs->op.getdir) {
1408 struct fuse_dirhandle dh;
1409
1410 if (fs->debug)
1411 fprintf(stderr, "getdir[%llu]\n",
1412 (unsigned long long) fi->fh);
1413
1414 dh.filler = filler;
1415 dh.buf = buf;
1416 return fs->op.getdir(path, &dh, fill_dir_old);
1417 } else {
1418 return -ENOSYS;
1419 }
1420}
1421
1422int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
1423 struct fuse_file_info *fi)
1424{
1425 fuse_get_context()->private_data = fs->user_data;
1426 if (fs->op.create) {
1427 int err;
1428
1429 if (fs->debug)
1430 fprintf(stderr,
1431 "create flags: 0x%x %s 0%o umask=0%03o\n",
1432 fi->flags, path, mode,
1433 fuse_get_context()->umask);
1434
1435 err = fs->op.create(path, mode, fi);
1436
1437 if (fs->debug && !err)
1438 fprintf(stderr, " create[%llu] flags: 0x%x %s\n",
1439 (unsigned long long) fi->fh, fi->flags, path);
1440
1441 return err;
1442 } else {
1443 return -ENOSYS;
1444 }
1445}
1446
1447int fuse_fs_lock(struct fuse_fs *fs, const char *path,
1448 struct fuse_file_info *fi, int cmd, struct flock *lock)
1449{
1450 fuse_get_context()->private_data = fs->user_data;
1451 if (fs->op.lock) {
1452 if (fs->debug)
1453 fprintf(stderr, "lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
1454 (unsigned long long) fi->fh,
1455 (cmd == F_GETLK ? "F_GETLK" :
1456 (cmd == F_SETLK ? "F_SETLK" :
1457 (cmd == F_SETLKW ? "F_SETLKW" : "???"))),
1458 (lock->l_type == F_RDLCK ? "F_RDLCK" :
1459 (lock->l_type == F_WRLCK ? "F_WRLCK" :
1460 (lock->l_type == F_UNLCK ? "F_UNLCK" :
1461 "???"))),
1462 (unsigned long long) lock->l_start,
1463 (unsigned long long) lock->l_len,
1464 (unsigned long long) lock->l_pid);
1465
1466 return fs->op.lock(path, fi, cmd, lock);
1467 } else {
1468 return -ENOSYS;
1469 }
1470}
1471
1472int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
1473{
1474 fuse_get_context()->private_data = fs->user_data;
1475 if (fs->op.chown) {
1476 if (fs->debug)
1477 fprintf(stderr, "chown %s %lu %lu\n", path,
1478 (unsigned long) uid, (unsigned long) gid);
1479
1480 return fs->op.chown(path, uid, gid);
1481 } else {
1482 return -ENOSYS;
1483 }
1484}
1485
1486int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off64_t size)
1487{
1488 fuse_get_context()->private_data = fs->user_data;
1489 if (fs->op.truncate) {
1490 if (fs->debug)
1491 fprintf(stderr, "truncate %s %llu\n", path,
1492 (unsigned long long) size);
1493
1494 return fs->op.truncate(path, size);
1495 } else {
1496 return -ENOSYS;
1497 }
1498}
1499
1500int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off64_t size,
1501 struct fuse_file_info *fi)
1502{
1503 fuse_get_context()->private_data = fs->user_data;
1504 if (fs->op.ftruncate) {
1505 if (fs->debug)
1506 fprintf(stderr, "ftruncate[%llu] %s %llu\n",
1507 (unsigned long long) fi->fh, path,
1508 (unsigned long long) size);
1509
1510 return fs->op.ftruncate(path, size, fi);
1511 } else if (path && fs->op.truncate) {
1512 if (fs->debug)
1513 fprintf(stderr, "truncate %s %llu\n", path,
1514 (unsigned long long) size);
1515
1516 return fs->op.truncate(path, size);
1517 } else {
1518 return -ENOSYS;
1519 }
1520}
1521
1522int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
1523 const struct timespec tv[2])
1524{
1525 fuse_get_context()->private_data = fs->user_data;
1526 if (fs->op.utimens) {
1527 if (fs->debug)
1528 fprintf(stderr, "utimens %s %li.%09lu %li.%09lu\n",
1529 path, tv[0].tv_sec, tv[0].tv_nsec,
1530 tv[1].tv_sec, tv[1].tv_nsec);
1531
1532 return fs->op.utimens(path, tv);
1533 } else if(fs->op.utime) {
1534 struct utimbuf buf;
1535
1536 if (fs->debug)
1537 fprintf(stderr, "utime %s %li %li\n", path,
1538 tv[0].tv_sec, tv[1].tv_sec);
1539
1540 buf.actime = tv[0].tv_sec;
1541 buf.modtime = tv[1].tv_sec;
1542 return fs->op.utime(path, &buf);
1543 } else {
1544 return -ENOSYS;
1545 }
1546}
1547
1548int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
1549{
1550 fuse_get_context()->private_data = fs->user_data;
1551 if (fs->op.access) {
1552 if (fs->debug)
1553 fprintf(stderr, "access %s 0%o\n", path, mask);
1554
1555 return fs->op.access(path, mask);
1556 } else {
1557 return -ENOSYS;
1558 }
1559}
1560
1561int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
1562 size_t len)
1563{
1564 fuse_get_context()->private_data = fs->user_data;
1565 if (fs->op.readlink) {
1566 if (fs->debug)
1567 fprintf(stderr, "readlink %s %lu\n", path,
1568 (unsigned long) len);
1569
1570 return fs->op.readlink(path, buf, len);
1571 } else {
1572 return -ENOSYS;
1573 }
1574}
1575
1576int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
1577 dev_t rdev)
1578{
1579 fuse_get_context()->private_data = fs->user_data;
1580 if (fs->op.mknod) {
1581 if (fs->debug)
1582 fprintf(stderr, "mknod %s 0%o 0x%llx umask=0%03o\n",
1583 path, mode, (unsigned long long) rdev,
1584 fuse_get_context()->umask);
1585
1586 return fs->op.mknod(path, mode, rdev);
1587 } else {
1588 return -ENOSYS;
1589 }
1590}
1591
1592int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
1593{
1594 fuse_get_context()->private_data = fs->user_data;
1595 if (fs->op.mkdir) {
1596 if (fs->debug)
1597 fprintf(stderr, "mkdir %s 0%o umask=0%03o\n",
1598 path, mode, fuse_get_context()->umask);
1599
1600 return fs->op.mkdir(path, mode);
1601 } else {
1602 return -ENOSYS;
1603 }
1604}
1605
1606int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
1607 const char *value, size_t size, int flags)
1608{
1609 fuse_get_context()->private_data = fs->user_data;
1610 if (fs->op.setxattr) {
1611 if (fs->debug)
1612 fprintf(stderr, "setxattr %s %s %lu 0x%x\n",
1613 path, name, (unsigned long) size, flags);
1614
1615 return fs->op.setxattr(path, name, value, size, flags);
1616 } else {
1617 return -ENOSYS;
1618 }
1619}
1620
1621int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
1622 char *value, size_t size)
1623{
1624 fuse_get_context()->private_data = fs->user_data;
1625 if (fs->op.getxattr) {
1626 if (fs->debug)
1627 fprintf(stderr, "getxattr %s %s %lu\n",
1628 path, name, (unsigned long) size);
1629
1630 return fs->op.getxattr(path, name, value, size);
1631 } else {
1632 return -ENOSYS;
1633 }
1634}
1635
1636int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
1637 size_t size)
1638{
1639 fuse_get_context()->private_data = fs->user_data;
1640 if (fs->op.listxattr) {
1641 if (fs->debug)
1642 fprintf(stderr, "listxattr %s %lu\n",
1643 path, (unsigned long) size);
1644
1645 return fs->op.listxattr(path, list, size);
1646 } else {
1647 return -ENOSYS;
1648 }
1649}
1650
1651int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
1652 uint64_t *idx)
1653{
1654 fuse_get_context()->private_data = fs->user_data;
1655 if (fs->op.bmap) {
1656 if (fs->debug)
1657 fprintf(stderr, "bmap %s blocksize: %lu index: %llu\n",
1658 path, (unsigned long) blocksize,
1659 (unsigned long long) *idx);
1660
1661 return fs->op.bmap(path, blocksize, idx);
1662 } else {
1663 return -ENOSYS;
1664 }
1665}
1666
1667int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
1668{
1669 fuse_get_context()->private_data = fs->user_data;
1670 if (fs->op.removexattr) {
1671 if (fs->debug)
1672 fprintf(stderr, "removexattr %s %s\n", path, name);
1673
1674 return fs->op.removexattr(path, name);
1675 } else {
1676 return -ENOSYS;
1677 }
1678}
1679
1680int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
1681 struct fuse_file_info *fi, unsigned int flags, void *data)
1682{
1683 fuse_get_context()->private_data = fs->user_data;
1684 if (fs->op.ioctl) {
1685 if (fs->debug)
1686 fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
1687 (unsigned long long) fi->fh, cmd, flags);
1688
1689 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
1690 } else
1691 return -ENOSYS;
1692}
1693
1694int fuse_fs_poll(struct fuse_fs *fs, const char *path,
1695 struct fuse_file_info *fi, struct fuse_pollhandle *ph,
1696 unsigned *reventsp)
1697{
1698 fuse_get_context()->private_data = fs->user_data;
1699 if (fs->op.poll) {
1700 int res;
1701
1702 if (fs->debug)
1703 fprintf(stderr, "poll[%llu] ph: %p\n",
1704 (unsigned long long) fi->fh, ph);
1705
1706 res = fs->op.poll(path, fi, ph, reventsp);
1707
1708 if (fs->debug && !res)
1709 fprintf(stderr, " poll[%llu] revents: 0x%x\n",
1710 (unsigned long long) fi->fh, *reventsp);
1711
1712 return res;
1713 } else
1714 return -ENOSYS;
1715}
1716
1717static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
1718{
1719 struct node *node;
1720 int isopen = 0;
1721 pthread_mutex_lock(&f->lock);
1722 node = lookup_node(f, dir, name);
1723 if (node && node->open_count > 0)
1724 isopen = 1;
1725 pthread_mutex_unlock(&f->lock);
1726 return isopen;
1727}
1728
1729static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
1730 char *newname, size_t bufsize)
1731{
1732 struct stat buf;
1733 struct node *node;
1734 struct node *newnode;
1735 char *newpath;
1736 int res;
1737 int failctr = 10;
1738
1739 do {
1740 pthread_mutex_lock(&f->lock);
1741 node = lookup_node(f, dir, oldname);
1742 if (node == NULL) {
1743 pthread_mutex_unlock(&f->lock);
1744 return NULL;
1745 }
1746 do {
1747 f->hidectr ++;
1748 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
1749 (unsigned int) node->nodeid, f->hidectr);
1750 newnode = lookup_node(f, dir, newname);
1751 } while(newnode);
1752
1753 try_get_path(f, dir, newname, &newpath, NULL, 0);
1754 pthread_mutex_unlock(&f->lock);
1755
1756 if (!newpath)
1757 break;
1758
1759 res = fuse_fs_getattr(f->fs, newpath, &buf);
1760 if (res == -ENOENT)
1761 break;
1762 free(newpath);
1763 newpath = NULL;
1764 } while(res == 0 && --failctr);
1765
1766 return newpath;
1767}
1768
1769static int hide_node(struct fuse *f, const char *oldpath,
1770 fuse_ino_t dir, const char *oldname)
1771{
1772 char newname[64];
1773 char *newpath;
1774 int err = -EBUSY;
1775
1776 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
1777 if (newpath) {
1778 err = fuse_fs_rename(f->fs, oldpath, newpath);
1779 if (!err)
1780 err = rename_node(f, dir, oldname, dir, newname, 1);
1781 free(newpath);
1782 }
1783 return err;
1784}
1785
1786static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
1787{
1788 return stbuf->st_mtime == ts->tv_sec &&
1789 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
1790}
1791
1792#ifndef CLOCK_MONOTONIC
1793#define CLOCK_MONOTONIC CLOCK_REALTIME
1794#endif
1795
1796static void curr_time(struct timespec *now)
1797{
1798 static clockid_t clockid = CLOCK_MONOTONIC;
1799 int res = clock_gettime(clockid, now);
1800 if (res == -1 && errno == EINVAL) {
1801 clockid = CLOCK_REALTIME;
1802 res = clock_gettime(clockid, now);
1803 }
1804 if (res == -1) {
1805 perror("fuse: clock_gettime");
1806 abort();
1807 }
1808}
1809
1810static void update_stat(struct node *node, const struct stat *stbuf)
1811{
1812 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
1813 stbuf->st_size != node->size))
1814 node->cache_valid = 0;
1815 node->mtime.tv_sec = stbuf->st_mtime;
1816 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
1817 node->size = stbuf->st_size;
1818 curr_time(&node->stat_updated);
1819}
1820
1821static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
1822 const char *name, const char *path,
1823 struct fuse_entry_param *e, struct fuse_file_info *fi)
1824{
1825 int res;
1826
1827 memset(e, 0, sizeof(struct fuse_entry_param));
1828 if (fi)
1829 res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
1830 else
1831 res = fuse_fs_getattr(f->fs, path, &e->attr);
1832 if (res == 0) {
1833 struct node *node;
1834
1835 node = find_node(f, nodeid, name);
1836 if (node == NULL)
1837 res = -ENOMEM;
1838 else {
1839 e->ino = node->nodeid;
1840 e->generation = node->generation;
1841 e->entry_timeout = f->conf.entry_timeout;
1842 e->attr_timeout = f->conf.attr_timeout;
1843 if (f->conf.auto_cache) {
1844 pthread_mutex_lock(&f->lock);
1845 update_stat(node, &e->attr);
1846 pthread_mutex_unlock(&f->lock);
1847 }
1848 set_stat(f, e->ino, &e->attr);
1849 if (f->conf.debug)
1850 fprintf(stderr, " NODEID: %lu\n",
1851 (unsigned long) e->ino);
1852 }
1853 }
1854 return res;
1855}
1856
1857static struct fuse_context_i *fuse_get_context_internal(void)
1858{
1859 struct fuse_context_i *c;
1860
1861 c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
1862 if (c == NULL) {
1863 c = (struct fuse_context_i *)
1864 malloc(sizeof(struct fuse_context_i));
1865 if (c == NULL) {
1866 /* This is hard to deal with properly, so just
1867 abort. If memory is so low that the
1868 context cannot be allocated, there's not
1869 much hope for the filesystem anyway */
1870 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
1871 abort();
1872 }
1873 pthread_setspecific(fuse_context_key, c);
1874 }
1875 return c;
1876}
1877
1878static void fuse_freecontext(void *data)
1879{
1880 free(data);
1881}
1882
1883static int fuse_create_context_key(void)
1884{
1885 int err = 0;
1886 pthread_mutex_lock(&fuse_context_lock);
1887 if (!fuse_context_ref) {
1888 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
1889 if (err) {
1890 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
1891 strerror(err));
1892 pthread_mutex_unlock(&fuse_context_lock);
1893 return -1;
1894 }
1895 }
1896 fuse_context_ref++;
1897 pthread_mutex_unlock(&fuse_context_lock);
1898 return 0;
1899}
1900
1901static void fuse_delete_context_key(void)
1902{
1903 pthread_mutex_lock(&fuse_context_lock);
1904 fuse_context_ref--;
1905 if (!fuse_context_ref) {
1906 free(pthread_getspecific(fuse_context_key));
1907 pthread_key_delete(fuse_context_key);
1908 }
1909 pthread_mutex_unlock(&fuse_context_lock);
1910}
1911
1912static struct fuse *req_fuse_prepare(fuse_req_t req)
1913{
1914 struct fuse_context_i *c = fuse_get_context_internal();
1915 const struct fuse_ctx *ctx = fuse_req_ctx(req);
1916 c->req = req;
1917 c->ctx.fuse = req_fuse(req);
1918 c->ctx.uid = ctx->uid;
1919 c->ctx.gid = ctx->gid;
1920 c->ctx.pid = ctx->pid;
1921 c->ctx.umask = ctx->umask;
1922 return c->ctx.fuse;
1923}
1924
1925static inline void reply_err(fuse_req_t req, int err)
1926{
1927 /* fuse_reply_err() uses non-negated errno values */
1928 fuse_reply_err(req, -err);
1929}
1930
1931static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
1932 int err)
1933{
1934 if (!err) {
1935 struct fuse *f = req_fuse(req);
1936 if (fuse_reply_entry(req, e) == -ENOENT) {
1937 /* Skip forget for negative result */
1938 if (e->ino != 0)
1939 forget_node(f, e->ino, 1);
1940 }
1941 } else
1942 reply_err(req, err);
1943}
1944
1945void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
1946{
1947 fuse_get_context()->private_data = fs->user_data;
1948 if (fs->op.init)
1949 fs->user_data = fs->op.init(conn);
1950}
1951
1952static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
1953{
1954 struct fuse *f = (struct fuse *) data;
1955 struct fuse_context_i *c = fuse_get_context_internal();
1956
1957 memset(c, 0, sizeof(*c));
1958 c->ctx.fuse = f;
1959 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
1960 fuse_fs_init(f->fs, conn);
1961}
1962
1963void fuse_fs_destroy(struct fuse_fs *fs)
1964{
1965 fuse_get_context()->private_data = fs->user_data;
1966 if (fs->op.destroy)
1967 fs->op.destroy(fs->user_data);
1968 if (fs->m)
1969 fuse_put_module(fs->m);
1970 free(fs);
1971}
1972
1973static void fuse_lib_destroy(void *data)
1974{
1975 struct fuse *f = (struct fuse *) data;
1976 struct fuse_context_i *c = fuse_get_context_internal();
1977
1978 memset(c, 0, sizeof(*c));
1979 c->ctx.fuse = f;
1980 fuse_fs_destroy(f->fs);
1981 f->fs = NULL;
1982}
1983
1984static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
1985 const char *name)
1986{
1987 struct fuse *f = req_fuse_prepare(req);
1988 struct fuse_entry_param e;
1989 char *path;
1990 int err;
1991 struct node *dot = NULL;
1992
1993 if (name[0] == '.') {
1994 int len = strlen(name);
1995
1996 if (len == 1 || (name[1] == '.' && len == 2)) {
1997 pthread_mutex_lock(&f->lock);
1998 if (len == 1) {
1999 if (f->conf.debug)
2000 fprintf(stderr, "LOOKUP-DOT\n");
2001 dot = get_node_nocheck(f, parent);
2002 if (dot == NULL) {
2003 pthread_mutex_unlock(&f->lock);
2004 reply_entry(req, &e, -ESTALE);
2005 return;
2006 }
2007 dot->refctr++;
2008 } else {
2009 if (f->conf.debug)
2010 fprintf(stderr, "LOOKUP-DOTDOT\n");
2011 parent = get_node(f, parent)->parent->nodeid;
2012 }
2013 pthread_mutex_unlock(&f->lock);
2014 name = NULL;
2015 }
2016 }
2017
2018 err = get_path_name(f, parent, name, &path);
2019 if (!err) {
2020 struct fuse_intr_data d;
2021 if (f->conf.debug)
2022 fprintf(stderr, "LOOKUP %s\n", path);
2023 fuse_prepare_interrupt(f, req, &d);
2024 err = lookup_path(f, parent, name, path, &e, NULL);
2025 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2026 e.ino = 0;
2027 e.entry_timeout = f->conf.negative_timeout;
2028 err = 0;
2029 }
2030 fuse_finish_interrupt(f, req, &d);
2031 free_path(f, parent, path);
2032 }
2033 if (dot) {
2034 pthread_mutex_lock(&f->lock);
2035 unref_node(f, dot);
2036 pthread_mutex_unlock(&f->lock);
2037 }
2038 reply_entry(req, &e, err);
2039}
2040
2041static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
2042 unsigned long nlookup)
2043{
2044 struct fuse *f = req_fuse(req);
2045 if (f->conf.debug)
2046 fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino,
2047 nlookup);
2048 forget_node(f, ino, nlookup);
2049 fuse_reply_none(req);
2050}
2051
2052static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
2053 struct fuse_file_info *fi)
2054{
2055 struct fuse *f = req_fuse_prepare(req);
2056 struct stat buf;
2057 char *path;
2058 int err;
2059
2060 memset(&buf, 0, sizeof(buf));
2061
2062 if (fi != NULL)
2063 err = get_path_nullok(f, ino, &path);
2064 else
2065 err = get_path(f, ino, &path);
2066 if (!err) {
2067 struct fuse_intr_data d;
2068 fuse_prepare_interrupt(f, req, &d);
2069 if (fi)
2070 err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2071 else
2072 err = fuse_fs_getattr(f->fs, path, &buf);
2073 fuse_finish_interrupt(f, req, &d);
2074 free_path(f, ino, path);
2075 }
2076 if (!err) {
2077 if (f->conf.auto_cache) {
2078 pthread_mutex_lock(&f->lock);
2079 update_stat(get_node(f, ino), &buf);
2080 pthread_mutex_unlock(&f->lock);
2081 }
2082 set_stat(f, ino, &buf);
2083 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2084 } else
2085 reply_err(req, err);
2086}
2087
2088int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
2089{
2090 fuse_get_context()->private_data = fs->user_data;
2091 if (fs->op.chmod)
2092 return fs->op.chmod(path, mode);
2093 else
2094 return -ENOSYS;
2095}
2096
2097static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2098 int valid, struct fuse_file_info *fi)
2099{
2100 struct fuse *f = req_fuse_prepare(req);
2101 struct stat buf;
2102 char *path;
2103 int err;
2104
2105 err = get_path(f, ino, &path);
2106 if (!err) {
2107 struct fuse_intr_data d;
2108 fuse_prepare_interrupt(f, req, &d);
2109 err = 0;
2110 if (!err && (valid & FUSE_SET_ATTR_MODE))
2111 err = fuse_fs_chmod(f->fs, path, attr->st_mode);
2112 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2113 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2114 attr->st_uid : (uid_t) -1;
2115 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2116 attr->st_gid : (gid_t) -1;
2117 err = fuse_fs_chown(f->fs, path, uid, gid);
2118 }
2119 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2120 if (fi)
2121 err = fuse_fs_ftruncate(f->fs, path,
2122 attr->st_size, fi);
2123 else
2124 err = fuse_fs_truncate(f->fs, path,
2125 attr->st_size);
2126 }
2127 if (!err &&
2128 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2129 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2130 struct timespec tv[2];
2131 tv[0].tv_sec = attr->st_atime;
2132 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2133 tv[1].tv_sec = attr->st_mtime;
2134 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2135 err = fuse_fs_utimens(f->fs, path, tv);
2136 }
2137 if (!err)
2138 err = fuse_fs_getattr(f->fs, path, &buf);
2139 fuse_finish_interrupt(f, req, &d);
2140 free_path(f, ino, path);
2141 }
2142 if (!err) {
2143 if (f->conf.auto_cache) {
2144 pthread_mutex_lock(&f->lock);
2145 update_stat(get_node(f, ino), &buf);
2146 pthread_mutex_unlock(&f->lock);
2147 }
2148 set_stat(f, ino, &buf);
2149 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2150 } else
2151 reply_err(req, err);
2152}
2153
2154static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
2155{
2156 struct fuse *f = req_fuse_prepare(req);
2157 char *path;
2158 int err;
2159
2160 err = get_path(f, ino, &path);
2161 if (!err) {
2162 struct fuse_intr_data d;
2163
2164 fuse_prepare_interrupt(f, req, &d);
2165 err = fuse_fs_access(f->fs, path, mask);
2166 fuse_finish_interrupt(f, req, &d);
2167 free_path(f, ino, path);
2168 }
2169 reply_err(req, err);
2170}
2171
2172static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
2173{
2174 struct fuse *f = req_fuse_prepare(req);
2175 char linkname[PATH_MAX + 1];
2176 char *path;
2177 int err;
2178
2179 err = get_path(f, ino, &path);
2180 if (!err) {
2181 struct fuse_intr_data d;
2182 fuse_prepare_interrupt(f, req, &d);
2183 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
2184 fuse_finish_interrupt(f, req, &d);
2185 free_path(f, ino, path);
2186 }
2187 if (!err) {
2188 linkname[PATH_MAX] = '\0';
2189 fuse_reply_readlink(req, linkname);
2190 } else
2191 reply_err(req, err);
2192}
2193
2194static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2195 mode_t mode, dev_t rdev)
2196{
2197 struct fuse *f = req_fuse_prepare(req);
2198 struct fuse_entry_param e;
2199 char *path;
2200 int err;
2201
2202 err = get_path_name(f, parent, name, &path);
2203 if (!err) {
2204 struct fuse_intr_data d;
2205
2206 fuse_prepare_interrupt(f, req, &d);
2207 err = -ENOSYS;
2208 if (S_ISREG(mode)) {
2209 struct fuse_file_info fi;
2210
2211 memset(&fi, 0, sizeof(fi));
2212 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
2213 err = fuse_fs_create(f->fs, path, mode, &fi);
2214 if (!err) {
2215 err = lookup_path(f, parent, name, path, &e,
2216 &fi);
2217 fuse_fs_release(f->fs, path, &fi);
2218 }
2219 }
2220 if (err == -ENOSYS) {
2221 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2222 if (!err)
2223 err = lookup_path(f, parent, name, path, &e,
2224 NULL);
2225 }
2226 fuse_finish_interrupt(f, req, &d);
2227 free_path(f, parent, path);
2228 }
2229 reply_entry(req, &e, err);
2230}
2231
2232static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
2233 mode_t mode)
2234{
2235 struct fuse *f = req_fuse_prepare(req);
2236 struct fuse_entry_param e;
2237 char *path;
2238 int err;
2239
2240 err = get_path_name(f, parent, name, &path);
2241 if (!err) {
2242 struct fuse_intr_data d;
2243
2244 fuse_prepare_interrupt(f, req, &d);
2245 err = fuse_fs_mkdir(f->fs, path, mode);
2246 if (!err)
2247 err = lookup_path(f, parent, name, path, &e, NULL);
2248 fuse_finish_interrupt(f, req, &d);
2249 free_path(f, parent, path);
2250 }
2251 reply_entry(req, &e, err);
2252}
2253
2254static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
2255 const char *name)
2256{
2257 struct fuse *f = req_fuse_prepare(req);
2258 struct node *wnode;
2259 char *path;
2260 int err;
2261
2262 err = get_path_wrlock(f, parent, name, &path, &wnode);
2263 if (!err) {
2264 struct fuse_intr_data d;
2265
2266 fuse_prepare_interrupt(f, req, &d);
2267 if (!f->conf.hard_remove && is_open(f, parent, name)) {
2268 err = hide_node(f, path, parent, name);
2269 } else {
2270 err = fuse_fs_unlink(f->fs, path);
2271 if (!err)
2272 remove_node(f, parent, name);
2273 }
2274 fuse_finish_interrupt(f, req, &d);
2275 free_path_wrlock(f, parent, wnode, path);
2276 }
2277 reply_err(req, err);
2278}
2279
2280static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
2281{
2282 struct fuse *f = req_fuse_prepare(req);
2283 struct node *wnode;
2284 char *path;
2285 int err;
2286
2287 err = get_path_wrlock(f, parent, name, &path, &wnode);
2288 if (!err) {
2289 struct fuse_intr_data d;
2290
2291 fuse_prepare_interrupt(f, req, &d);
2292 err = fuse_fs_rmdir(f->fs, path);
2293 fuse_finish_interrupt(f, req, &d);
2294 if (!err)
2295 remove_node(f, parent, name);
2296 free_path_wrlock(f, parent, wnode, path);
2297 }
2298 reply_err(req, err);
2299}
2300
2301static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
2302 fuse_ino_t parent, const char *name)
2303{
2304 struct fuse *f = req_fuse_prepare(req);
2305 struct fuse_entry_param e;
2306 char *path;
2307 int err;
2308
2309 err = get_path_name(f, parent, name, &path);
2310 if (!err) {
2311 struct fuse_intr_data d;
2312
2313 fuse_prepare_interrupt(f, req, &d);
2314 err = fuse_fs_symlink(f->fs, linkname, path);
2315 if (!err)
2316 err = lookup_path(f, parent, name, path, &e, NULL);
2317 fuse_finish_interrupt(f, req, &d);
2318 free_path(f, parent, path);
2319 }
2320 reply_entry(req, &e, err);
2321}
2322
2323static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
2324 const char *oldname, fuse_ino_t newdir,
2325 const char *newname)
2326{
2327 struct fuse *f = req_fuse_prepare(req);
2328 char *oldpath;
2329 char *newpath;
2330 struct node *wnode1;
2331 struct node *wnode2;
2332 int err;
2333
2334 err = get_path2(f, olddir, oldname, newdir, newname,
2335 &oldpath, &newpath, &wnode1, &wnode2);
2336 if (!err) {
2337 struct fuse_intr_data d;
2338 err = 0;
2339 fuse_prepare_interrupt(f, req, &d);
2340 if (!f->conf.hard_remove && is_open(f, newdir, newname))
2341 err = hide_node(f, newpath, newdir, newname);
2342 if (!err) {
2343 err = fuse_fs_rename(f->fs, oldpath, newpath);
2344 if (!err)
2345 err = rename_node(f, olddir, oldname, newdir,
2346 newname, 0);
2347 }
2348 fuse_finish_interrupt(f, req, &d);
2349 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
2350 }
2351 reply_err(req, err);
2352}
2353
2354static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
2355 const char *newname)
2356{
2357 struct fuse *f = req_fuse_prepare(req);
2358 struct fuse_entry_param e;
2359 char *oldpath;
2360 char *newpath;
2361 int err;
2362
2363 err = get_path2(f, ino, NULL, newparent, newname,
2364 &oldpath, &newpath, NULL, NULL);
2365 if (!err) {
2366 struct fuse_intr_data d;
2367
2368 fuse_prepare_interrupt(f, req, &d);
2369 err = fuse_fs_link(f->fs, oldpath, newpath);
2370 if (!err)
2371 err = lookup_path(f, newparent, newname, newpath,
2372 &e, NULL);
2373 fuse_finish_interrupt(f, req, &d);
2374 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
2375 }
2376 reply_entry(req, &e, err);
2377}
2378
2379static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
2380 struct fuse_file_info *fi)
2381{
2382 struct node *node;
2383 int unlink_hidden = 0;
2384
2385 fuse_fs_release(f->fs, (path || f->nullpath_ok) ? path : "-", fi);
2386
2387 pthread_mutex_lock(&f->lock);
2388 node = get_node(f, ino);
2389 assert(node->open_count > 0);
2390 --node->open_count;
2391 if (node->is_hidden && !node->open_count) {
2392 unlink_hidden = 1;
2393 node->is_hidden = 0;
2394 }
2395 pthread_mutex_unlock(&f->lock);
2396
2397 if(unlink_hidden && path)
2398 fuse_fs_unlink(f->fs, path);
2399}
2400
2401static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
2402 const char *name, mode_t mode,
2403 struct fuse_file_info *fi)
2404{
2405 struct fuse *f = req_fuse_prepare(req);
2406 struct fuse_intr_data d;
2407 struct fuse_entry_param e;
2408 char *path;
2409 int err;
2410
2411 err = get_path_name(f, parent, name, &path);
2412 if (!err) {
2413 fuse_prepare_interrupt(f, req, &d);
2414 err = fuse_fs_create(f->fs, path, mode, fi);
2415 if (!err) {
2416 err = lookup_path(f, parent, name, path, &e, fi);
2417 if (err)
2418 fuse_fs_release(f->fs, path, fi);
2419 else if (!S_ISREG(e.attr.st_mode)) {
2420 err = -EIO;
2421 fuse_fs_release(f->fs, path, fi);
2422 forget_node(f, e.ino, 1);
2423 } else {
2424 if (f->conf.direct_io)
2425 fi->direct_io = 1;
2426 if (f->conf.kernel_cache)
2427 fi->keep_cache = 1;
2428
2429 }
2430 }
2431 fuse_finish_interrupt(f, req, &d);
2432 }
2433 if (!err) {
2434 pthread_mutex_lock(&f->lock);
2435 get_node(f, e.ino)->open_count++;
2436 pthread_mutex_unlock(&f->lock);
2437 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
2438 /* The open syscall was interrupted, so it
2439 must be cancelled */
2440 fuse_prepare_interrupt(f, req, &d);
2441 fuse_do_release(f, e.ino, path, fi);
2442 fuse_finish_interrupt(f, req, &d);
2443 forget_node(f, e.ino, 1);
2444 }
2445 } else {
2446 reply_err(req, err);
2447 }
2448
2449 free_path(f, parent, path);
2450}
2451
2452static double diff_timespec(const struct timespec *t1,
2453 const struct timespec *t2)
2454{
2455 return (t1->tv_sec - t2->tv_sec) +
2456 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
2457}
2458
2459static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
2460 struct fuse_file_info *fi)
2461{
2462 struct node *node;
2463
2464 pthread_mutex_lock(&f->lock);
2465 node = get_node(f, ino);
2466 if (node->cache_valid) {
2467 struct timespec now;
2468
2469 curr_time(&now);
2470 if (diff_timespec(&now, &node->stat_updated) >
2471 f->conf.ac_attr_timeout) {
2472 struct stat stbuf;
2473 int err;
2474 pthread_mutex_unlock(&f->lock);
2475 err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
2476 pthread_mutex_lock(&f->lock);
2477 if (!err)
2478 update_stat(node, &stbuf);
2479 else
2480 node->cache_valid = 0;
2481 }
2482 }
2483 if (node->cache_valid)
2484 fi->keep_cache = 1;
2485
2486 node->cache_valid = 1;
2487 pthread_mutex_unlock(&f->lock);
2488}
2489
2490static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
2491 struct fuse_file_info *fi)
2492{
2493 struct fuse *f = req_fuse_prepare(req);
2494 struct fuse_intr_data d;
2495 char *path;
2496 int err;
2497
2498 err = get_path(f, ino, &path);
2499 if (!err) {
2500 fuse_prepare_interrupt(f, req, &d);
2501 err = fuse_fs_open(f->fs, path, fi);
2502 if (!err) {
2503 if (f->conf.direct_io)
2504 fi->direct_io = 1;
2505 if (f->conf.kernel_cache)
2506 fi->keep_cache = 1;
2507
2508 if (f->conf.auto_cache)
2509 open_auto_cache(f, ino, path, fi);
2510 }
2511 fuse_finish_interrupt(f, req, &d);
2512 }
2513 if (!err) {
2514 pthread_mutex_lock(&f->lock);
2515 get_node(f, ino)->open_count++;
2516 pthread_mutex_unlock(&f->lock);
2517 if (fuse_reply_open(req, fi) == -ENOENT) {
2518 /* The open syscall was interrupted, so it
2519 must be cancelled */
2520 fuse_prepare_interrupt(f, req, &d);
2521 fuse_do_release(f, ino, path, fi);
2522 fuse_finish_interrupt(f, req, &d);
2523 }
2524 } else
2525 reply_err(req, err);
2526
2527 free_path(f, ino, path);
2528}
2529
2530static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
2531 off64_t off, struct fuse_file_info *fi)
2532{
2533 struct fuse *f = req_fuse_prepare(req);
2534 char *path;
2535 char *buf;
2536 int res;
2537
2538 buf = (char *) malloc(size);
2539 if (buf == NULL) {
2540 reply_err(req, -ENOMEM);
2541 return;
2542 }
2543
2544 res = get_path_nullok(f, ino, &path);
2545 if (res == 0) {
2546 struct fuse_intr_data d;
2547
2548 fuse_prepare_interrupt(f, req, &d);
2549 res = fuse_fs_read(f->fs, path, buf, size, off, fi);
2550 fuse_finish_interrupt(f, req, &d);
2551 free_path(f, ino, path);
2552 }
2553
2554 if (res >= 0)
2555 fuse_reply_buf(req, buf, res);
2556 else
2557 reply_err(req, res);
2558
2559 free(buf);
2560}
2561
2562static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
2563 size_t size, off64_t off, struct fuse_file_info *fi)
2564{
2565 struct fuse *f = req_fuse_prepare(req);
2566 char *path;
2567 int res;
2568
2569 res = get_path_nullok(f, ino, &path);
2570 if (res == 0) {
2571 struct fuse_intr_data d;
2572
2573 fuse_prepare_interrupt(f, req, &d);
2574 res = fuse_fs_write(f->fs, path, buf, size, off, fi);
2575 printf("died\n");
2576 fuse_finish_interrupt(f, req, &d);
2577 free_path(f, ino, path);
2578 }
2579
2580 if (res >= 0)
2581 fuse_reply_write(req, res);
2582 else
2583 reply_err(req, res);
2584}
2585
2586static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
2587 struct fuse_file_info *fi)
2588{
2589 struct fuse *f = req_fuse_prepare(req);
2590 char *path;
2591 int err;
2592
2593 err = get_path_nullok(f, ino, &path);
2594 if (!err) {
2595 struct fuse_intr_data d;
2596
2597 fuse_prepare_interrupt(f, req, &d);
2598 err = fuse_fs_fsync(f->fs, path, datasync, fi);
2599 fuse_finish_interrupt(f, req, &d);
2600 free_path(f, ino, path);
2601 }
2602 reply_err(req, err);
2603}
2604
2605static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
2606 struct fuse_file_info *fi)
2607{
2608 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
2609 memset(fi, 0, sizeof(struct fuse_file_info));
2610 fi->fh = dh->fh;
2611 fi->fh_old = dh->fh;
2612 return dh;
2613}
2614
2615static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
2616 struct fuse_file_info *llfi)
2617{
2618 struct fuse *f = req_fuse_prepare(req);
2619 struct fuse_intr_data d;
2620 struct fuse_dh *dh;
2621 struct fuse_file_info fi;
2622 char *path;
2623 int err;
2624
2625 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
2626 if (dh == NULL) {
2627 reply_err(req, -ENOMEM);
2628 return;
2629 }
2630 memset(dh, 0, sizeof(struct fuse_dh));
2631 dh->fuse = f;
2632 dh->contents = NULL;
2633 dh->len = 0;
2634 dh->filled = 0;
2635 dh->nodeid = ino;
2636 fuse_mutex_init(&dh->lock);
2637
2638 llfi->fh = (uintptr_t) dh;
2639
2640 memset(&fi, 0, sizeof(fi));
2641 fi.flags = llfi->flags;
2642
2643 err = get_path(f, ino, &path);
2644 if (!err) {
2645 fuse_prepare_interrupt(f, req, &d);
2646 err = fuse_fs_opendir(f->fs, path, &fi);
2647 fuse_finish_interrupt(f, req, &d);
2648 dh->fh = fi.fh;
2649 }
2650 if (!err) {
2651 if (fuse_reply_open(req, llfi) == -ENOENT) {
2652 /* The opendir syscall was interrupted, so it
2653 must be cancelled */
2654 fuse_prepare_interrupt(f, req, &d);
2655 fuse_fs_releasedir(f->fs, path, &fi);
2656 fuse_finish_interrupt(f, req, &d);
2657 pthread_mutex_destroy(&dh->lock);
2658 free(dh);
2659 }
2660 } else {
2661 reply_err(req, err);
2662 pthread_mutex_destroy(&dh->lock);
2663 free(dh);
2664 }
2665 free_path(f, ino, path);
2666}
2667
2668static int extend_contents(struct fuse_dh *dh, unsigned minsize)
2669{
2670 if (minsize > dh->size) {
2671 char *newptr;
2672 unsigned newsize = dh->size;
2673 if (!newsize)
2674 newsize = 1024;
2675 while (newsize < minsize) {
2676 if (newsize >= 0x80000000)
2677 newsize = 0xffffffff;
2678 else
2679 newsize *= 2;
2680 }
2681
2682 newptr = (char *) realloc(dh->contents, newsize);
2683 if (!newptr) {
2684 dh->error = -ENOMEM;
2685 return -1;
2686 }
2687 dh->contents = newptr;
2688 dh->size = newsize;
2689 }
2690 return 0;
2691}
2692
2693static int fill_dir(void *dh_, const char *name, const struct stat *statp,
2694 off64_t off)
2695{
2696 struct fuse_dh *dh = (struct fuse_dh *) dh_;
2697 struct stat stbuf;
2698 size_t newlen;
2699
2700 if (statp)
2701 stbuf = *statp;
2702 else {
2703 memset(&stbuf, 0, sizeof(stbuf));
2704 stbuf.st_ino = FUSE_UNKNOWN_INO;
2705 }
2706
2707 if (!dh->fuse->conf.use_ino) {
2708 stbuf.st_ino = FUSE_UNKNOWN_INO;
2709 if (dh->fuse->conf.readdir_ino) {
2710 struct node *node;
2711 pthread_mutex_lock(&dh->fuse->lock);
2712 node = lookup_node(dh->fuse, dh->nodeid, name);
2713 if (node)
2714 stbuf.st_ino = (ino_t) node->nodeid;
2715 pthread_mutex_unlock(&dh->fuse->lock);
2716 }
2717 }
2718
2719 if (off) {
2720 if (extend_contents(dh, dh->needlen) == -1)
2721 return 1;
2722
2723 dh->filled = 0;
2724 newlen = dh->len +
2725 fuse_add_direntry(dh->req, dh->contents + dh->len,
2726 dh->needlen - dh->len, name,
2727 &stbuf, off);
2728 if (newlen > dh->needlen)
2729 return 1;
2730 } else {
2731 newlen = dh->len +
2732 fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
2733 if (extend_contents(dh, newlen) == -1)
2734 return 1;
2735
2736 fuse_add_direntry(dh->req, dh->contents + dh->len,
2737 dh->size - dh->len, name, &stbuf, newlen);
2738 }
2739 dh->len = newlen;
2740 return 0;
2741}
2742
2743static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2744 size_t size, off64_t off, struct fuse_dh *dh,
2745 struct fuse_file_info *fi)
2746{
2747 char *path;
2748 int err;
2749
2750 err = get_path(f, ino, &path);
2751 if (!err) {
2752 struct fuse_intr_data d;
2753
2754 dh->len = 0;
2755 dh->error = 0;
2756 dh->needlen = size;
2757 dh->filled = 1;
2758 dh->req = req;
2759 fuse_prepare_interrupt(f, req, &d);
2760 err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
2761 fuse_finish_interrupt(f, req, &d);
2762 dh->req = NULL;
2763 if (!err)
2764 err = dh->error;
2765 if (err)
2766 dh->filled = 0;
2767 free_path(f, ino, path);
2768 }
2769 return err;
2770}
2771
2772static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
2773 off64_t off, struct fuse_file_info *llfi)
2774{
2775 struct fuse *f = req_fuse_prepare(req);
2776 struct fuse_file_info fi;
2777 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
2778
2779 pthread_mutex_lock(&dh->lock);
2780 /* According to SUS, directory contents need to be refreshed on
2781 rewinddir() */
2782 if (!off)
2783 dh->filled = 0;
2784
2785 if (!dh->filled) {
2786 int err = readdir_fill(f, req, ino, size, off, dh, &fi);
2787 if (err) {
2788 reply_err(req, err);
2789 goto out;
2790 }
2791 }
2792 if (dh->filled) {
2793 if (off < dh->len) {
2794 if (off + size > dh->len)
2795 size = dh->len - off;
2796 } else
2797 size = 0;
2798 } else {
2799 size = dh->len;
2800 off = 0;
2801 }
2802 fuse_reply_buf(req, dh->contents + off, size);
2803out:
2804 pthread_mutex_unlock(&dh->lock);
2805}
2806
2807static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
2808 struct fuse_file_info *llfi)
2809{
2810 struct fuse *f = req_fuse_prepare(req);
2811 struct fuse_intr_data d;
2812 struct fuse_file_info fi;
2813 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
2814 char *path;
2815
2816 get_path(f, ino, &path);
2817 fuse_prepare_interrupt(f, req, &d);
2818 fuse_fs_releasedir(f->fs, (path || f->nullpath_ok) ? path : "-", &fi);
2819 fuse_finish_interrupt(f, req, &d);
2820 free_path(f, ino, path);
2821
2822 pthread_mutex_lock(&dh->lock);
2823 pthread_mutex_unlock(&dh->lock);
2824 pthread_mutex_destroy(&dh->lock);
2825 free(dh->contents);
2826 free(dh);
2827 reply_err(req, 0);
2828}
2829
2830static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
2831 struct fuse_file_info *llfi)
2832{
2833 struct fuse *f = req_fuse_prepare(req);
2834 struct fuse_file_info fi;
2835 char *path;
2836 int err;
2837
2838 get_dirhandle(llfi, &fi);
2839
2840 err = get_path(f, ino, &path);
2841 if (!err) {
2842 struct fuse_intr_data d;
2843 fuse_prepare_interrupt(f, req, &d);
2844 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
2845 fuse_finish_interrupt(f, req, &d);
2846 free_path(f, ino, path);
2847 }
2848 reply_err(req, err);
2849}
2850
2851static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
2852{
2853 struct fuse *f = req_fuse_prepare(req);
2854 struct statvfs buf;
2855 char *path = NULL;
2856 int err = 0;
2857
2858 memset(&buf, 0, sizeof(buf));
2859 if (ino)
2860 err = get_path(f, ino, &path);
2861
2862 if (!err) {
2863 struct fuse_intr_data d;
2864 fuse_prepare_interrupt(f, req, &d);
2865 err = fuse_fs_statfs(f->fs, path ? path : "/", &buf);
2866 fuse_finish_interrupt(f, req, &d);
2867 free_path(f, ino, path);
2868 }
2869
2870 if (!err)
2871 fuse_reply_statfs(req, &buf);
2872 else
2873 reply_err(req, err);
2874}
2875
2876static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
2877 const char *value, size_t size, int flags)
2878{
2879 struct fuse *f = req_fuse_prepare(req);
2880 char *path;
2881 int err;
2882
2883 err = get_path(f, ino, &path);
2884 if (!err) {
2885 struct fuse_intr_data d;
2886 fuse_prepare_interrupt(f, req, &d);
2887 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
2888 fuse_finish_interrupt(f, req, &d);
2889 free_path(f, ino, path);
2890 }
2891 reply_err(req, err);
2892}
2893
2894static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2895 const char *name, char *value, size_t size)
2896{
2897 int err;
2898 char *path;
2899
2900 err = get_path(f, ino, &path);
2901 if (!err) {
2902 struct fuse_intr_data d;
2903 fuse_prepare_interrupt(f, req, &d);
2904 err = fuse_fs_getxattr(f->fs, path, name, value, size);
2905 fuse_finish_interrupt(f, req, &d);
2906 free_path(f, ino, path);
2907 }
2908 return err;
2909}
2910
2911static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
2912 size_t size)
2913{
2914 struct fuse *f = req_fuse_prepare(req);
2915 int res;
2916
2917 if (size) {
2918 char *value = (char *) malloc(size);
2919 if (value == NULL) {
2920 reply_err(req, -ENOMEM);
2921 return;
2922 }
2923 res = common_getxattr(f, req, ino, name, value, size);
2924 if (res > 0)
2925 fuse_reply_buf(req, value, res);
2926 else
2927 reply_err(req, res);
2928 free(value);
2929 } else {
2930 res = common_getxattr(f, req, ino, name, NULL, 0);
2931 if (res >= 0)
2932 fuse_reply_xattr(req, res);
2933 else
2934 reply_err(req, res);
2935 }
2936}
2937
2938static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2939 char *list, size_t size)
2940{
2941 char *path;
2942 int err;
2943
2944 err = get_path(f, ino, &path);
2945 if (!err) {
2946 struct fuse_intr_data d;
2947 fuse_prepare_interrupt(f, req, &d);
2948 err = fuse_fs_listxattr(f->fs, path, list, size);
2949 fuse_finish_interrupt(f, req, &d);
2950 free_path(f, ino, path);
2951 }
2952 return err;
2953}
2954
2955static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
2956{
2957 struct fuse *f = req_fuse_prepare(req);
2958 int res;
2959
2960 if (size) {
2961 char *list = (char *) malloc(size);
2962 if (list == NULL) {
2963 reply_err(req, -ENOMEM);
2964 return;
2965 }
2966 res = common_listxattr(f, req, ino, list, size);
2967 if (res > 0)
2968 fuse_reply_buf(req, list, res);
2969 else
2970 reply_err(req, res);
2971 free(list);
2972 } else {
2973 res = common_listxattr(f, req, ino, NULL, 0);
2974 if (res >= 0)
2975 fuse_reply_xattr(req, res);
2976 else
2977 reply_err(req, res);
2978 }
2979}
2980
2981static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
2982 const char *name)
2983{
2984 struct fuse *f = req_fuse_prepare(req);
2985 char *path;
2986 int err;
2987
2988 err = get_path(f, ino, &path);
2989 if (!err) {
2990 struct fuse_intr_data d;
2991 fuse_prepare_interrupt(f, req, &d);
2992 err = fuse_fs_removexattr(f->fs, path, name);
2993 fuse_finish_interrupt(f, req, &d);
2994 free_path(f, ino, path);
2995 }
2996 reply_err(req, err);
2997}
2998
2999static struct lock *locks_conflict(struct node *node, const struct lock *lock)
3000{
3001 struct lock *l;
3002
3003 for (l = node->locks; l; l = l->next)
3004 if (l->owner != lock->owner &&
3005 lock->start <= l->end && l->start <= lock->end &&
3006 (l->type == F_WRLCK || lock->type == F_WRLCK))
3007 break;
3008
3009 return l;
3010}
3011
3012static void delete_lock(struct lock **lockp)
3013{
3014 struct lock *l = *lockp;
3015 *lockp = l->next;
3016 free(l);
3017}
3018
3019static void insert_lock(struct lock **pos, struct lock *lock)
3020{
3021 lock->next = *pos;
3022 *pos = lock;
3023}
3024
3025static int locks_insert(struct node *node, struct lock *lock)
3026{
3027 struct lock **lp;
3028 struct lock *newl1 = NULL;
3029 struct lock *newl2 = NULL;
3030
3031 if (lock->type != F_UNLCK || lock->start != 0 ||
3032 lock->end != OFFSET_MAX) {
3033 newl1 = malloc(sizeof(struct lock));
3034 newl2 = malloc(sizeof(struct lock));
3035
3036 if (!newl1 || !newl2) {
3037 free(newl1);
3038 free(newl2);
3039 return -ENOLCK;
3040 }
3041 }
3042
3043 for (lp = &node->locks; *lp;) {
3044 struct lock *l = *lp;
3045 if (l->owner != lock->owner)
3046 goto skip;
3047
3048 if (lock->type == l->type) {
3049 if (l->end < lock->start - 1)
3050 goto skip;
3051 if (lock->end < l->start - 1)
3052 break;
3053 if (l->start <= lock->start && lock->end <= l->end)
3054 goto out;
3055 if (l->start < lock->start)
3056 lock->start = l->start;
3057 if (lock->end < l->end)
3058 lock->end = l->end;
3059 goto delete;
3060 } else {
3061 if (l->end < lock->start)
3062 goto skip;
3063 if (lock->end < l->start)
3064 break;
3065 if (lock->start <= l->start && l->end <= lock->end)
3066 goto delete;
3067 if (l->end <= lock->end) {
3068 l->end = lock->start - 1;
3069 goto skip;
3070 }
3071 if (lock->start <= l->start) {
3072 l->start = lock->end + 1;
3073 break;
3074 }
3075 *newl2 = *l;
3076 newl2->start = lock->end + 1;
3077 l->end = lock->start - 1;
3078 insert_lock(&l->next, newl2);
3079 newl2 = NULL;
3080 }
3081 skip:
3082 lp = &l->next;
3083 continue;
3084
3085 delete:
3086 delete_lock(lp);
3087 }
3088 if (lock->type != F_UNLCK) {
3089 *newl1 = *lock;
3090 insert_lock(lp, newl1);
3091 newl1 = NULL;
3092 }
3093out:
3094 free(newl1);
3095 free(newl2);
3096 return 0;
3097}
3098
3099static void flock_to_lock(struct flock *flock, struct lock *lock)
3100{
3101 memset(lock, 0, sizeof(struct lock));
3102 lock->type = flock->l_type;
3103 lock->start = flock->l_start;
3104 lock->end =
3105 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
3106 lock->pid = flock->l_pid;
3107}
3108
3109static void lock_to_flock(struct lock *lock, struct flock *flock)
3110{
3111 flock->l_type = lock->type;
3112 flock->l_start = lock->start;
3113 flock->l_len =
3114 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
3115 flock->l_pid = lock->pid;
3116}
3117
3118static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3119 const char *path, struct fuse_file_info *fi)
3120{
3121 struct fuse_intr_data d;
3122 struct flock lock;
3123 struct lock l;
3124 int err;
3125 int errlock;
3126
3127 fuse_prepare_interrupt(f, req, &d);
3128 memset(&lock, 0, sizeof(lock));
3129 lock.l_type = F_UNLCK;
3130 lock.l_whence = SEEK_SET;
3131 err = fuse_fs_flush(f->fs, path, fi);
3132 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
3133 fuse_finish_interrupt(f, req, &d);
3134
3135 if (errlock != -ENOSYS) {
3136 flock_to_lock(&lock, &l);
3137 l.owner = fi->lock_owner;
3138 pthread_mutex_lock(&f->lock);
3139 locks_insert(get_node(f, ino), &l);
3140 pthread_mutex_unlock(&f->lock);
3141
3142 /* if op.lock() is defined FLUSH is needed regardless
3143 of op.flush() */
3144 if (err == -ENOSYS)
3145 err = 0;
3146 }
3147 return err;
3148}
3149
3150static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
3151 struct fuse_file_info *fi)
3152{
3153 struct fuse *f = req_fuse_prepare(req);
3154 struct fuse_intr_data d;
3155 char *path;
3156 int err = 0;
3157
3158 get_path(f, ino, &path);
3159 if (fi->flush) {
3160 err = fuse_flush_common(f, req, ino, path, fi);
3161 if (err == -ENOSYS)
3162 err = 0;
3163 }
3164
3165 fuse_prepare_interrupt(f, req, &d);
3166 fuse_do_release(f, ino, path, fi);
3167 fuse_finish_interrupt(f, req, &d);
3168 free_path(f, ino, path);
3169
3170 reply_err(req, err);
3171}
3172
3173static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
3174 struct fuse_file_info *fi)
3175{
3176 struct fuse *f = req_fuse_prepare(req);
3177 char *path;
3178 int err;
3179
3180 get_path(f, ino, &path);
3181 err = fuse_flush_common(f, req, ino, path, fi);
3182 free_path(f, ino, path);
3183
3184 reply_err(req, err);
3185}
3186
3187static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
3188 struct fuse_file_info *fi, struct flock *lock,
3189 int cmd)
3190{
3191 struct fuse *f = req_fuse_prepare(req);
3192 char *path;
3193 int err;
3194
3195 err = get_path_nullok(f, ino, &path);
3196 if (!err) {
3197 struct fuse_intr_data d;
3198 fuse_prepare_interrupt(f, req, &d);
3199 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
3200 fuse_finish_interrupt(f, req, &d);
3201 free_path(f, ino, path);
3202 }
3203 return err;
3204}
3205
3206static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
3207 struct fuse_file_info *fi, struct flock *lock)
3208{
3209 int err;
3210 struct lock l;
3211 struct lock *conflict;
3212 struct fuse *f = req_fuse(req);
3213
3214 flock_to_lock(lock, &l);
3215 l.owner = fi->lock_owner;
3216 pthread_mutex_lock(&f->lock);
3217 conflict = locks_conflict(get_node(f, ino), &l);
3218 if (conflict)
3219 lock_to_flock(conflict, lock);
3220 pthread_mutex_unlock(&f->lock);
3221 if (!conflict)
3222 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
3223 else
3224 err = 0;
3225
3226 if (!err)
3227 fuse_reply_lock(req, lock);
3228 else
3229 reply_err(req, err);
3230}
3231
3232static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
3233 struct fuse_file_info *fi, struct flock *lock,
3234 int sleep)
3235{
3236 int err = fuse_lock_common(req, ino, fi, lock,
3237 sleep ? F_SETLKW : F_SETLK);
3238 if (!err) {
3239 struct fuse *f = req_fuse(req);
3240 struct lock l;
3241 flock_to_lock(lock, &l);
3242 l.owner = fi->lock_owner;
3243 pthread_mutex_lock(&f->lock);
3244 locks_insert(get_node(f, ino), &l);
3245 pthread_mutex_unlock(&f->lock);
3246 }
3247 reply_err(req, err);
3248}
3249
3250static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
3251 uint64_t idx)
3252{
3253 struct fuse *f = req_fuse_prepare(req);
3254 struct fuse_intr_data d;
3255 char *path;
3256 int err;
3257
3258 err = get_path(f, ino, &path);
3259 if (!err) {
3260 fuse_prepare_interrupt(f, req, &d);
3261 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
3262 fuse_finish_interrupt(f, req, &d);
3263 free_path(f, ino, path);
3264 }
3265 if (!err)
3266 fuse_reply_bmap(req, idx);
3267 else
3268 reply_err(req, err);
3269}
3270
3271static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
3272 struct fuse_file_info *fi, unsigned int flags,
3273 const void *in_buf, size_t in_bufsz,
3274 size_t out_bufsz)
3275{
3276 struct fuse *f = req_fuse_prepare(req);
3277 struct fuse_intr_data d;
3278 char *path, *out_buf = NULL;
3279 int err;
3280
3281 err = -EPERM;
3282 if (flags & FUSE_IOCTL_UNRESTRICTED)
3283 goto err;
3284
3285 if (out_bufsz) {
3286 err = -ENOMEM;
3287 out_buf = malloc(out_bufsz);
3288 if (!out_buf)
3289 goto err;
3290 }
3291
3292 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
3293 if (out_buf)
3294 memcpy(out_buf, in_buf, in_bufsz);
3295
3296 err = get_path(f, ino, &path);
3297 if (err)
3298 goto err;
3299
3300 fuse_prepare_interrupt(f, req, &d);
3301
3302 err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, flags,
3303 out_buf ?: (void *)in_buf);
3304
3305 fuse_finish_interrupt(f, req, &d);
3306 free_path(f, ino, path);
3307
3308 fuse_reply_ioctl(req, err, out_buf, out_bufsz);
3309 goto out;
3310err:
3311 reply_err(req, err);
3312out:
3313 free(out_buf);
3314}
3315
3316static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
3317 struct fuse_file_info *fi, struct fuse_pollhandle *ph)
3318{
3319 struct fuse *f = req_fuse_prepare(req);
3320 struct fuse_intr_data d;
3321 char *path;
3322 int ret;
3323 unsigned revents = 0;
3324
3325 ret = get_path(f, ino, &path);
3326 if (!ret) {
3327 fuse_prepare_interrupt(f, req, &d);
3328 ret = fuse_fs_poll(f->fs, path, fi, ph, &revents);
3329 fuse_finish_interrupt(f, req, &d);
3330 free_path(f, ino, path);
3331 }
3332 if (!ret)
3333 fuse_reply_poll(req, revents);
3334 else
3335 reply_err(req, ret);
3336}
3337
3338static struct fuse_lowlevel_ops fuse_path_ops = {
3339 .init = fuse_lib_init,
3340 .destroy = fuse_lib_destroy,
3341 .lookup = fuse_lib_lookup,
3342 .forget = fuse_lib_forget,
3343 .getattr = fuse_lib_getattr,
3344 .setattr = fuse_lib_setattr,
3345 .access = fuse_lib_access,
3346 .readlink = fuse_lib_readlink,
3347 .mknod = fuse_lib_mknod,
3348 .mkdir = fuse_lib_mkdir,
3349 .unlink = fuse_lib_unlink,
3350 .rmdir = fuse_lib_rmdir,
3351 .symlink = fuse_lib_symlink,
3352 .rename = fuse_lib_rename,
3353 .link = fuse_lib_link,
3354 .create = fuse_lib_create,
3355 .open = fuse_lib_open,
3356 .read = fuse_lib_read,
3357 .write = fuse_lib_write,
3358 .flush = fuse_lib_flush,
3359 .release = fuse_lib_release,
3360 .fsync = fuse_lib_fsync,
3361 .opendir = fuse_lib_opendir,
3362 .readdir = fuse_lib_readdir,
3363 .releasedir = fuse_lib_releasedir,
3364 .fsyncdir = fuse_lib_fsyncdir,
3365 .statfs = fuse_lib_statfs,
3366 .setxattr = fuse_lib_setxattr,
3367 .getxattr = fuse_lib_getxattr,
3368 .listxattr = fuse_lib_listxattr,
3369 .removexattr = fuse_lib_removexattr,
3370 .getlk = fuse_lib_getlk,
3371 .setlk = fuse_lib_setlk,
3372 .bmap = fuse_lib_bmap,
3373 .ioctl = fuse_lib_ioctl,
3374 .poll = fuse_lib_poll,
3375};
3376
3377int fuse_notify_poll(struct fuse_pollhandle *ph)
3378{
3379 return fuse_lowlevel_notify_poll(ph);
3380}
3381
3382static void free_cmd(struct fuse_cmd *cmd)
3383{
3384 free(cmd->buf);
3385 free(cmd);
3386}
3387
3388void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
3389{
3390 fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch);
3391 free_cmd(cmd);
3392}
3393
3394int fuse_exited(struct fuse *f)
3395{
3396 return fuse_session_exited(f->se);
3397}
3398
3399struct fuse_session *fuse_get_session(struct fuse *f)
3400{
3401 return f->se;
3402}
3403
3404static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize)
3405{
3406 struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd));
3407 if (cmd == NULL) {
3408 fprintf(stderr, "fuse: failed to allocate cmd\n");
3409 return NULL;
3410 }
3411 cmd->buf = (char *) malloc(bufsize);
3412 if (cmd->buf == NULL) {
3413 fprintf(stderr, "fuse: failed to allocate read buffer\n");
3414 free(cmd);
3415 return NULL;
3416 }
3417 return cmd;
3418}
3419
3420struct fuse_cmd *fuse_read_cmd(struct fuse *f)
3421{
3422 struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL);
3423 size_t bufsize = fuse_chan_bufsize(ch);
3424 struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
3425 if (cmd != NULL) {
3426 int res = fuse_chan_recv(&ch, cmd->buf, bufsize);
3427 if (res <= 0) {
3428 free_cmd(cmd);
3429 if (res < 0 && res != -EINTR && res != -EAGAIN)
3430 fuse_exit(f);
3431 return NULL;
3432 }
3433 cmd->buflen = res;
3434 cmd->ch = ch;
3435 }
3436 return cmd;
3437}
3438
3439int fuse_loop(struct fuse *f)
3440{
3441 if (f)
3442 return fuse_session_loop(f->se);
3443 else
3444 return -1;
3445}
3446
3447int fuse_invalidate(struct fuse *f, const char *path)
3448{
3449 (void) f;
3450 (void) path;
3451 return -EINVAL;
3452}
3453
3454void fuse_exit(struct fuse *f)
3455{
3456 fuse_session_exit(f->se);
3457}
3458
3459struct fuse_context *fuse_get_context(void)
3460{
3461 return &fuse_get_context_internal()->ctx;
3462}
3463
3464/*
3465 * The size of fuse_context got extended, so need to be careful about
3466 * incompatibility (i.e. a new binary cannot work with an old
3467 * library).
3468 */
3469struct fuse_context *fuse_get_context_compat22(void);
3470struct fuse_context *fuse_get_context_compat22(void)
3471{
3472 return &fuse_get_context_internal()->ctx;
3473}
3474FUSE_SYMVER(".symver fuse_get_context_compat22,fuse_get_context@FUSE_2.2");
3475
3476int fuse_getgroups(int size, gid_t list[])
3477{
3478 fuse_req_t req = fuse_get_context_internal()->req;
3479 return fuse_req_getgroups(req, size, list);
3480}
3481
3482int fuse_interrupted(void)
3483{
3484 return fuse_req_interrupted(fuse_get_context_internal()->req);
3485}
3486
3487void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
3488{
3489 (void) func;
3490 /* no-op */
3491}
3492
3493enum {
3494 KEY_HELP,
3495};
3496
3497#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
3498
3499static const struct fuse_opt fuse_lib_opts[] = {
3500 FUSE_OPT_KEY("-h", KEY_HELP),
3501 FUSE_OPT_KEY("--help", KEY_HELP),
3502 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
3503 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
3504 FUSE_LIB_OPT("debug", debug, 1),
3505 FUSE_LIB_OPT("-d", debug, 1),
3506 FUSE_LIB_OPT("hard_remove", hard_remove, 1),
3507 FUSE_LIB_OPT("use_ino", use_ino, 1),
3508 FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
3509 FUSE_LIB_OPT("direct_io", direct_io, 1),
3510 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
3511 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
3512 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
3513 FUSE_LIB_OPT("umask=", set_mode, 1),
3514 FUSE_LIB_OPT("umask=%o", umask, 0),
3515 FUSE_LIB_OPT("uid=", set_uid, 1),
3516 FUSE_LIB_OPT("uid=%d", uid, 0),
3517 FUSE_LIB_OPT("gid=", set_gid, 1),
3518 FUSE_LIB_OPT("gid=%d", gid, 0),
3519 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
3520 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
3521 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
3522 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
3523 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
3524 FUSE_LIB_OPT("noforget", noforget, 1),
3525 FUSE_LIB_OPT("intr", intr, 1),
3526 FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
3527 FUSE_LIB_OPT("modules=%s", modules, 0),
3528 FUSE_OPT_END
3529};
3530
3531static void fuse_lib_help(void)
3532{
3533 fprintf(stderr,
3534" -o hard_remove immediate removal (don't hide files)\n"
3535" -o use_ino let filesystem set inode numbers\n"
3536" -o readdir_ino try to fill in d_ino in readdir\n"
3537" -o direct_io use direct I/O\n"
3538" -o kernel_cache cache files in kernel\n"
3539" -o [no]auto_cache enable caching based on modification times (off)\n"
3540" -o umask=M set file permissions (octal)\n"
3541" -o uid=N set file owner\n"
3542" -o gid=N set file group\n"
3543" -o entry_timeout=T cache timeout for names (1.0s)\n"
3544" -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
3545" -o attr_timeout=T cache timeout for attributes (1.0s)\n"
3546" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
3547" -o intr allow requests to be interrupted\n"
3548" -o intr_signal=NUM signal to send on interrupt (%i)\n"
3549" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
3550"\n", FUSE_DEFAULT_INTR_SIGNAL);
3551}
3552
3553static void fuse_lib_help_modules(void)
3554{
3555 struct fuse_module *m;
3556 fprintf(stderr, "\nModule options:\n");
3557 pthread_mutex_lock(&fuse_context_lock);
3558 for (m = fuse_modules; m; m = m->next) {
3559 struct fuse_fs *fs = NULL;
3560 struct fuse_fs *newfs;
3561 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
3562 if (fuse_opt_add_arg(&args, "") != -1 &&
3563 fuse_opt_add_arg(&args, "-h") != -1) {
3564 fprintf(stderr, "\n[%s]\n", m->name);
3565 newfs = m->factory(&args, &fs);
3566 assert(newfs == NULL);
3567 }
3568 fuse_opt_free_args(&args);
3569 }
3570 pthread_mutex_unlock(&fuse_context_lock);
3571}
3572
3573static int fuse_lib_opt_proc(void *data, const char *arg, int key,
3574 struct fuse_args *outargs)
3575{
3576 (void) arg; (void) outargs;
3577
3578 if (key == KEY_HELP) {
3579 struct fuse_config *conf = (struct fuse_config *) data;
3580 fuse_lib_help();
3581 conf->help = 1;
3582 }
3583
3584 return 1;
3585}
3586
3587int fuse_is_lib_option(const char *opt)
3588{
3589 return fuse_lowlevel_is_lib_option(opt) ||
3590 fuse_opt_match(fuse_lib_opts, opt);
3591}
3592
3593static int fuse_init_intr_signal(int signum, int *installed)
3594{
3595 struct sigaction old_sa;
3596
3597 if (sigaction(signum, NULL, &old_sa) == -1) {
3598 perror("fuse: cannot get old signal handler");
3599 return -1;
3600 }
3601
3602 if (old_sa.sa_handler == SIG_DFL) {
3603 struct sigaction sa;
3604
3605 memset(&sa, 0, sizeof(struct sigaction));
3606 sa.sa_handler = fuse_intr_sighandler;
3607 sigemptyset(&sa.sa_mask);
3608
3609 if (sigaction(signum, &sa, NULL) == -1) {
3610 perror("fuse: cannot set interrupt signal handler");
3611 return -1;
3612 }
3613 *installed = 1;
3614 }
3615 return 0;
3616}
3617
3618static void fuse_restore_intr_signal(int signum)
3619{
3620 struct sigaction sa;
3621
3622 memset(&sa, 0, sizeof(struct sigaction));
3623 sa.sa_handler = SIG_DFL;
3624 sigaction(signum, &sa, NULL);
3625}
3626
3627
3628static int fuse_push_module(struct fuse *f, const char *module,
3629 struct fuse_args *args)
3630{
3631 struct fuse_fs *fs[2] = { f->fs, NULL };
3632 struct fuse_fs *newfs;
3633 struct fuse_module *m = fuse_get_module(module);
3634
3635 if (!m)
3636 return -1;
3637
3638 newfs = m->factory(args, fs);
3639 if (!newfs) {
3640 fuse_put_module(m);
3641 return -1;
3642 }
3643 newfs->m = m;
3644 f->fs = newfs;
3645 f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
3646 return 0;
3647}
3648
3649struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
3650 void *user_data)
3651{
3652 struct fuse_fs *fs;
3653
3654 if (sizeof(struct fuse_operations) < op_size) {
3655 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
3656 op_size = sizeof(struct fuse_operations);
3657 }
3658
3659 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
3660 if (!fs) {
3661 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
3662 return NULL;
3663 }
3664
3665 fs->user_data = user_data;
3666 if (op)
3667 memcpy(&fs->op, op, op_size);
3668 return fs;
3669}
3670
3671struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
3672 const struct fuse_operations *op,
3673 size_t op_size, void *user_data, int compat)
3674{
3675 struct fuse *f;
3676 struct node *root;
3677 struct fuse_fs *fs;
3678 struct fuse_lowlevel_ops llop = fuse_path_ops;
3679
3680 if (fuse_create_context_key() == -1)
3681 goto out;
3682
3683 f = (struct fuse *) calloc(1, sizeof(struct fuse));
3684 if (f == NULL) {
3685 fprintf(stderr, "fuse: failed to allocate fuse object\n");
3686 goto out_delete_context_key;
3687 }
3688
3689 fs = fuse_fs_new(op, op_size, user_data);
3690 if (!fs)
3691 goto out_free;
3692
3693 fs->compat = compat;
3694 f->fs = fs;
3695 f->nullpath_ok = fs->op.flag_nullpath_ok;
3696
3697 /* Oh f**k, this is ugly! */
3698 if (!fs->op.lock) {
3699 llop.getlk = NULL;
3700 llop.setlk = NULL;
3701 }
3702
3703 f->conf.entry_timeout = 1.0;
3704 f->conf.attr_timeout = 1.0;
3705 f->conf.negative_timeout = 0.0;
3706 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
3707
3708 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
3709 fuse_lib_opt_proc) == -1)
3710 goto out_free_fs;
3711
3712 if (f->conf.modules) {
3713 char *module;
3714 char *next;
3715
3716 for (module = f->conf.modules; module; module = next) {
3717 char *p;
3718 for (p = module; *p && *p != ':'; p++);
3719 next = *p ? p + 1 : NULL;
3720 *p = '\0';
3721 if (module[0] &&
3722 fuse_push_module(f, module, args) == -1)
3723 goto out_free_fs;
3724 }
3725 }
3726
3727 if (!f->conf.ac_attr_timeout_set)
3728 f->conf.ac_attr_timeout = f->conf.attr_timeout;
3729
3730#ifdef __FreeBSD__
3731 /*
3732 * In FreeBSD, we always use these settings as inode numbers
3733 * are needed to make getcwd(3) work.
3734 */
3735 f->conf.readdir_ino = 1;
3736#endif
3737
3738 if (compat && compat <= 25) {
3739 if (fuse_sync_compat_args(args) == -1)
3740 goto out_free_fs;
3741 }
3742
3743 f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f);
3744 if (f->se == NULL) {
3745 if (f->conf.help)
3746 fuse_lib_help_modules();
3747 goto out_free_fs;
3748 }
3749
3750 fuse_session_add_chan(f->se, ch);
3751
3752 if (f->conf.debug)
3753 fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
3754
3755 /* Trace topmost layer by default */
3756 f->fs->debug = f->conf.debug;
3757 f->ctr = 0;
3758 f->generation = 0;
3759 /* FIXME: Dynamic hash table */
3760 f->name_table_size = 14057;
3761 f->name_table = (struct node **)
3762 calloc(1, sizeof(struct node *) * f->name_table_size);
3763 if (f->name_table == NULL) {
3764 fprintf(stderr, "fuse: memory allocation failed\n");
3765 goto out_free_session;
3766 }
3767
3768 f->id_table_size = 14057;
3769 f->id_table = (struct node **)
3770 calloc(1, sizeof(struct node *) * f->id_table_size);
3771 if (f->id_table == NULL) {
3772 fprintf(stderr, "fuse: memory allocation failed\n");
3773 goto out_free_name_table;
3774 }
3775
3776 fuse_mutex_init(&f->lock);
3777
3778 root = (struct node *) calloc(1, sizeof(struct node));
3779 if (root == NULL) {
3780 fprintf(stderr, "fuse: memory allocation failed\n");
3781 goto out_free_id_table;
3782 }
3783
3784 root->name = strdup("/");
3785 if (root->name == NULL) {
3786 fprintf(stderr, "fuse: memory allocation failed\n");
3787 goto out_free_root;
3788 }
3789
3790 if (f->conf.intr &&
3791 fuse_init_intr_signal(f->conf.intr_signal,
3792 &f->intr_installed) == -1)
3793 goto out_free_root_name;
3794
3795 root->parent = NULL;
3796 root->nodeid = FUSE_ROOT_ID;
3797 root->generation = 0;
3798 root->refctr = 1;
3799 root->nlookup = 1;
3800 hash_id(f, root);
3801
3802 return f;
3803
3804out_free_root_name:
3805 free(root->name);
3806out_free_root:
3807 free(root);
3808out_free_id_table:
3809 free(f->id_table);
3810out_free_name_table:
3811 free(f->name_table);
3812out_free_session:
3813 fuse_session_destroy(f->se);
3814out_free_fs:
3815 /* Horrible compatibility hack to stop the destructor from being
3816 called on the filesystem without init being called first */
3817 fs->op.destroy = NULL;
3818 fuse_fs_destroy(f->fs);
3819 free(f->conf.modules);
3820out_free:
3821 free(f);
3822out_delete_context_key:
3823 fuse_delete_context_key();
3824out:
3825 return NULL;
3826}
3827
3828struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
3829 const struct fuse_operations *op, size_t op_size,
3830 void *user_data)
3831{
3832 return fuse_new_common(ch, args, op, op_size, user_data, 0);
3833}
3834
3835void fuse_destroy(struct fuse *f)
3836{
3837 size_t i;
3838
3839 if (f->conf.intr && f->intr_installed)
3840 fuse_restore_intr_signal(f->conf.intr_signal);
3841
3842 if (f->fs) {
3843 struct fuse_context_i *c = fuse_get_context_internal();
3844
3845 memset(c, 0, sizeof(*c));
3846 c->ctx.fuse = f;
3847
3848 for (i = 0; i < f->id_table_size; i++) {
3849 struct node *node;
3850
3851 for (node = f->id_table[i]; node != NULL;
3852 node = node->id_next) {
3853 if (node->is_hidden) {
3854 char *path;
3855 if (try_get_path(f, node->nodeid, NULL, &path, NULL, 0) == 0) {
3856 fuse_fs_unlink(f->fs, path);
3857 free(path);
3858 }
3859 }
3860 }
3861 }
3862 }
3863 for (i = 0; i < f->id_table_size; i++) {
3864 struct node *node;
3865 struct node *next;
3866
3867 for (node = f->id_table[i]; node != NULL; node = next) {
3868 next = node->id_next;
3869 free_node(node);
3870 }
3871 }
3872 free(f->id_table);
3873 free(f->name_table);
3874 pthread_mutex_destroy(&f->lock);
3875 fuse_session_destroy(f->se);
3876 free(f->conf.modules);
3877 free(f);
3878 fuse_delete_context_key();
3879}
3880
3881static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args,
3882 const struct fuse_operations *op,
3883 size_t op_size, int compat)
3884{
3885 struct fuse *f = NULL;
3886 struct fuse_chan *ch = fuse_kern_chan_new(fd);
3887
3888 if (ch)
3889 f = fuse_new_common(ch, args, op, op_size, NULL, compat);
3890
3891 return f;
3892}
3893
3894/* called with fuse_context_lock held or during initialization (before
3895 main() has been called) */
3896void fuse_register_module(struct fuse_module *mod)
3897{
3898 mod->ctr = 0;
3899 mod->so = fuse_current_so;
3900 if (mod->so)
3901 mod->so->ctr++;
3902 mod->next = fuse_modules;
3903 fuse_modules = mod;
3904}
3905
3906#ifndef __FreeBSD__
3907
3908static struct fuse *fuse_new_common_compat(int fd, const char *opts,
3909 const struct fuse_operations *op,
3910 size_t op_size, int compat)
3911{
3912 struct fuse *f;
3913 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
3914
3915 if (fuse_opt_add_arg(&args, "") == -1)
3916 return NULL;
3917 if (opts &&
3918 (fuse_opt_add_arg(&args, "-o") == -1 ||
3919 fuse_opt_add_arg(&args, opts) == -1)) {
3920 fuse_opt_free_args(&args);
3921 return NULL;
3922 }
3923 f = fuse_new_common_compat25(fd, &args, op, op_size, compat);
3924 fuse_opt_free_args(&args);
3925
3926 return f;
3927}
3928
3929struct fuse *fuse_new_compat22(int fd, const char *opts,
3930 const struct fuse_operations_compat22 *op,
3931 size_t op_size)
3932{
3933 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
3934 op_size, 22);
3935}
3936
3937struct fuse *fuse_new_compat2(int fd, const char *opts,
3938 const struct fuse_operations_compat2 *op)
3939{
3940 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
3941 sizeof(struct fuse_operations_compat2),
3942 21);
3943}
3944
3945struct fuse *fuse_new_compat1(int fd, int flags,
3946 const struct fuse_operations_compat1 *op)
3947{
3948 const char *opts = NULL;
3949 if (flags & FUSE_DEBUG_COMPAT1)
3950 opts = "debug";
3951 return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
3952 sizeof(struct fuse_operations_compat1),
3953 11);
3954}
3955
3956FUSE_SYMVER(".symver fuse_exited,__fuse_exited@");
3957FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@");
3958FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@");
3959FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
3960FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@");
3961FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
3962
3963#endif /* __FreeBSD__ */
3964
3965struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
3966 const struct fuse_operations_compat25 *op,
3967 size_t op_size)
3968{
3969 return fuse_new_common_compat25(fd, args, (struct fuse_operations *) op,
3970 op_size, 25);
3971}
3972
3973FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5");