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