summaryrefslogtreecommitdiff
path: root/libfuse-lite/fuse.c (plain)
blob: a5bf6bd6e7a765d62acd1ad59c7642bad72ea745
1/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU LGPLv2.
6 See the file COPYING.LIB
7*/
8
9#ifdef __SOLARIS__
10/* For pthread_rwlock_t */
11#define _GNU_SOURCE
12#endif /* __SOLARIS__ */
13
14#include "config.h"
15#include "fuse_i.h"
16#include "fuse_lowlevel.h"
17#include "fuse_opt.h"
18#include "fuse_misc.h"
19
20#include <stdio.h>
21#include <string.h>
22#include <stdlib.h>
23#include <stddef.h>
24#include <unistd.h>
25#include <time.h>
26#include <fcntl.h>
27#include <limits.h>
28#include <errno.h>
29#include <signal.h>
30#include <dlfcn.h>
31#include <assert.h>
32#include <sys/param.h>
33#include <sys/uio.h>
34#include <sys/time.h>
35
36#ifdef __SOLARIS__
37#define FUSE_MAX_PATH 4096
38#endif /* __SOLARIS__ */
39
40#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
41
42#define FUSE_UNKNOWN_INO 0xffffffff
43#define OFFSET_MAX 0x7fffffffffffffffLL
44
45struct fuse_config {
46 unsigned int uid;
47 unsigned int gid;
48 unsigned int umask;
49 double entry_timeout;
50 double negative_timeout;
51 double attr_timeout;
52 double ac_attr_timeout;
53 int ac_attr_timeout_set;
54 int debug;
55 int hard_remove;
56 int use_ino;
57 int readdir_ino;
58 int set_mode;
59 int set_uid;
60 int set_gid;
61 int direct_io;
62 int kernel_cache;
63 int intr;
64 int intr_signal;
65 int help;
66#ifdef __SOLARIS__
67 int auto_cache;
68 char *modules;
69#endif /* __SOLARIS__ */
70};
71
72struct fuse_fs {
73 struct fuse_operations op;
74 void *user_data;
75#ifdef __SOLARIS__
76 struct fuse_module *m;
77#endif /* __SOLARIS__ */
78};
79
80#ifdef __SOLARIS__
81struct fusemod_so {
82 void *handle;
83 int ctr;
84};
85#endif /* __SOLARIS__ */
86
87struct fuse {
88 struct fuse_session *se;
89 struct node **name_table;
90 size_t name_table_size;
91 struct node **id_table;
92 size_t id_table_size;
93 fuse_ino_t ctr;
94 unsigned int generation;
95 unsigned int hidectr;
96 pthread_mutex_t lock;
97 pthread_rwlock_t tree_lock;
98 struct fuse_config conf;
99 int intr_installed;
100 struct fuse_fs *fs;
101};
102
103struct lock {
104 int type;
105 off_t start;
106 off_t end;
107 pid_t pid;
108 uint64_t owner;
109 struct lock *next;
110};
111
112struct node {
113 struct node *name_next;
114 struct node *id_next;
115 fuse_ino_t nodeid;
116 unsigned int generation;
117 int refctr;
118 struct node *parent;
119 char *name;
120 uint64_t nlookup;
121 int open_count;
122 int is_hidden;
123#ifdef __SOLARIS__
124 struct timespec stat_updated;
125 struct timespec mtime;
126 off_t size;
127 int cache_valid;
128#endif /* __SOLARIS__ */
129 struct lock *locks;
130};
131
132struct fuse_dh {
133 pthread_mutex_t lock;
134 struct fuse *fuse;
135 fuse_req_t req;
136 char *contents;
137 int allocated;
138 unsigned len;
139 unsigned size;
140 unsigned needlen;
141 int filled;
142 uint64_t fh;
143 int error;
144 fuse_ino_t nodeid;
145};
146
147struct fuse_context_i {
148 struct fuse_context ctx;
149 fuse_req_t req;
150};
151
152static pthread_key_t fuse_context_key;
153static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
154static int fuse_context_ref;
155
156#ifdef __SOLARIS__
157
158static struct fusemod_so *fuse_current_so;
159static struct fuse_module *fuse_modules;
160
161static int fuse_load_so_name(const char *soname)
162{
163 struct fusemod_so *so;
164
165 so = calloc(1, sizeof(struct fusemod_so));
166 if (!so) {
167 fprintf(stderr, "fuse: memory allocation failed\n");
168 return -1;
169 }
170
171 fuse_current_so = so;
172 so->handle = dlopen(soname, RTLD_NOW);
173 fuse_current_so = NULL;
174 if (!so->handle) {
175 fprintf(stderr, "fuse: %s\n", dlerror());
176 goto err;
177 }
178 if (!so->ctr) {
179 fprintf(stderr, "fuse: %s did not register any modules", soname);
180 goto err;
181 }
182 return 0;
183
184 err:
185 if (so->handle)
186 dlclose(so->handle);
187 free(so);
188 return -1;
189}
190
191static int fuse_load_so_module(const char *module)
192{
193 int res;
194 char *soname = malloc(strlen(module) + 64);
195 if (!soname) {
196 fprintf(stderr, "fuse: memory allocation failed\n");
197 return -1;
198 }
199 sprintf(soname, "libfusemod_%s.so", module);
200 res = fuse_load_so_name(soname);
201 free(soname);
202 return res;
203}
204
205static struct fuse_module *fuse_find_module(const char *module)
206{
207 struct fuse_module *m;
208 for (m = fuse_modules; m; m = m->next) {
209 if (strcmp(module, m->name) == 0) {
210 m->ctr++;
211 break;
212 }
213 }
214 return m;
215}
216
217static struct fuse_module *fuse_get_module(const char *module)
218{
219 struct fuse_module *m;
220
221 pthread_mutex_lock(&fuse_context_lock);
222 m = fuse_find_module(module);
223 if (!m) {
224 int err = fuse_load_so_module(module);
225 if (!err)
226 m = fuse_find_module(module);
227 }
228 pthread_mutex_unlock(&fuse_context_lock);
229 return m;
230}
231
232static void fuse_put_module(struct fuse_module *m)
233{
234 pthread_mutex_lock(&fuse_context_lock);
235 assert(m->ctr > 0);
236 m->ctr--;
237 if (!m->ctr && m->so) {
238 struct fusemod_so *so = m->so;
239 assert(so->ctr > 0);
240 so->ctr--;
241 if (!so->ctr) {
242 struct fuse_module **mp;
243 for (mp = &fuse_modules; *mp;) {
244 if ((*mp)->so == so)
245 *mp = (*mp)->next;
246 else
247 mp = &(*mp)->next;
248 }
249 dlclose(so->handle);
250 free(so);
251 }
252 }
253 pthread_mutex_unlock(&fuse_context_lock);
254}
255#endif /* __SOLARIS__ */
256
257static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
258{
259 size_t hash = nodeid % f->id_table_size;
260 struct node *node;
261
262 for (node = f->id_table[hash]; node != NULL; node = node->id_next)
263 if (node->nodeid == nodeid)
264 return node;
265
266 return NULL;
267}
268
269static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
270{
271 struct node *node = get_node_nocheck(f, nodeid);
272 if (!node) {
273 fprintf(stderr, "fuse internal error: node %llu not found\n",
274 (unsigned long long) nodeid);
275 abort();
276 }
277 return node;
278}
279
280static void free_node(struct node *node)
281{
282 free(node->name);
283 free(node);
284}
285
286static void unhash_id(struct fuse *f, struct node *node)
287{
288 size_t hash = node->nodeid % f->id_table_size;
289 struct node **nodep = &f->id_table[hash];
290
291 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
292 if (*nodep == node) {
293 *nodep = node->id_next;
294 return;
295 }
296}
297
298static void hash_id(struct fuse *f, struct node *node)
299{
300 size_t hash = node->nodeid % f->id_table_size;
301 node->id_next = f->id_table[hash];
302 f->id_table[hash] = node;
303}
304
305static unsigned int name_hash(struct fuse *f, fuse_ino_t parent,
306 const char *name)
307{
308 unsigned int hash = *name;
309
310 if (hash)
311 for (name += 1; *name != '\0'; name++)
312 hash = (hash << 5) - hash + *name;
313
314 return (hash + parent) % f->name_table_size;
315}
316
317static void unref_node(struct fuse *f, struct node *node);
318
319static void unhash_name(struct fuse *f, struct node *node)
320{
321 if (node->name) {
322 size_t hash = name_hash(f, node->parent->nodeid, node->name);
323 struct node **nodep = &f->name_table[hash];
324
325 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
326 if (*nodep == node) {
327 *nodep = node->name_next;
328 node->name_next = NULL;
329 unref_node(f, node->parent);
330 free(node->name);
331 node->name = NULL;
332 node->parent = NULL;
333 return;
334 }
335 fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n",
336 (unsigned long long) node->nodeid);
337 abort();
338 }
339}
340
341static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
342 const char *name)
343{
344 size_t hash = name_hash(f, parentid, name);
345 struct node *parent = get_node(f, parentid);
346 node->name = strdup(name);
347 if (node->name == NULL)
348 return -1;
349
350 parent->refctr ++;
351 node->parent = parent;
352 node->name_next = f->name_table[hash];
353 f->name_table[hash] = node;
354 return 0;
355}
356
357static void delete_node(struct fuse *f, struct node *node)
358{
359 if (f->conf.debug)
360 fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid);
361
362 assert(!node->name);
363 unhash_id(f, node);
364 free_node(node);
365}
366
367static void unref_node(struct fuse *f, struct node *node)
368{
369 assert(node->refctr > 0);
370 node->refctr --;
371 if (!node->refctr)
372 delete_node(f, node);
373}
374
375static fuse_ino_t next_id(struct fuse *f)
376{
377 do {
378 f->ctr = (f->ctr + 1) & 0xffffffff;
379 if (!f->ctr)
380 f->generation ++;
381 } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
382 get_node_nocheck(f, f->ctr) != NULL);
383 return f->ctr;
384}
385
386static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
387 const char *name)
388{
389 size_t hash = name_hash(f, parent, name);
390 struct node *node;
391
392 for (node = f->name_table[hash]; node != NULL; node = node->name_next)
393 if (node->parent->nodeid == parent && strcmp(node->name, name) == 0)
394 return node;
395
396 return NULL;
397}
398
399static struct node *find_node(struct fuse *f, fuse_ino_t parent,
400 const char *name)
401{
402 struct node *node;
403
404 pthread_mutex_lock(&f->lock);
405 node = lookup_node(f, parent, name);
406 if (node == NULL) {
407 node = (struct node *) calloc(1, sizeof(struct node));
408 if (node == NULL)
409 goto out_err;
410
411 node->refctr = 1;
412 node->nodeid = next_id(f);
413 node->open_count = 0;
414 node->is_hidden = 0;
415 node->generation = f->generation;
416 if (hash_name(f, node, parent, name) == -1) {
417 free(node);
418 node = NULL;
419 goto out_err;
420 }
421 hash_id(f, node);
422 }
423 node->nlookup ++;
424 out_err:
425 pthread_mutex_unlock(&f->lock);
426 return node;
427}
428
429#ifndef __SOLARIS__
430static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
431#else /* __SOLARIS__ */
432static char *add_name(char *buf, char *s, const char *name)
433#endif /* __SOLARIS__ */
434{
435 size_t len = strlen(name);
436
437#ifndef __SOLARIS__
438 if (s - len <= *buf) {
439 unsigned pathlen = *bufsize - (s - *buf);
440 unsigned newbufsize = *bufsize;
441 char *newbuf;
442
443 while (newbufsize < pathlen + len + 1) {
444 if (newbufsize >= 0x80000000)
445 newbufsize = 0xffffffff;
446 else
447 newbufsize *= 2;
448 }
449
450 newbuf = realloc(*buf, newbufsize);
451 if (newbuf == NULL)
452 return NULL;
453
454 *buf = newbuf;
455 s = newbuf + newbufsize - pathlen;
456 memmove(s, newbuf + *bufsize - pathlen, pathlen);
457 *bufsize = newbufsize;
458 }
459 s -= len;
460#else /* ! __SOLARIS__ */
461 s -= len;
462 if (s <= buf) {
463 fprintf(stderr, "fuse: path too long: ...%s\n", s + len);
464 return NULL;
465 }
466#endif /* __SOLARIS__ */
467 strncpy(s, name, len);
468 s--;
469 *s = '/';
470
471 return s;
472}
473
474static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
475{
476#ifdef __SOLARIS__
477 char buf[FUSE_MAX_PATH];
478 char *s = buf + FUSE_MAX_PATH - 1;
479 struct node *node;
480
481 *s = '\0';
482
483 if (name != NULL) {
484 s = add_name(buf, s, name);
485 if (s == NULL)
486 return NULL;
487 }
488
489 pthread_mutex_lock(&f->lock);
490 for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
491 node = node->parent) {
492 if (node->name == NULL) {
493 s = NULL;
494 break;
495 }
496
497 s = add_name(buf, s, node->name);
498 if (s == NULL)
499 break;
500 }
501 pthread_mutex_unlock(&f->lock);
502
503 if (node == NULL || s == NULL)
504 return NULL;
505 else if (*s == '\0')
506 return strdup("/");
507 else
508 return strdup(s);
509
510#else /* __SOLARIS__ */
511
512 unsigned bufsize = 256;
513 char *buf;
514 char *s;
515 struct node *node;
516
517 buf = malloc(bufsize);
518 if (buf == NULL)
519 return NULL;
520
521 s = buf + bufsize - 1;
522 *s = '\0';
523
524 if (name != NULL) {
525 s = add_name(&buf, &bufsize, s, name);
526 if (s == NULL)
527 goto out_free;
528 }
529
530 pthread_mutex_lock(&f->lock);
531 for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
532 node = node->parent) {
533 if (node->name == NULL) {
534 s = NULL;
535 break;
536 }
537
538 s = add_name(&buf, &bufsize, s, node->name);
539 if (s == NULL)
540 break;
541 }
542 pthread_mutex_unlock(&f->lock);
543
544 if (node == NULL || s == NULL)
545 goto out_free;
546
547 if (s[0])
548 memmove(buf, s, bufsize - (s - buf));
549 else
550 strcpy(buf, "/");
551 return buf;
552
553out_free:
554 free(buf);
555 return NULL;
556#endif /* __SOLARIS__ */
557}
558
559static char *get_path(struct fuse *f, fuse_ino_t nodeid)
560{
561 return get_path_name(f, nodeid, NULL);
562}
563
564static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
565{
566 struct node *node;
567 if (nodeid == FUSE_ROOT_ID)
568 return;
569 pthread_mutex_lock(&f->lock);
570 node = get_node(f, nodeid);
571 assert(node->nlookup >= nlookup);
572 node->nlookup -= nlookup;
573 if (!node->nlookup) {
574 unhash_name(f, node);
575 unref_node(f, node);
576 }
577 pthread_mutex_unlock(&f->lock);
578}
579
580static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
581{
582 struct node *node;
583
584 pthread_mutex_lock(&f->lock);
585 node = lookup_node(f, dir, name);
586 if (node != NULL)
587 unhash_name(f, node);
588 pthread_mutex_unlock(&f->lock);
589}
590
591static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
592 fuse_ino_t newdir, const char *newname, int hide)
593{
594 struct node *node;
595 struct node *newnode;
596 int err = 0;
597
598 pthread_mutex_lock(&f->lock);
599 node = lookup_node(f, olddir, oldname);
600 newnode = lookup_node(f, newdir, newname);
601 if (node == NULL)
602 goto out;
603
604 if (newnode != NULL) {
605 if (hide) {
606 fprintf(stderr, "fuse: hidden file got created during hiding\n");
607 err = -EBUSY;
608 goto out;
609 }
610 unhash_name(f, newnode);
611 }
612
613 unhash_name(f, node);
614 if (hash_name(f, node, newdir, newname) == -1) {
615 err = -ENOMEM;
616 goto out;
617 }
618
619 if (hide)
620 node->is_hidden = 1;
621
622 out:
623 pthread_mutex_unlock(&f->lock);
624 return err;
625}
626
627static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
628{
629 if (!f->conf.use_ino)
630 stbuf->st_ino = nodeid;
631 if (f->conf.set_mode)
632 stbuf->st_mode = (stbuf->st_mode & S_IFMT) | (0777 & ~f->conf.umask);
633 if (f->conf.set_uid)
634 stbuf->st_uid = f->conf.uid;
635 if (f->conf.set_gid)
636 stbuf->st_gid = f->conf.gid;
637}
638
639static struct fuse *req_fuse(fuse_req_t req)
640{
641 return (struct fuse *) fuse_req_userdata(req);
642}
643
644static void fuse_intr_sighandler(int sig)
645{
646 (void) sig;
647 /* Nothing to do */
648}
649
650struct fuse_intr_data {
651 pthread_t id;
652 pthread_cond_t cond;
653 int finished;
654};
655
656static void fuse_interrupt(fuse_req_t req, void *d_)
657{
658 struct fuse_intr_data *d = d_;
659 struct fuse *f = req_fuse(req);
660
661 if (d->id == pthread_self())
662 return;
663
664 pthread_mutex_lock(&f->lock);
665 while (!d->finished) {
666 struct timeval now;
667 struct timespec timeout;
668
669 pthread_kill(d->id, f->conf.intr_signal);
670 gettimeofday(&now, NULL);
671 timeout.tv_sec = now.tv_sec + 1;
672 timeout.tv_nsec = now.tv_usec * 1000;
673 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
674 }
675 pthread_mutex_unlock(&f->lock);
676}
677
678static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
679 struct fuse_intr_data *d)
680{
681 pthread_mutex_lock(&f->lock);
682 d->finished = 1;
683 pthread_cond_broadcast(&d->cond);
684 pthread_mutex_unlock(&f->lock);
685 fuse_req_interrupt_func(req, NULL, NULL);
686 pthread_cond_destroy(&d->cond);
687}
688
689static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
690{
691 d->id = pthread_self();
692 pthread_cond_init(&d->cond, NULL);
693 d->finished = 0;
694 fuse_req_interrupt_func(req, fuse_interrupt, d);
695}
696
697static void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
698 struct fuse_intr_data *d)
699{
700 if (f->conf.intr)
701 fuse_do_finish_interrupt(f, req, d);
702}
703
704static void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
705 struct fuse_intr_data *d)
706{
707 if (f->conf.intr)
708 fuse_do_prepare_interrupt(req, d);
709}
710
711int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
712{
713 fuse_get_context()->private_data = fs->user_data;
714 if (fs->op.getattr)
715 return fs->op.getattr(path, buf);
716 else
717 return -ENOSYS;
718}
719
720int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
721 struct fuse_file_info *fi)
722{
723 fuse_get_context()->private_data = fs->user_data;
724 if (fs->op.fgetattr)
725 return fs->op.fgetattr(path, buf, fi);
726 else if (fs->op.getattr)
727 return fs->op.getattr(path, buf);
728 else
729 return -ENOSYS;
730}
731
732int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
733 const char *newpath)
734{
735 fuse_get_context()->private_data = fs->user_data;
736 if (fs->op.rename)
737 return fs->op.rename(oldpath, newpath);
738 else
739 return -ENOSYS;
740}
741
742int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
743{
744 fuse_get_context()->private_data = fs->user_data;
745 if (fs->op.unlink)
746 return fs->op.unlink(path);
747 else
748 return -ENOSYS;
749}
750
751int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
752{
753 fuse_get_context()->private_data = fs->user_data;
754 if (fs->op.rmdir)
755 return fs->op.rmdir(path);
756 else
757 return -ENOSYS;
758}
759
760int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
761{
762 fuse_get_context()->private_data = fs->user_data;
763 if (fs->op.symlink)
764 return fs->op.symlink(linkname, path);
765 else
766 return -ENOSYS;
767}
768
769int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
770{
771 fuse_get_context()->private_data = fs->user_data;
772 if (fs->op.link)
773 return fs->op.link(oldpath, newpath);
774 else
775 return -ENOSYS;
776}
777
778int fuse_fs_release(struct fuse_fs *fs, const char *path,
779 struct fuse_file_info *fi)
780{
781 fuse_get_context()->private_data = fs->user_data;
782 if (fs->op.release)
783 return fs->op.release(path, fi);
784 else
785 return 0;
786}
787
788int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
789 struct fuse_file_info *fi)
790{
791 fuse_get_context()->private_data = fs->user_data;
792 if (fs->op.opendir)
793 return fs->op.opendir(path, fi);
794 else
795 return 0;
796}
797
798int fuse_fs_open(struct fuse_fs *fs, const char *path,
799 struct fuse_file_info *fi)
800{
801 fuse_get_context()->private_data = fs->user_data;
802 if (fs->op.open)
803 return fs->op.open(path, fi);
804 else
805 return 0;
806}
807
808int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
809 off_t off, struct fuse_file_info *fi)
810{
811 fuse_get_context()->private_data = fs->user_data;
812 if (fs->op.read)
813 return fs->op.read(path, buf, size, off, fi);
814 else
815 return -ENOSYS;
816}
817
818int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf,
819 size_t size, off_t off, struct fuse_file_info *fi)
820{
821 fuse_get_context()->private_data = fs->user_data;
822 if (fs->op.write)
823 return fs->op.write(path, buf, size, off, fi);
824 else
825 return -ENOSYS;
826}
827
828int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
829 struct fuse_file_info *fi)
830{
831 fuse_get_context()->private_data = fs->user_data;
832 if (fs->op.fsync)
833 return fs->op.fsync(path, datasync, fi);
834 else
835 return -ENOSYS;
836}
837
838int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
839 struct fuse_file_info *fi)
840{
841 fuse_get_context()->private_data = fs->user_data;
842 if (fs->op.fsyncdir)
843 return fs->op.fsyncdir(path, datasync, fi);
844 else
845 return -ENOSYS;
846}
847
848int fuse_fs_flush(struct fuse_fs *fs, const char *path,
849 struct fuse_file_info *fi)
850{
851 fuse_get_context()->private_data = fs->user_data;
852 if (fs->op.flush)
853 return fs->op.flush(path, fi);
854 else
855 return -ENOSYS;
856}
857
858#if HAVE_SYS_STATVFS_H
859int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
860{
861 fuse_get_context()->private_data = fs->user_data;
862 if (fs->op.statfs)
863 return fs->op.statfs(path, buf);
864 else {
865 buf->f_namemax = 255;
866 buf->f_bsize = 512;
867 return 0;
868 }
869}
870#endif
871
872int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
873 struct fuse_file_info *fi)
874{
875 fuse_get_context()->private_data = fs->user_data;
876 if (fs->op.releasedir)
877 return fs->op.releasedir(path, fi);
878 else
879 return 0;
880}
881
882int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
883 fuse_fill_dir_t filler, off_t off,
884 struct fuse_file_info *fi)
885{
886 fuse_get_context()->private_data = fs->user_data;
887 if (fs->op.readdir)
888 return fs->op.readdir(path, buf, filler, off, fi);
889 else
890 return -ENOSYS;
891}
892
893int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
894 struct fuse_file_info *fi)
895{
896 fuse_get_context()->private_data = fs->user_data;
897 if (fs->op.create)
898 return fs->op.create(path, mode, fi);
899 else
900 return -ENOSYS;
901}
902
903int fuse_fs_lock(struct fuse_fs *fs, const char *path,
904 struct fuse_file_info *fi, int cmd, struct flock *lock)
905{
906 fuse_get_context()->private_data = fs->user_data;
907 if (fs->op.lock)
908 return fs->op.lock(path, fi, cmd, lock);
909 else
910 return -ENOSYS;
911}
912
913int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
914{
915 fuse_get_context()->private_data = fs->user_data;
916 if (fs->op.chown)
917 return fs->op.chown(path, uid, gid);
918 else
919 return -ENOSYS;
920}
921
922int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
923{
924 fuse_get_context()->private_data = fs->user_data;
925 if (fs->op.truncate)
926 return fs->op.truncate(path, size);
927 else
928 return -ENOSYS;
929}
930
931int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
932 struct fuse_file_info *fi)
933{
934 fuse_get_context()->private_data = fs->user_data;
935 if (fs->op.ftruncate)
936 return fs->op.ftruncate(path, size, fi);
937 else if (fs->op.truncate)
938 return fs->op.truncate(path, size);
939 else
940 return -ENOSYS;
941}
942
943int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
944 const struct timespec tv[2])
945{
946 fuse_get_context()->private_data = fs->user_data;
947 if (fs->op.utimens)
948 return fs->op.utimens(path, tv);
949 else if(fs->op.utime) {
950 struct utimbuf buf;
951 buf.actime = tv[0].tv_sec;
952 buf.modtime = tv[1].tv_sec;
953 return fs->op.utime(path, &buf);
954 } else
955 return -ENOSYS;
956}
957
958int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
959{
960 fuse_get_context()->private_data = fs->user_data;
961 if (fs->op.access)
962 return fs->op.access(path, mask);
963 else
964 return -ENOSYS;
965}
966
967int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
968 size_t len)
969{
970 fuse_get_context()->private_data = fs->user_data;
971 if (fs->op.readlink)
972 return fs->op.readlink(path, buf, len);
973 else
974 return -ENOSYS;
975}
976
977int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
978 dev_t rdev)
979{
980 fuse_get_context()->private_data = fs->user_data;
981 if (fs->op.mknod)
982 return fs->op.mknod(path, mode, rdev);
983 else
984 return -ENOSYS;
985}
986
987int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
988{
989 fuse_get_context()->private_data = fs->user_data;
990 if (fs->op.mkdir)
991 return fs->op.mkdir(path, mode);
992 else
993 return -ENOSYS;
994}
995
996int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
997 const char *value, size_t size, int flags)
998{
999 fuse_get_context()->private_data = fs->user_data;
1000 if (fs->op.setxattr)
1001 return fs->op.setxattr(path, name, value, size, flags);
1002 else
1003 return -ENOSYS;
1004}
1005
1006int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
1007 char *value, size_t size)
1008{
1009 fuse_get_context()->private_data = fs->user_data;
1010 if (fs->op.getxattr)
1011 return fs->op.getxattr(path, name, value, size);
1012 else
1013 return -ENOSYS;
1014}
1015
1016int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
1017 size_t size)
1018{
1019 fuse_get_context()->private_data = fs->user_data;
1020 if (fs->op.listxattr)
1021 return fs->op.listxattr(path, list, size);
1022 else
1023 return -ENOSYS;
1024}
1025
1026int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
1027 uint64_t *idx)
1028{
1029 fuse_get_context()->private_data = fs->user_data;
1030 if (fs->op.bmap)
1031 return fs->op.bmap(path, blocksize, idx);
1032 else
1033 return -ENOSYS;
1034}
1035
1036int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
1037{
1038 fuse_get_context()->private_data = fs->user_data;
1039 if (fs->op.removexattr)
1040 return fs->op.removexattr(path, name);
1041 else
1042 return -ENOSYS;
1043}
1044
1045static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
1046{
1047 struct node *node;
1048 int isopen = 0;
1049 pthread_mutex_lock(&f->lock);
1050 node = lookup_node(f, dir, name);
1051 if (node && node->open_count > 0)
1052 isopen = 1;
1053 pthread_mutex_unlock(&f->lock);
1054 return isopen;
1055}
1056
1057static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
1058 char *newname, size_t bufsize)
1059{
1060 struct stat buf;
1061 struct node *node;
1062 struct node *newnode;
1063 char *newpath;
1064 int res;
1065 int failctr = 10;
1066
1067 do {
1068 pthread_mutex_lock(&f->lock);
1069 node = lookup_node(f, dir, oldname);
1070 if (node == NULL) {
1071 pthread_mutex_unlock(&f->lock);
1072 return NULL;
1073 }
1074 do {
1075 f->hidectr ++;
1076 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
1077 (unsigned int) node->nodeid, f->hidectr);
1078 newnode = lookup_node(f, dir, newname);
1079 } while(newnode);
1080 pthread_mutex_unlock(&f->lock);
1081
1082 newpath = get_path_name(f, dir, newname);
1083 if (!newpath)
1084 break;
1085
1086 res = fuse_fs_getattr(f->fs, newpath, &buf);
1087 if (res == -ENOENT)
1088 break;
1089 free(newpath);
1090 newpath = NULL;
1091 } while(res == 0 && --failctr);
1092
1093 return newpath;
1094}
1095
1096static int hide_node(struct fuse *f, const char *oldpath,
1097 fuse_ino_t dir, const char *oldname)
1098{
1099 char newname[64];
1100 char *newpath;
1101 int err = -EBUSY;
1102
1103 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
1104 if (newpath) {
1105 err = fuse_fs_rename(f->fs, oldpath, newpath);
1106 if (!err)
1107 err = rename_node(f, dir, oldname, dir, newname, 1);
1108 free(newpath);
1109 }
1110 return err;
1111}
1112
1113#ifdef __SOLARIS__
1114
1115static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
1116{
1117 return stbuf->st_mtime == ts->tv_sec && ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
1118}
1119
1120#ifndef CLOCK_MONOTONIC
1121#define CLOCK_MONOTONIC CLOCK_REALTIME
1122#endif
1123
1124static void curr_time(struct timespec *now)
1125{
1126 static clockid_t clockid = CLOCK_MONOTONIC;
1127 int res = clock_gettime(clockid, now);
1128 if (res == -1 && errno == EINVAL) {
1129 clockid = CLOCK_REALTIME;
1130 res = clock_gettime(clockid, now);
1131 }
1132 if (res == -1) {
1133 perror("fuse: clock_gettime");
1134 abort();
1135 }
1136}
1137
1138static void update_stat(struct node *node, const struct stat *stbuf)
1139{
1140 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
1141 stbuf->st_size != node->size))
1142 node->cache_valid = 0;
1143 node->mtime.tv_sec = stbuf->st_mtime;
1144 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
1145 node->size = stbuf->st_size;
1146 curr_time(&node->stat_updated);
1147}
1148
1149#endif /* __SOLARIS__ */
1150
1151static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
1152 const char *name, const char *path,
1153 struct fuse_entry_param *e, struct fuse_file_info *fi)
1154{
1155 int res;
1156
1157 memset(e, 0, sizeof(struct fuse_entry_param));
1158 if (fi)
1159 res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
1160 else
1161 res = fuse_fs_getattr(f->fs, path, &e->attr);
1162 if (res == 0) {
1163 struct node *node;
1164
1165 node = find_node(f, nodeid, name);
1166 if (node == NULL)
1167 res = -ENOMEM;
1168 else {
1169 e->ino = node->nodeid;
1170 e->generation = node->generation;
1171 e->entry_timeout = f->conf.entry_timeout;
1172 e->attr_timeout = f->conf.attr_timeout;
1173#ifdef __SOLARIS__
1174 if (f->conf.auto_cache) {
1175 pthread_mutex_lock(&f->lock);
1176 update_stat(node, &e->attr);
1177 pthread_mutex_unlock(&f->lock);
1178 }
1179#endif /* __SOLARIS__ */
1180 set_stat(f, e->ino, &e->attr);
1181 if (f->conf.debug)
1182 fprintf(stderr, " NODEID: %lu\n", (unsigned long) e->ino);
1183 }
1184 }
1185 return res;
1186}
1187
1188static struct fuse_context_i *fuse_get_context_internal(void)
1189{
1190 struct fuse_context_i *c;
1191
1192 c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
1193 if (c == NULL) {
1194 c = (struct fuse_context_i *) malloc(sizeof(struct fuse_context_i));
1195 if (c == NULL) {
1196 /* This is hard to deal with properly, so just abort. If
1197 memory is so low that the context cannot be allocated,
1198 there's not much hope for the filesystem anyway */
1199 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
1200 abort();
1201 }
1202 pthread_setspecific(fuse_context_key, c);
1203 }
1204 return c;
1205}
1206
1207static void fuse_freecontext(void *data)
1208{
1209 free(data);
1210}
1211
1212static int fuse_create_context_key(void)
1213{
1214 int err = 0;
1215 pthread_mutex_lock(&fuse_context_lock);
1216 if (!fuse_context_ref) {
1217 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
1218 if (err) {
1219 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
1220 strerror(err));
1221 pthread_mutex_unlock(&fuse_context_lock);
1222 return -1;
1223 }
1224 }
1225 fuse_context_ref++;
1226 pthread_mutex_unlock(&fuse_context_lock);
1227 return 0;
1228}
1229
1230static void fuse_delete_context_key(void)
1231{
1232 pthread_mutex_lock(&fuse_context_lock);
1233 fuse_context_ref--;
1234 if (!fuse_context_ref) {
1235 free(pthread_getspecific(fuse_context_key));
1236 pthread_key_delete(fuse_context_key);
1237 }
1238 pthread_mutex_unlock(&fuse_context_lock);
1239}
1240
1241static struct fuse *req_fuse_prepare(fuse_req_t req)
1242{
1243 struct fuse_context_i *c = fuse_get_context_internal();
1244 const struct fuse_ctx *ctx = fuse_req_ctx(req);
1245 c->req = req;
1246 c->ctx.fuse = req_fuse(req);
1247 c->ctx.uid = ctx->uid;
1248 c->ctx.gid = ctx->gid;
1249 c->ctx.pid = ctx->pid;
1250#ifdef POSIXACLS
1251 c->ctx.umask = ctx->umask;
1252#endif
1253 return c->ctx.fuse;
1254}
1255
1256#ifndef __SOLARIS__
1257static void reply_err(fuse_req_t req, int err)
1258#else /* __SOLARIS__ */
1259static inline void reply_err(fuse_req_t req, int err)
1260#endif /* __SOLARIS__ */
1261{
1262 /* fuse_reply_err() uses non-negated errno values */
1263 fuse_reply_err(req, -err);
1264}
1265
1266static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
1267 int err)
1268{
1269 if (!err) {
1270 struct fuse *f = req_fuse(req);
1271 if (fuse_reply_entry(req, e) == -ENOENT)
1272 forget_node(f, e->ino, 1);
1273 } else
1274 reply_err(req, err);
1275}
1276
1277void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
1278{
1279 fuse_get_context()->private_data = fs->user_data;
1280 if (fs->op.init)
1281 fs->user_data = fs->op.init(conn);
1282}
1283
1284static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
1285{
1286 struct fuse *f = (struct fuse *) data;
1287 struct fuse_context_i *c = fuse_get_context_internal();
1288
1289 memset(c, 0, sizeof(*c));
1290 c->ctx.fuse = f;
1291 fuse_fs_init(f->fs, conn);
1292}
1293
1294void fuse_fs_destroy(struct fuse_fs *fs)
1295{
1296 fuse_get_context()->private_data = fs->user_data;
1297 if (fs->op.destroy)
1298 fs->op.destroy(fs->user_data);
1299#ifdef __SOLARIS__
1300 if (fs->m)
1301 fuse_put_module(fs->m);
1302#endif /* __SOLARIS__ */
1303 free(fs);
1304}
1305
1306static void fuse_lib_destroy(void *data)
1307{
1308 struct fuse *f = (struct fuse *) data;
1309 struct fuse_context_i *c = fuse_get_context_internal();
1310
1311 memset(c, 0, sizeof(*c));
1312 c->ctx.fuse = f;
1313 fuse_fs_destroy(f->fs);
1314 f->fs = NULL;
1315}
1316
1317static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
1318 const char *name)
1319{
1320 struct fuse *f = req_fuse_prepare(req);
1321 struct fuse_entry_param e;
1322 char *path;
1323 int err;
1324
1325 err = -ENOENT;
1326 pthread_rwlock_rdlock(&f->tree_lock);
1327 path = get_path_name(f, parent, name);
1328 if (path != NULL) {
1329 struct fuse_intr_data d;
1330 if (f->conf.debug)
1331 fprintf(stderr, "LOOKUP %s\n", path);
1332 fuse_prepare_interrupt(f, req, &d);
1333 err = lookup_path(f, parent, name, path, &e, NULL);
1334 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
1335 e.ino = 0;
1336 e.entry_timeout = f->conf.negative_timeout;
1337 err = 0;
1338 }
1339 fuse_finish_interrupt(f, req, &d);
1340 free(path);
1341 }
1342 pthread_rwlock_unlock(&f->tree_lock);
1343 reply_entry(req, &e, err);
1344}
1345
1346static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
1347 unsigned long nlookup)
1348{
1349 struct fuse *f = req_fuse(req);
1350 if (f->conf.debug)
1351 fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino, nlookup);
1352 forget_node(f, ino, nlookup);
1353 fuse_reply_none(req);
1354}
1355
1356static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
1357 struct fuse_file_info *fi)
1358{
1359 struct fuse *f = req_fuse_prepare(req);
1360 struct stat buf;
1361 char *path;
1362 int err;
1363
1364 (void) fi;
1365 memset(&buf, 0, sizeof(buf));
1366
1367 err = -ENOENT;
1368 pthread_rwlock_rdlock(&f->tree_lock);
1369 path = get_path(f, ino);
1370 if (path != NULL) {
1371 struct fuse_intr_data d;
1372 fuse_prepare_interrupt(f, req, &d);
1373 err = fuse_fs_getattr(f->fs, path, &buf);
1374 fuse_finish_interrupt(f, req, &d);
1375 free(path);
1376 }
1377 pthread_rwlock_unlock(&f->tree_lock);
1378 if (!err) {
1379#ifdef __SOLARIS__
1380 if (f->conf.auto_cache) {
1381 pthread_mutex_lock(&f->lock);
1382 update_stat(get_node(f, ino), &buf);
1383 pthread_mutex_unlock(&f->lock);
1384 }
1385#endif /* __SOLARIS__ */
1386 set_stat(f, ino, &buf);
1387 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
1388 } else
1389 reply_err(req, err);
1390}
1391
1392int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
1393{
1394 fuse_get_context()->private_data = fs->user_data;
1395 if (fs->op.chmod)
1396 return fs->op.chmod(path, mode);
1397 else
1398 return -ENOSYS;
1399}
1400
1401static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
1402 int valid, struct fuse_file_info *fi)
1403{
1404 struct fuse *f = req_fuse_prepare(req);
1405 struct stat buf;
1406 char *path;
1407 int err;
1408
1409 err = -ENOENT;
1410 pthread_rwlock_rdlock(&f->tree_lock);
1411 path = get_path(f, ino);
1412 if (path != NULL) {
1413 struct fuse_intr_data d;
1414 fuse_prepare_interrupt(f, req, &d);
1415 err = 0;
1416 if (!err && (valid & FUSE_SET_ATTR_MODE))
1417 err = fuse_fs_chmod(f->fs, path, attr->st_mode);
1418 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
1419 uid_t uid =
1420 (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1;
1421 gid_t gid =
1422 (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1;
1423 err = fuse_fs_chown(f->fs, path, uid, gid);
1424 }
1425 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
1426 if (fi)
1427 err = fuse_fs_ftruncate(f->fs, path, attr->st_size, fi);
1428 else
1429 err = fuse_fs_truncate(f->fs, path, attr->st_size);
1430 }
1431#ifdef HAVE_UTIMENSAT
1432 if (!err &&
1433 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
1434 struct timespec tv[2];
1435
1436 tv[0].tv_sec = 0;
1437 tv[1].tv_sec = 0;
1438 tv[0].tv_nsec = UTIME_OMIT;
1439 tv[1].tv_nsec = UTIME_OMIT;
1440
1441 if (valid & FUSE_SET_ATTR_ATIME_NOW)
1442 tv[0].tv_nsec = UTIME_NOW;
1443 else if (valid & FUSE_SET_ATTR_ATIME)
1444 tv[0] = attr->st_atim;
1445
1446 if (valid & FUSE_SET_ATTR_MTIME_NOW)
1447 tv[1].tv_nsec = UTIME_NOW;
1448 else if (valid & FUSE_SET_ATTR_MTIME)
1449 tv[1] = attr->st_mtim;
1450
1451 err = fuse_fs_utimens(f->fs, path, tv);
1452 } else
1453#endif
1454 if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
1455 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
1456 struct timespec tv[2];
1457 tv[0].tv_sec = attr->st_atime;
1458 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
1459 tv[1].tv_sec = attr->st_mtime;
1460 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
1461 err = fuse_fs_utimens(f->fs, path, tv);
1462 }
1463 if (!err)
1464 err = fuse_fs_getattr(f->fs, path, &buf);
1465 fuse_finish_interrupt(f, req, &d);
1466 free(path);
1467 }
1468 pthread_rwlock_unlock(&f->tree_lock);
1469 if (!err) {
1470#ifdef __SOLARIS__
1471 if (f->conf.auto_cache) {
1472 pthread_mutex_lock(&f->lock);
1473 update_stat(get_node(f, ino), &buf);
1474 pthread_mutex_unlock(&f->lock);
1475 }
1476#endif /* __SOLARIS__ */
1477 set_stat(f, ino, &buf);
1478 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
1479 } else
1480 reply_err(req, err);
1481}
1482
1483static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
1484{
1485 struct fuse *f = req_fuse_prepare(req);
1486 char *path;
1487 int err;
1488
1489 err = -ENOENT;
1490 pthread_rwlock_rdlock(&f->tree_lock);
1491 path = get_path(f, ino);
1492 if (path != NULL) {
1493 struct fuse_intr_data d;
1494 if (f->conf.debug)
1495 fprintf(stderr, "ACCESS %s 0%o\n", path, mask);
1496 fuse_prepare_interrupt(f, req, &d);
1497 err = fuse_fs_access(f->fs, path, mask);
1498 fuse_finish_interrupt(f, req, &d);
1499 free(path);
1500 }
1501 pthread_rwlock_unlock(&f->tree_lock);
1502 reply_err(req, err);
1503}
1504
1505static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
1506{
1507 struct fuse *f = req_fuse_prepare(req);
1508 char linkname[PATH_MAX + 1];
1509 char *path;
1510 int err;
1511
1512 err = -ENOENT;
1513 pthread_rwlock_rdlock(&f->tree_lock);
1514 path = get_path(f, ino);
1515 if (path != NULL) {
1516 struct fuse_intr_data d;
1517 fuse_prepare_interrupt(f, req, &d);
1518 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
1519 fuse_finish_interrupt(f, req, &d);
1520 free(path);
1521 }
1522 pthread_rwlock_unlock(&f->tree_lock);
1523 if (!err) {
1524 linkname[PATH_MAX] = '\0';
1525 fuse_reply_readlink(req, linkname);
1526 } else
1527 reply_err(req, err);
1528}
1529
1530static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
1531 mode_t mode, dev_t rdev)
1532{
1533 struct fuse *f = req_fuse_prepare(req);
1534 struct fuse_entry_param e;
1535 char *path;
1536 int err;
1537
1538 err = -ENOENT;
1539 pthread_rwlock_rdlock(&f->tree_lock);
1540 path = get_path_name(f, parent, name);
1541 if (path) {
1542 struct fuse_intr_data d;
1543 if (f->conf.debug)
1544 fprintf(stderr, "MKNOD %s\n", path);
1545 fuse_prepare_interrupt(f, req, &d);
1546 err = -ENOSYS;
1547 if (S_ISREG(mode)) {
1548 struct fuse_file_info fi;
1549
1550 memset(&fi, 0, sizeof(fi));
1551 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
1552 err = fuse_fs_create(f->fs, path, mode, &fi);
1553 if (!err) {
1554 err = lookup_path(f, parent, name, path, &e, &fi);
1555 fuse_fs_release(f->fs, path, &fi);
1556 }
1557 }
1558 if (err == -ENOSYS) {
1559 err = fuse_fs_mknod(f->fs, path, mode, rdev);
1560 if (!err)
1561 err = lookup_path(f, parent, name, path, &e, NULL);
1562 }
1563 fuse_finish_interrupt(f, req, &d);
1564 free(path);
1565 }
1566 pthread_rwlock_unlock(&f->tree_lock);
1567 reply_entry(req, &e, err);
1568}
1569
1570static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
1571 mode_t mode)
1572{
1573 struct fuse *f = req_fuse_prepare(req);
1574 struct fuse_entry_param e;
1575 char *path;
1576 int err;
1577
1578 err = -ENOENT;
1579 pthread_rwlock_rdlock(&f->tree_lock);
1580 path = get_path_name(f, parent, name);
1581 if (path != NULL) {
1582 struct fuse_intr_data d;
1583 if (f->conf.debug)
1584 fprintf(stderr, "MKDIR %s\n", path);
1585 fuse_prepare_interrupt(f, req, &d);
1586 err = fuse_fs_mkdir(f->fs, path, mode);
1587 if (!err)
1588 err = lookup_path(f, parent, name, path, &e, NULL);
1589 fuse_finish_interrupt(f, req, &d);
1590 free(path);
1591 }
1592 pthread_rwlock_unlock(&f->tree_lock);
1593 reply_entry(req, &e, err);
1594}
1595
1596static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
1597 const char *name)
1598{
1599 struct fuse *f = req_fuse_prepare(req);
1600 char *path;
1601 int err;
1602
1603 err = -ENOENT;
1604 pthread_rwlock_wrlock(&f->tree_lock);
1605 path = get_path_name(f, parent, name);
1606 if (path != NULL) {
1607 struct fuse_intr_data d;
1608 if (f->conf.debug)
1609 fprintf(stderr, "UNLINK %s\n", path);
1610 fuse_prepare_interrupt(f, req, &d);
1611 if (!f->conf.hard_remove && is_open(f, parent, name))
1612 err = hide_node(f, path, parent, name);
1613 else {
1614 err = fuse_fs_unlink(f->fs, path);
1615 if (!err)
1616 remove_node(f, parent, name);
1617 }
1618 fuse_finish_interrupt(f, req, &d);
1619 free(path);
1620 }
1621 pthread_rwlock_unlock(&f->tree_lock);
1622 reply_err(req, err);
1623}
1624
1625static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
1626{
1627 struct fuse *f = req_fuse_prepare(req);
1628 char *path;
1629 int err;
1630
1631 err = -ENOENT;
1632 pthread_rwlock_wrlock(&f->tree_lock);
1633 path = get_path_name(f, parent, name);
1634 if (path != NULL) {
1635 struct fuse_intr_data d;
1636 if (f->conf.debug)
1637 fprintf(stderr, "RMDIR %s\n", path);
1638 fuse_prepare_interrupt(f, req, &d);
1639 err = fuse_fs_rmdir(f->fs, path);
1640 fuse_finish_interrupt(f, req, &d);
1641 if (!err)
1642 remove_node(f, parent, name);
1643 free(path);
1644 }
1645 pthread_rwlock_unlock(&f->tree_lock);
1646 reply_err(req, err);
1647}
1648
1649static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
1650 fuse_ino_t parent, const char *name)
1651{
1652 struct fuse *f = req_fuse_prepare(req);
1653 struct fuse_entry_param e;
1654 char *path;
1655 int err;
1656
1657 err = -ENOENT;
1658 pthread_rwlock_rdlock(&f->tree_lock);
1659 path = get_path_name(f, parent, name);
1660 if (path != NULL) {
1661 struct fuse_intr_data d;
1662 if (f->conf.debug)
1663 fprintf(stderr, "SYMLINK %s\n", path);
1664 fuse_prepare_interrupt(f, req, &d);
1665 err = fuse_fs_symlink(f->fs, linkname, path);
1666 if (!err)
1667 err = lookup_path(f, parent, name, path, &e, NULL);
1668 fuse_finish_interrupt(f, req, &d);
1669 free(path);
1670 }
1671 pthread_rwlock_unlock(&f->tree_lock);
1672 reply_entry(req, &e, err);
1673}
1674
1675static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
1676 const char *oldname, fuse_ino_t newdir,
1677 const char *newname)
1678{
1679 struct fuse *f = req_fuse_prepare(req);
1680 char *oldpath;
1681 char *newpath;
1682 int err;
1683
1684 err = -ENOENT;
1685 pthread_rwlock_wrlock(&f->tree_lock);
1686 oldpath = get_path_name(f, olddir, oldname);
1687 if (oldpath != NULL) {
1688 newpath = get_path_name(f, newdir, newname);
1689 if (newpath != NULL) {
1690 struct fuse_intr_data d;
1691 if (f->conf.debug)
1692 fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath);
1693 err = 0;
1694 fuse_prepare_interrupt(f, req, &d);
1695 if (!f->conf.hard_remove && is_open(f, newdir, newname))
1696 err = hide_node(f, newpath, newdir, newname);
1697 if (!err) {
1698 err = fuse_fs_rename(f->fs, oldpath, newpath);
1699 if (!err)
1700 err = rename_node(f, olddir, oldname, newdir, newname, 0);
1701 }
1702 fuse_finish_interrupt(f, req, &d);
1703 free(newpath);
1704 }
1705 free(oldpath);
1706 }
1707 pthread_rwlock_unlock(&f->tree_lock);
1708 reply_err(req, err);
1709}
1710
1711static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
1712 const char *newname)
1713{
1714 struct fuse *f = req_fuse_prepare(req);
1715 struct fuse_entry_param e;
1716 char *oldpath;
1717 char *newpath;
1718 int err;
1719
1720 err = -ENOENT;
1721 pthread_rwlock_rdlock(&f->tree_lock);
1722 oldpath = get_path(f, ino);
1723 if (oldpath != NULL) {
1724 newpath = get_path_name(f, newparent, newname);
1725 if (newpath != NULL) {
1726 struct fuse_intr_data d;
1727 if (f->conf.debug)
1728 fprintf(stderr, "LINK %s\n", newpath);
1729 fuse_prepare_interrupt(f, req, &d);
1730 err = fuse_fs_link(f->fs, oldpath, newpath);
1731 if (!err)
1732 err = lookup_path(f, newparent, newname, newpath, &e, NULL);
1733 fuse_finish_interrupt(f, req, &d);
1734 free(newpath);
1735 }
1736 free(oldpath);
1737 }
1738 pthread_rwlock_unlock(&f->tree_lock);
1739 reply_entry(req, &e, err);
1740}
1741
1742static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
1743 struct fuse_file_info *fi)
1744{
1745 struct node *node;
1746 int unlink_hidden = 0;
1747
1748 fuse_fs_release(f->fs, path ? path : "-", fi);
1749
1750 pthread_mutex_lock(&f->lock);
1751 node = get_node(f, ino);
1752 assert(node->open_count > 0);
1753 --node->open_count;
1754 if (node->is_hidden && !node->open_count) {
1755 unlink_hidden = 1;
1756 node->is_hidden = 0;
1757 }
1758 pthread_mutex_unlock(&f->lock);
1759
1760 if(unlink_hidden && path)
1761 fuse_fs_unlink(f->fs, path);
1762}
1763
1764static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
1765 const char *name, mode_t mode,
1766 struct fuse_file_info *fi)
1767{
1768 struct fuse *f = req_fuse_prepare(req);
1769 struct fuse_intr_data d;
1770 struct fuse_entry_param e;
1771 char *path;
1772 int err;
1773
1774 err = -ENOENT;
1775 pthread_rwlock_rdlock(&f->tree_lock);
1776 path = get_path_name(f, parent, name);
1777 if (path) {
1778 fuse_prepare_interrupt(f, req, &d);
1779 err = fuse_fs_create(f->fs, path, mode, fi);
1780 if (!err) {
1781 err = lookup_path(f, parent, name, path, &e, fi);
1782 if (err)
1783 fuse_fs_release(f->fs, path, fi);
1784 else if (!S_ISREG(e.attr.st_mode)) {
1785 err = -EIO;
1786 fuse_fs_release(f->fs, path, fi);
1787 forget_node(f, e.ino, 1);
1788 } else {
1789 if (f->conf.direct_io)
1790 fi->direct_io = 1;
1791 if (f->conf.kernel_cache)
1792 fi->keep_cache = 1;
1793
1794 }
1795 }
1796 fuse_finish_interrupt(f, req, &d);
1797 }
1798 if (!err) {
1799 pthread_mutex_lock(&f->lock);
1800 get_node(f, e.ino)->open_count++;
1801 pthread_mutex_unlock(&f->lock);
1802 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
1803 /* The open syscall was interrupted, so it must be cancelled */
1804 fuse_prepare_interrupt(f, req, &d);
1805 fuse_do_release(f, e.ino, path, fi);
1806 fuse_finish_interrupt(f, req, &d);
1807 forget_node(f, e.ino, 1);
1808 } else if (f->conf.debug) {
1809 fprintf(stderr, " CREATE[%llu] flags: 0x%x %s\n",
1810 (unsigned long long) fi->fh, fi->flags, path);
1811 }
1812 } else
1813 reply_err(req, err);
1814
1815 if (path)
1816 free(path);
1817
1818 pthread_rwlock_unlock(&f->tree_lock);
1819}
1820
1821#ifdef __SOLARIS__
1822
1823static double diff_timespec(const struct timespec *t1,
1824 const struct timespec *t2)
1825{
1826 return (t1->tv_sec - t2->tv_sec) +
1827 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
1828}
1829
1830static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
1831 struct fuse_file_info *fi)
1832{
1833 struct node *node;
1834
1835 pthread_mutex_lock(&f->lock);
1836 node = get_node(f, ino);
1837 if (node->cache_valid) {
1838 struct timespec now;
1839
1840 curr_time(&now);
1841 if (diff_timespec(&now, &node->stat_updated) > f->conf.ac_attr_timeout) {
1842 struct stat stbuf;
1843 int err;
1844 pthread_mutex_unlock(&f->lock);
1845 err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
1846 pthread_mutex_lock(&f->lock);
1847 if (!err)
1848 update_stat(node, &stbuf);
1849 else
1850 node->cache_valid = 0;
1851 }
1852 }
1853 if (node->cache_valid)
1854 fi->keep_cache = 1;
1855
1856 node->cache_valid = 1;
1857 pthread_mutex_unlock(&f->lock);
1858}
1859
1860#endif /* __SOLARIS__ */
1861
1862static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
1863 struct fuse_file_info *fi)
1864{
1865 struct fuse *f = req_fuse_prepare(req);
1866 struct fuse_intr_data d;
1867 char *path = NULL;
1868 int err = 0;
1869
1870 err = -ENOENT;
1871 pthread_rwlock_rdlock(&f->tree_lock);
1872 path = get_path(f, ino);
1873 if (path) {
1874 fuse_prepare_interrupt(f, req, &d);
1875 err = fuse_fs_open(f->fs, path, fi);
1876 if (!err) {
1877 if (f->conf.direct_io)
1878 fi->direct_io = 1;
1879 if (f->conf.kernel_cache)
1880 fi->keep_cache = 1;
1881#ifdef __SOLARIS__
1882
1883 if (f->conf.auto_cache)
1884 open_auto_cache(f, ino, path, fi);
1885#endif /* __SOLARIS__ */
1886 }
1887 fuse_finish_interrupt(f, req, &d);
1888 }
1889 if (!err) {
1890 pthread_mutex_lock(&f->lock);
1891 get_node(f, ino)->open_count++;
1892 pthread_mutex_unlock(&f->lock);
1893 if (fuse_reply_open(req, fi) == -ENOENT) {
1894 /* The open syscall was interrupted, so it must be cancelled */
1895 fuse_prepare_interrupt(f, req, &d);
1896 fuse_do_release(f, ino, path, fi);
1897 fuse_finish_interrupt(f, req, &d);
1898 } else if (f->conf.debug) {
1899 fprintf(stderr, "OPEN[%llu] flags: 0x%x %s\n",
1900 (unsigned long long) fi->fh, fi->flags, path);
1901 }
1902 } else
1903 reply_err(req, err);
1904
1905 if (path)
1906 free(path);
1907 pthread_rwlock_unlock(&f->tree_lock);
1908}
1909
1910static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
1911 off_t off, struct fuse_file_info *fi)
1912{
1913 struct fuse *f = req_fuse_prepare(req);
1914 char *path;
1915 char *buf;
1916 int res;
1917
1918 buf = (char *) malloc(size);
1919 if (buf == NULL) {
1920 reply_err(req, -ENOMEM);
1921 return;
1922 }
1923
1924 res = -ENOENT;
1925 pthread_rwlock_rdlock(&f->tree_lock);
1926 path = get_path(f, ino);
1927 if (path != NULL) {
1928 struct fuse_intr_data d;
1929 if (f->conf.debug)
1930 fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",
1931 (unsigned long long) fi->fh, (unsigned long) size,
1932 (unsigned long long) off);
1933
1934 fuse_prepare_interrupt(f, req, &d);
1935 res = fuse_fs_read(f->fs, path, buf, size, off, fi);
1936 fuse_finish_interrupt(f, req, &d);
1937 free(path);
1938 }
1939 pthread_rwlock_unlock(&f->tree_lock);
1940
1941 if (res >= 0) {
1942 if (f->conf.debug)
1943 fprintf(stderr, " READ[%llu] %u bytes\n",
1944 (unsigned long long)fi->fh, res);
1945 if ((size_t) res > size)
1946 fprintf(stderr, "fuse: read too many bytes");
1947 fuse_reply_buf(req, buf, res);
1948 } else
1949 reply_err(req, res);
1950
1951 free(buf);
1952}
1953
1954static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
1955 size_t size, off_t off, struct fuse_file_info *fi)
1956{
1957 struct fuse *f = req_fuse_prepare(req);
1958 char *path;
1959 int res;
1960
1961 res = -ENOENT;
1962 pthread_rwlock_rdlock(&f->tree_lock);
1963 path = get_path(f, ino);
1964 if (path != NULL) {
1965 struct fuse_intr_data d;
1966 if (f->conf.debug)
1967 fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n",
1968 fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
1969 (unsigned long) size, (unsigned long long) off);
1970
1971 fuse_prepare_interrupt(f, req, &d);
1972 res = fuse_fs_write(f->fs, path, buf, size, off, fi);
1973 fuse_finish_interrupt(f, req, &d);
1974 free(path);
1975 }
1976 pthread_rwlock_unlock(&f->tree_lock);
1977
1978 if (res >= 0) {
1979 if (f->conf.debug)
1980 fprintf(stderr, " WRITE%s[%llu] %u bytes\n",
1981 fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
1982 res);
1983 if ((size_t) res > size)
1984 fprintf(stderr, "fuse: wrote too many bytes");
1985 fuse_reply_write(req, res);
1986 } else
1987 reply_err(req, res);
1988}
1989
1990static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
1991 struct fuse_file_info *fi)
1992{
1993 struct fuse *f = req_fuse_prepare(req);
1994 char *path;
1995 int err;
1996
1997 err = -ENOENT;
1998 pthread_rwlock_rdlock(&f->tree_lock);
1999 path = get_path(f, ino);
2000 if (path != NULL) {
2001 struct fuse_intr_data d;
2002 if (f->conf.debug)
2003 fprintf(stderr, "FSYNC[%llu]\n", (unsigned long long) fi->fh);
2004 fuse_prepare_interrupt(f, req, &d);
2005 err = fuse_fs_fsync(f->fs, path, datasync, fi);
2006 fuse_finish_interrupt(f, req, &d);
2007 free(path);
2008 }
2009 pthread_rwlock_unlock(&f->tree_lock);
2010 reply_err(req, err);
2011}
2012
2013static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
2014 struct fuse_file_info *fi)
2015{
2016 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
2017 memset(fi, 0, sizeof(struct fuse_file_info));
2018 fi->fh = dh->fh;
2019 fi->fh_old = dh->fh;
2020 return dh;
2021}
2022
2023static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
2024 struct fuse_file_info *llfi)
2025{
2026 struct fuse *f = req_fuse_prepare(req);
2027 struct fuse_intr_data d;
2028 struct fuse_dh *dh;
2029 struct fuse_file_info fi;
2030 char *path;
2031 int err;
2032
2033 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
2034 if (dh == NULL) {
2035 reply_err(req, -ENOMEM);
2036 return;
2037 }
2038 memset(dh, 0, sizeof(struct fuse_dh));
2039 dh->fuse = f;
2040 dh->contents = NULL;
2041 dh->len = 0;
2042 dh->filled = 0;
2043 dh->nodeid = ino;
2044 fuse_mutex_init(&dh->lock);
2045
2046 llfi->fh = (uintptr_t) dh;
2047
2048 memset(&fi, 0, sizeof(fi));
2049 fi.flags = llfi->flags;
2050
2051 err = -ENOENT;
2052 pthread_rwlock_rdlock(&f->tree_lock);
2053 path = get_path(f, ino);
2054 if (path != NULL) {
2055 fuse_prepare_interrupt(f, req, &d);
2056 err = fuse_fs_opendir(f->fs, path, &fi);
2057 fuse_finish_interrupt(f, req, &d);
2058 dh->fh = fi.fh;
2059 }
2060 if (!err) {
2061 if (fuse_reply_open(req, llfi) == -ENOENT) {
2062 /* The opendir syscall was interrupted, so it must be cancelled */
2063 fuse_prepare_interrupt(f, req, &d);
2064 fuse_fs_releasedir(f->fs, path, &fi);
2065 fuse_finish_interrupt(f, req, &d);
2066 pthread_mutex_destroy(&dh->lock);
2067 free(dh);
2068 }
2069 } else {
2070 reply_err(req, err);
2071#ifndef __SOLARIS__
2072 pthread_mutex_destroy(&dh->lock);
2073#endif /* ! __SOLARIS__ */
2074 free(dh);
2075 }
2076 free(path);
2077 pthread_rwlock_unlock(&f->tree_lock);
2078}
2079
2080static int extend_contents(struct fuse_dh *dh, unsigned minsize)
2081{
2082 if (minsize > dh->size) {
2083 char *newptr;
2084 unsigned newsize = dh->size;
2085 if (!newsize)
2086 newsize = 1024;
2087#ifndef __SOLARIS__
2088 while (newsize < minsize) {
2089 if (newsize >= 0x80000000)
2090 newsize = 0xffffffff;
2091 else
2092 newsize *= 2;
2093 }
2094#else /* __SOLARIS__ */
2095 while (newsize < minsize)
2096 newsize *= 2;
2097#endif /* __SOLARIS__ */
2098
2099 newptr = (char *) realloc(dh->contents, newsize);
2100 if (!newptr) {
2101 dh->error = -ENOMEM;
2102 return -1;
2103 }
2104 dh->contents = newptr;
2105 dh->size = newsize;
2106 }
2107 return 0;
2108}
2109
2110static int fill_dir(void *dh_, const char *name, const struct stat *statp,
2111 off_t off)
2112{
2113 struct fuse_dh *dh = (struct fuse_dh *) dh_;
2114 struct stat stbuf;
2115 size_t newlen;
2116
2117 if (statp)
2118 stbuf = *statp;
2119 else {
2120 memset(&stbuf, 0, sizeof(stbuf));
2121 stbuf.st_ino = FUSE_UNKNOWN_INO;
2122 }
2123
2124 if (!dh->fuse->conf.use_ino) {
2125 stbuf.st_ino = FUSE_UNKNOWN_INO;
2126 if (dh->fuse->conf.readdir_ino) {
2127 struct node *node;
2128 pthread_mutex_lock(&dh->fuse->lock);
2129 node = lookup_node(dh->fuse, dh->nodeid, name);
2130 if (node)
2131 stbuf.st_ino = (ino_t) node->nodeid;
2132 pthread_mutex_unlock(&dh->fuse->lock);
2133 }
2134 }
2135
2136 if (off) {
2137 if (extend_contents(dh, dh->needlen) == -1)
2138 return 1;
2139
2140 dh->filled = 0;
2141 newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len,
2142 dh->needlen - dh->len, name,
2143 &stbuf, off);
2144 if (newlen > dh->needlen)
2145 return 1;
2146 } else {
2147 newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
2148 if (extend_contents(dh, newlen) == -1)
2149 return 1;
2150
2151 fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len,
2152 name, &stbuf, newlen);
2153 }
2154 dh->len = newlen;
2155 return 0;
2156}
2157
2158static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2159 size_t size, off_t off, struct fuse_dh *dh,
2160 struct fuse_file_info *fi)
2161{
2162 int err = -ENOENT;
2163 char *path;
2164 pthread_rwlock_rdlock(&f->tree_lock);
2165 path = get_path(f, ino);
2166 if (path != NULL) {
2167 struct fuse_intr_data d;
2168
2169 dh->len = 0;
2170 dh->error = 0;
2171 dh->needlen = size;
2172 dh->filled = 1;
2173 dh->req = req;
2174 fuse_prepare_interrupt(f, req, &d);
2175 err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
2176 fuse_finish_interrupt(f, req, &d);
2177 dh->req = NULL;
2178 if (!err)
2179 err = dh->error;
2180 if (err)
2181 dh->filled = 0;
2182 free(path);
2183 }
2184 pthread_rwlock_unlock(&f->tree_lock);
2185 return err;
2186}
2187
2188static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
2189 off_t off, struct fuse_file_info *llfi)
2190{
2191 struct fuse *f = req_fuse_prepare(req);
2192 struct fuse_file_info fi;
2193 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
2194
2195 pthread_mutex_lock(&dh->lock);
2196 /* According to SUS, directory contents need to be refreshed on
2197 rewinddir() */
2198 if (!off)
2199 dh->filled = 0;
2200
2201 if (!dh->filled) {
2202 int err = readdir_fill(f, req, ino, size, off, dh, &fi);
2203 if (err) {
2204 reply_err(req, err);
2205 goto out;
2206 }
2207 }
2208 if (dh->filled) {
2209 if (off < dh->len) {
2210 if (off + size > dh->len)
2211 size = dh->len - off;
2212 } else
2213 size = 0;
2214 } else {
2215 size = dh->len;
2216 off = 0;
2217 }
2218 fuse_reply_buf(req, dh->contents + off, size);
2219 out:
2220 pthread_mutex_unlock(&dh->lock);
2221}
2222
2223static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
2224 struct fuse_file_info *llfi)
2225{
2226 struct fuse *f = req_fuse_prepare(req);
2227 struct fuse_intr_data d;
2228 struct fuse_file_info fi;
2229 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
2230 char *path;
2231
2232 pthread_rwlock_rdlock(&f->tree_lock);
2233 path = get_path(f, ino);
2234 fuse_prepare_interrupt(f, req, &d);
2235 fuse_fs_releasedir(f->fs, path ? path : "-", &fi);
2236 fuse_finish_interrupt(f, req, &d);
2237 if (path)
2238 free(path);
2239 pthread_rwlock_unlock(&f->tree_lock);
2240 pthread_mutex_lock(&dh->lock);
2241 pthread_mutex_unlock(&dh->lock);
2242 pthread_mutex_destroy(&dh->lock);
2243 free(dh->contents);
2244 free(dh);
2245 reply_err(req, 0);
2246}
2247
2248static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
2249 struct fuse_file_info *llfi)
2250{
2251 struct fuse *f = req_fuse_prepare(req);
2252 struct fuse_file_info fi;
2253 char *path;
2254 int err;
2255
2256 get_dirhandle(llfi, &fi);
2257
2258 err = -ENOENT;
2259 pthread_rwlock_rdlock(&f->tree_lock);
2260 path = get_path(f, ino);
2261 if (path != NULL) {
2262 struct fuse_intr_data d;
2263 fuse_prepare_interrupt(f, req, &d);
2264 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
2265 fuse_finish_interrupt(f, req, &d);
2266 free(path);
2267 }
2268 pthread_rwlock_unlock(&f->tree_lock);
2269 reply_err(req, err);
2270}
2271
2272#if HAVE_SYS_STATVFS_H
2273static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
2274{
2275 struct fuse *f = req_fuse_prepare(req);
2276 struct statvfs buf;
2277 char *path;
2278 int err;
2279
2280 memset(&buf, 0, sizeof(buf));
2281 pthread_rwlock_rdlock(&f->tree_lock);
2282 if (!ino) {
2283 err = -ENOMEM;
2284 path = strdup("/");
2285 } else {
2286 err = -ENOENT;
2287 path = get_path(f, ino);
2288 }
2289 if (path) {
2290 struct fuse_intr_data d;
2291 fuse_prepare_interrupt(f, req, &d);
2292 err = fuse_fs_statfs(f->fs, path, &buf);
2293 fuse_finish_interrupt(f, req, &d);
2294 free(path);
2295 }
2296 pthread_rwlock_unlock(&f->tree_lock);
2297
2298 if (!err)
2299 fuse_reply_statfs(req, &buf);
2300 else
2301 reply_err(req, err);
2302}
2303#endif
2304
2305static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
2306 const char *value, size_t size, int flags)
2307{
2308 struct fuse *f = req_fuse_prepare(req);
2309 char *path;
2310 int err;
2311
2312 err = -ENOENT;
2313 pthread_rwlock_rdlock(&f->tree_lock);
2314 path = get_path(f, ino);
2315 if (path != NULL) {
2316 struct fuse_intr_data d;
2317 fuse_prepare_interrupt(f, req, &d);
2318 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
2319 fuse_finish_interrupt(f, req, &d);
2320 free(path);
2321 }
2322 pthread_rwlock_unlock(&f->tree_lock);
2323 reply_err(req, err);
2324}
2325
2326static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2327 const char *name, char *value, size_t size)
2328{
2329 int err;
2330 char *path;
2331
2332 err = -ENOENT;
2333 pthread_rwlock_rdlock(&f->tree_lock);
2334 path = get_path(f, ino);
2335 if (path != NULL) {
2336 struct fuse_intr_data d;
2337 fuse_prepare_interrupt(f, req, &d);
2338 err = fuse_fs_getxattr(f->fs, path, name, value, size);
2339 fuse_finish_interrupt(f, req, &d);
2340 free(path);
2341 }
2342 pthread_rwlock_unlock(&f->tree_lock);
2343 return err;
2344}
2345
2346static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
2347 size_t size)
2348{
2349 struct fuse *f = req_fuse_prepare(req);
2350 int res;
2351
2352 if (size) {
2353 char *value = (char *) malloc(size);
2354 if (value == NULL) {
2355 reply_err(req, -ENOMEM);
2356 return;
2357 }
2358 res = common_getxattr(f, req, ino, name, value, size);
2359 if (res > 0)
2360 fuse_reply_buf(req, value, res);
2361 else
2362 reply_err(req, res);
2363 free(value);
2364 } else {
2365 res = common_getxattr(f, req, ino, name, NULL, 0);
2366 if (res >= 0)
2367 fuse_reply_xattr(req, res);
2368 else
2369 reply_err(req, res);
2370 }
2371}
2372
2373static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2374 char *list, size_t size)
2375{
2376 char *path;
2377 int err;
2378
2379 err = -ENOENT;
2380 pthread_rwlock_rdlock(&f->tree_lock);
2381 path = get_path(f, ino);
2382 if (path != NULL) {
2383 struct fuse_intr_data d;
2384 fuse_prepare_interrupt(f, req, &d);
2385 err = fuse_fs_listxattr(f->fs, path, list, size);
2386 fuse_finish_interrupt(f, req, &d);
2387 free(path);
2388 }
2389 pthread_rwlock_unlock(&f->tree_lock);
2390 return err;
2391}
2392
2393static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
2394{
2395 struct fuse *f = req_fuse_prepare(req);
2396 int res;
2397
2398 if (size) {
2399 char *list = (char *) malloc(size);
2400 if (list == NULL) {
2401 reply_err(req, -ENOMEM);
2402 return;
2403 }
2404 res = common_listxattr(f, req, ino, list, size);
2405 if (res > 0)
2406 fuse_reply_buf(req, list, res);
2407 else
2408 reply_err(req, res);
2409 free(list);
2410 } else {
2411 res = common_listxattr(f, req, ino, NULL, 0);
2412 if (res >= 0)
2413 fuse_reply_xattr(req, res);
2414 else
2415 reply_err(req, res);
2416 }
2417}
2418
2419static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
2420 const char *name)
2421{
2422 struct fuse *f = req_fuse_prepare(req);
2423 char *path;
2424 int err;
2425
2426 err = -ENOENT;
2427 pthread_rwlock_rdlock(&f->tree_lock);
2428 path = get_path(f, ino);
2429 if (path != NULL) {
2430 struct fuse_intr_data d;
2431 fuse_prepare_interrupt(f, req, &d);
2432 err = fuse_fs_removexattr(f->fs, path, name);
2433 fuse_finish_interrupt(f, req, &d);
2434 free(path);
2435 }
2436 pthread_rwlock_unlock(&f->tree_lock);
2437 reply_err(req, err);
2438}
2439
2440static struct lock *locks_conflict(struct node *node, const struct lock *lock)
2441{
2442 struct lock *l;
2443
2444 for (l = node->locks; l; l = l->next)
2445 if (l->owner != lock->owner &&
2446 lock->start <= l->end && l->start <= lock->end &&
2447 (l->type == F_WRLCK || lock->type == F_WRLCK))
2448 break;
2449
2450 return l;
2451}
2452
2453static void delete_lock(struct lock **lockp)
2454{
2455 struct lock *l = *lockp;
2456 *lockp = l->next;
2457 free(l);
2458}
2459
2460static void insert_lock(struct lock **pos, struct lock *lock)
2461{
2462 lock->next = *pos;
2463 *pos = lock;
2464}
2465
2466static int locks_insert(struct node *node, struct lock *lock)
2467{
2468 struct lock **lp;
2469 struct lock *newl1 = NULL;
2470 struct lock *newl2 = NULL;
2471
2472 if (lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX) {
2473 newl1 = malloc(sizeof(struct lock));
2474 newl2 = malloc(sizeof(struct lock));
2475
2476 if (!newl1 || !newl2) {
2477 free(newl1);
2478 free(newl2);
2479 return -ENOLCK;
2480 }
2481 }
2482
2483 for (lp = &node->locks; *lp;) {
2484 struct lock *l = *lp;
2485 if (l->owner != lock->owner)
2486 goto skip;
2487
2488 if (lock->type == l->type) {
2489 if (l->end < lock->start - 1)
2490 goto skip;
2491 if (lock->end < l->start - 1)
2492 break;
2493 if (l->start <= lock->start && lock->end <= l->end)
2494 goto out;
2495 if (l->start < lock->start)
2496 lock->start = l->start;
2497 if (lock->end < l->end)
2498 lock->end = l->end;
2499 goto delete;
2500 } else {
2501 if (l->end < lock->start)
2502 goto skip;
2503 if (lock->end < l->start)
2504 break;
2505 if (lock->start <= l->start && l->end <= lock->end)
2506 goto delete;
2507 if (l->end <= lock->end) {
2508 l->end = lock->start - 1;
2509 goto skip;
2510 }
2511 if (lock->start <= l->start) {
2512 l->start = lock->end + 1;
2513 break;
2514 }
2515 *newl2 = *l;
2516 newl2->start = lock->end + 1;
2517 l->end = lock->start - 1;
2518 insert_lock(&l->next, newl2);
2519 newl2 = NULL;
2520 }
2521 skip:
2522 lp = &l->next;
2523 continue;
2524
2525 delete:
2526 delete_lock(lp);
2527 }
2528 if (lock->type != F_UNLCK) {
2529 *newl1 = *lock;
2530 insert_lock(lp, newl1);
2531 newl1 = NULL;
2532 }
2533out:
2534 free(newl1);
2535 free(newl2);
2536 return 0;
2537}
2538
2539static void flock_to_lock(struct flock *flock, struct lock *lock)
2540{
2541 memset(lock, 0, sizeof(struct lock));
2542 lock->type = flock->l_type;
2543 lock->start = flock->l_start;
2544 lock->end = flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
2545 lock->pid = flock->l_pid;
2546}
2547
2548static void lock_to_flock(struct lock *lock, struct flock *flock)
2549{
2550 flock->l_type = lock->type;
2551 flock->l_start = lock->start;
2552 flock->l_len = (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
2553 flock->l_pid = lock->pid;
2554}
2555
2556static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2557 const char *path, struct fuse_file_info *fi)
2558{
2559 struct fuse_intr_data d;
2560 struct flock lock;
2561 struct lock l;
2562 int err;
2563 int errlock;
2564
2565 fuse_prepare_interrupt(f, req, &d);
2566 memset(&lock, 0, sizeof(lock));
2567 lock.l_type = F_UNLCK;
2568 lock.l_whence = SEEK_SET;
2569 err = fuse_fs_flush(f->fs, path, fi);
2570 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
2571 fuse_finish_interrupt(f, req, &d);
2572
2573 if (errlock != -ENOSYS) {
2574 flock_to_lock(&lock, &l);
2575 l.owner = fi->lock_owner;
2576 pthread_mutex_lock(&f->lock);
2577 locks_insert(get_node(f, ino), &l);
2578 pthread_mutex_unlock(&f->lock);
2579
2580 /* if op.lock() is defined FLUSH is needed regardless of op.flush() */
2581 if (err == -ENOSYS)
2582 err = 0;
2583 }
2584 return err;
2585}
2586
2587static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
2588 struct fuse_file_info *fi)
2589{
2590 struct fuse *f = req_fuse_prepare(req);
2591 struct fuse_intr_data d;
2592 char *path;
2593 int err = 0;
2594
2595 pthread_rwlock_rdlock(&f->tree_lock);
2596 path = get_path(f, ino);
2597 if (f->conf.debug)
2598 fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n",
2599 fi->flush ? "+FLUSH" : "",
2600 (unsigned long long) fi->fh, fi->flags);
2601
2602 if (fi->flush) {
2603 err = fuse_flush_common(f, req, ino, path, fi);
2604 if (err == -ENOSYS)
2605 err = 0;
2606 }
2607
2608 fuse_prepare_interrupt(f, req, &d);
2609 fuse_do_release(f, ino, path, fi);
2610 fuse_finish_interrupt(f, req, &d);
2611 free(path);
2612 pthread_rwlock_unlock(&f->tree_lock);
2613
2614 reply_err(req, err);
2615}
2616
2617static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
2618 struct fuse_file_info *fi)
2619{
2620 struct fuse *f = req_fuse_prepare(req);
2621 char *path;
2622 int err;
2623
2624 pthread_rwlock_rdlock(&f->tree_lock);
2625 path = get_path(f, ino);
2626 if (path && f->conf.debug)
2627 fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh);
2628 err = fuse_flush_common(f, req, ino, path, fi);
2629 free(path);
2630 pthread_rwlock_unlock(&f->tree_lock);
2631 reply_err(req, err);
2632}
2633
2634static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
2635 struct fuse_file_info *fi, struct flock *lock,
2636 int cmd)
2637{
2638 struct fuse *f = req_fuse_prepare(req);
2639 char *path;
2640 int err;
2641
2642 err = -ENOENT;
2643 pthread_rwlock_rdlock(&f->tree_lock);
2644 path = get_path(f, ino);
2645 if (path != NULL) {
2646 struct fuse_intr_data d;
2647 fuse_prepare_interrupt(f, req, &d);
2648 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
2649 fuse_finish_interrupt(f, req, &d);
2650 free(path);
2651 }
2652 pthread_rwlock_unlock(&f->tree_lock);
2653 return err;
2654}
2655
2656static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
2657 struct fuse_file_info *fi, struct flock *lock)
2658{
2659 int err;
2660 struct lock l;
2661 struct lock *conflict;
2662 struct fuse *f = req_fuse(req);
2663
2664 flock_to_lock(lock, &l);
2665 l.owner = fi->lock_owner;
2666 pthread_mutex_lock(&f->lock);
2667 conflict = locks_conflict(get_node(f, ino), &l);
2668 if (conflict)
2669 lock_to_flock(conflict, lock);
2670 pthread_mutex_unlock(&f->lock);
2671 if (!conflict)
2672 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
2673 else
2674 err = 0;
2675
2676 if (!err)
2677 fuse_reply_lock(req, lock);
2678 else
2679 reply_err(req, err);
2680}
2681
2682static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
2683 struct fuse_file_info *fi, struct flock *lock,
2684 int should_sleep)
2685{
2686 int err = fuse_lock_common(req, ino, fi, lock, should_sleep ? F_SETLKW : F_SETLK);
2687 if (!err) {
2688 struct fuse *f = req_fuse(req);
2689 struct lock l;
2690 flock_to_lock(lock, &l);
2691 l.owner = fi->lock_owner;
2692 pthread_mutex_lock(&f->lock);
2693 locks_insert(get_node(f, ino), &l);
2694 pthread_mutex_unlock(&f->lock);
2695 }
2696 reply_err(req, err);
2697}
2698
2699static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
2700 uint64_t idx)
2701{
2702 struct fuse *f = req_fuse_prepare(req);
2703 struct fuse_intr_data d;
2704 char *path;
2705 int err;
2706
2707 err = -ENOENT;
2708 pthread_rwlock_rdlock(&f->tree_lock);
2709 path = get_path(f, ino);
2710 if (path != NULL) {
2711 fuse_prepare_interrupt(f, req, &d);
2712 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
2713 fuse_finish_interrupt(f, req, &d);
2714 free(path);
2715 }
2716 pthread_rwlock_unlock(&f->tree_lock);
2717 if (!err)
2718 fuse_reply_bmap(req, idx);
2719 else
2720 reply_err(req, err);
2721}
2722
2723static struct fuse_lowlevel_ops fuse_path_ops = {
2724 .init = fuse_lib_init,
2725 .destroy = fuse_lib_destroy,
2726 .lookup = fuse_lib_lookup,
2727 .forget = fuse_lib_forget,
2728 .getattr = fuse_lib_getattr,
2729 .setattr = fuse_lib_setattr,
2730 .access = fuse_lib_access,
2731 .readlink = fuse_lib_readlink,
2732 .mknod = fuse_lib_mknod,
2733 .mkdir = fuse_lib_mkdir,
2734 .unlink = fuse_lib_unlink,
2735 .rmdir = fuse_lib_rmdir,
2736 .symlink = fuse_lib_symlink,
2737 .rename = fuse_lib_rename,
2738 .link = fuse_lib_link,
2739 .create = fuse_lib_create,
2740 .open = fuse_lib_open,
2741 .read = fuse_lib_read,
2742 .write = fuse_lib_write,
2743 .flush = fuse_lib_flush,
2744 .release = fuse_lib_release,
2745 .fsync = fuse_lib_fsync,
2746 .opendir = fuse_lib_opendir,
2747 .readdir = fuse_lib_readdir,
2748 .releasedir = fuse_lib_releasedir,
2749 .fsyncdir = fuse_lib_fsyncdir,
2750#if HAVE_SYS_STATVFS_H
2751 .statfs = fuse_lib_statfs,
2752#endif
2753 .setxattr = fuse_lib_setxattr,
2754 .getxattr = fuse_lib_getxattr,
2755 .listxattr = fuse_lib_listxattr,
2756 .removexattr = fuse_lib_removexattr,
2757 .getlk = fuse_lib_getlk,
2758 .setlk = fuse_lib_setlk,
2759 .bmap = fuse_lib_bmap,
2760};
2761
2762struct fuse_session *fuse_get_session(struct fuse *f)
2763{
2764 return f->se;
2765}
2766
2767int fuse_loop(struct fuse *f)
2768{
2769 if (f)
2770 return fuse_session_loop(f->se);
2771 else
2772 return -1;
2773}
2774
2775void fuse_exit(struct fuse *f)
2776{
2777 fuse_session_exit(f->se);
2778}
2779
2780struct fuse_context *fuse_get_context(void)
2781{
2782 return &fuse_get_context_internal()->ctx;
2783}
2784
2785int fuse_interrupted(void)
2786{
2787 return fuse_req_interrupted(fuse_get_context_internal()->req);
2788}
2789
2790enum {
2791 KEY_HELP,
2792};
2793
2794#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
2795
2796static const struct fuse_opt fuse_lib_opts[] = {
2797 FUSE_OPT_KEY("-h", KEY_HELP),
2798 FUSE_OPT_KEY("--help", KEY_HELP),
2799 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
2800 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
2801 FUSE_LIB_OPT("debug", debug, 1),
2802 FUSE_LIB_OPT("-d", debug, 1),
2803 FUSE_LIB_OPT("hard_remove", hard_remove, 1),
2804 FUSE_LIB_OPT("use_ino", use_ino, 1),
2805 FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
2806 FUSE_LIB_OPT("direct_io", direct_io, 1),
2807 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
2808#ifdef __SOLARIS__
2809 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
2810 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
2811#endif /* __SOLARIS__ */
2812 FUSE_LIB_OPT("umask=", set_mode, 1),
2813 FUSE_LIB_OPT("umask=%o", umask, 0),
2814 FUSE_LIB_OPT("uid=", set_uid, 1),
2815 FUSE_LIB_OPT("uid=%d", uid, 0),
2816 FUSE_LIB_OPT("gid=", set_gid, 1),
2817 FUSE_LIB_OPT("gid=%d", gid, 0),
2818 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
2819 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
2820 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
2821 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
2822 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
2823 FUSE_LIB_OPT("intr", intr, 1),
2824 FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
2825#ifdef __SOLARIS__
2826 FUSE_LIB_OPT("modules=%s", modules, 0),
2827#endif /* __SOLARIS__ */
2828 FUSE_OPT_END
2829};
2830
2831static void fuse_lib_help(void)
2832{
2833 fprintf(stderr,
2834" -o hard_remove immediate removal (don't hide files)\n"
2835" -o use_ino let filesystem set inode numbers\n"
2836" -o readdir_ino try to fill in d_ino in readdir\n"
2837" -o direct_io use direct I/O\n"
2838" -o kernel_cache cache files in kernel\n"
2839#ifdef __SOLARIS__
2840" -o [no]auto_cache enable caching based on modification times\n"
2841#endif /* __SOLARIS__ */
2842" -o umask=M set file permissions (octal)\n"
2843" -o uid=N set file owner\n"
2844" -o gid=N set file group\n"
2845" -o entry_timeout=T cache timeout for names (1.0s)\n"
2846" -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
2847" -o attr_timeout=T cache timeout for attributes (1.0s)\n"
2848" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
2849" -o intr allow requests to be interrupted\n"
2850" -o intr_signal=NUM signal to send on interrupt (%i)\n"
2851#ifdef __SOLARIS__
2852" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
2853#endif /* __SOLARIS__ */
2854"\n", FUSE_DEFAULT_INTR_SIGNAL);
2855}
2856
2857#ifdef __SOLARIS__
2858
2859static void fuse_lib_help_modules(void)
2860{
2861 struct fuse_module *m;
2862 fprintf(stderr, "\nModule options:\n");
2863 pthread_mutex_lock(&fuse_context_lock);
2864 for (m = fuse_modules; m; m = m->next) {
2865 struct fuse_fs *fs = NULL;
2866 struct fuse_fs *newfs;
2867 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
2868 if (fuse_opt_add_arg(&args, "") != -1 &&
2869 fuse_opt_add_arg(&args, "-h") != -1) {
2870 fprintf(stderr, "\n[%s]\n", m->name);
2871 newfs = m->factory(&args, &fs);
2872 assert(newfs == NULL);
2873 }
2874 fuse_opt_free_args(&args);
2875 }
2876 pthread_mutex_unlock(&fuse_context_lock);
2877}
2878
2879int fuse_is_lib_option(const char *opt)
2880{
2881 return fuse_lowlevel_is_lib_option(opt) ||
2882 fuse_opt_match(fuse_lib_opts, opt);
2883}
2884
2885#endif /* __SOLARIS__ */
2886
2887static int fuse_lib_opt_proc(void *data, const char *arg, int key,
2888 struct fuse_args *outargs)
2889{
2890 (void) arg; (void) outargs;
2891
2892 if (key == KEY_HELP) {
2893 struct fuse_config *conf = (struct fuse_config *) data;
2894 fuse_lib_help();
2895 conf->help = 1;
2896 }
2897
2898 return 1;
2899}
2900
2901static int fuse_init_intr_signal(int signum, int *installed)
2902{
2903 struct sigaction old_sa;
2904
2905 if (sigaction(signum, NULL, &old_sa) == -1) {
2906 perror("fuse: cannot get old signal handler");
2907 return -1;
2908 }
2909
2910 if (old_sa.sa_handler == SIG_DFL) {
2911 struct sigaction sa;
2912
2913 memset(&sa, 0, sizeof(struct sigaction));
2914 sa.sa_handler = fuse_intr_sighandler;
2915 sigemptyset(&sa.sa_mask);
2916
2917 if (sigaction(signum, &sa, NULL) == -1) {
2918 perror("fuse: cannot set interrupt signal handler");
2919 return -1;
2920 }
2921 *installed = 1;
2922 }
2923 return 0;
2924}
2925
2926static void fuse_restore_intr_signal(int signum)
2927{
2928 struct sigaction sa;
2929
2930 memset(&sa, 0, sizeof(struct sigaction));
2931 sa.sa_handler = SIG_DFL;
2932 sigaction(signum, &sa, NULL);
2933}
2934
2935#ifdef __SOLARIS__
2936
2937static int fuse_push_module(struct fuse *f, const char *module,
2938 struct fuse_args *args)
2939{
2940 struct fuse_fs *newfs;
2941 struct fuse_module *m = fuse_get_module(module);
2942 struct fuse_fs *fs[2];
2943
2944 fs[0] = f->fs;
2945 fs[1] = NULL;
2946 if (!m)
2947 return -1;
2948
2949 newfs = m->factory(args, fs);
2950 if (!newfs) {
2951 fuse_put_module(m);
2952 return -1;
2953 }
2954 newfs->m = m;
2955 f->fs = newfs;
2956 return 0;
2957}
2958
2959#endif /* __SOLARIS__ */
2960
2961struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
2962 void *user_data)
2963{
2964 struct fuse_fs *fs;
2965
2966 if (sizeof(struct fuse_operations) < op_size) {
2967 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
2968 op_size = sizeof(struct fuse_operations);
2969 }
2970
2971 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
2972 if (!fs) {
2973 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
2974 return NULL;
2975 }
2976
2977 fs->user_data = user_data;
2978 if (op)
2979 memcpy(&fs->op, op, op_size);
2980 return fs;
2981}
2982
2983struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
2984 const struct fuse_operations *op, size_t op_size,
2985 void *user_data)
2986{
2987 struct fuse *f;
2988 struct node *root;
2989 struct fuse_fs *fs;
2990 struct fuse_lowlevel_ops llop = fuse_path_ops;
2991
2992 if (fuse_create_context_key() == -1)
2993 goto out;
2994
2995 f = (struct fuse *) calloc(1, sizeof(struct fuse));
2996 if (f == NULL) {
2997 fprintf(stderr, "fuse: failed to allocate fuse object\n");
2998 goto out_delete_context_key;
2999 }
3000
3001 fs = fuse_fs_new(op, op_size, user_data);
3002 if (!fs)
3003 goto out_free;
3004
3005 f->fs = fs;
3006
3007 /* Oh f**k, this is ugly! */
3008 if (!fs->op.lock) {
3009 llop.getlk = NULL;
3010 llop.setlk = NULL;
3011 }
3012
3013 f->conf.entry_timeout = 1.0;
3014 f->conf.attr_timeout = 1.0;
3015 f->conf.negative_timeout = 0.0;
3016 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
3017
3018 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1)
3019 goto out_free_fs;
3020
3021#ifdef __SOLARIS__
3022 if (f->conf.modules) {
3023 char *module;
3024 char *next;
3025
3026 for (module = f->conf.modules; module; module = next) {
3027 char *p;
3028 for (p = module; *p && *p != ':'; p++);
3029 next = *p ? p + 1 : NULL;
3030 *p = '\0';
3031 if (module[0] && fuse_push_module(f, module, args) == -1)
3032 goto out_free_fs;
3033 }
3034 }
3035#endif /* __SOLARIS__ */
3036
3037 if (!f->conf.ac_attr_timeout_set)
3038 f->conf.ac_attr_timeout = f->conf.attr_timeout;
3039
3040#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
3041 /*
3042 * In FreeBSD, we always use these settings as inode numbers are needed to
3043 * make getcwd(3) work.
3044 */
3045 f->conf.readdir_ino = 1;
3046#endif
3047
3048 f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
3049
3050 if (f->se == NULL) {
3051#ifdef __SOLARIS__
3052 if (f->conf.help)
3053 fuse_lib_help_modules();
3054#endif /* __SOLARIS__ */
3055 goto out_free_fs;
3056 }
3057
3058 fuse_session_add_chan(f->se, ch);
3059
3060 f->ctr = 0;
3061 f->generation = 0;
3062 /* FIXME: Dynamic hash table */
3063 f->name_table_size = 14057;
3064 f->name_table = (struct node **)
3065 calloc(1, sizeof(struct node *) * f->name_table_size);
3066 if (f->name_table == NULL) {
3067 fprintf(stderr, "fuse: memory allocation failed\n");
3068 goto out_free_session;
3069 }
3070
3071 f->id_table_size = 14057;
3072 f->id_table = (struct node **)
3073 calloc(1, sizeof(struct node *) * f->id_table_size);
3074 if (f->id_table == NULL) {
3075 fprintf(stderr, "fuse: memory allocation failed\n");
3076 goto out_free_name_table;
3077 }
3078
3079 fuse_mutex_init(&f->lock);
3080 pthread_rwlock_init(&f->tree_lock, NULL);
3081
3082 root = (struct node *) calloc(1, sizeof(struct node));
3083 if (root == NULL) {
3084 fprintf(stderr, "fuse: memory allocation failed\n");
3085 goto out_free_id_table;
3086 }
3087
3088 root->name = strdup("/");
3089 if (root->name == NULL) {
3090 fprintf(stderr, "fuse: memory allocation failed\n");
3091 goto out_free_root;
3092 }
3093
3094 if (f->conf.intr &&
3095 fuse_init_intr_signal(f->conf.intr_signal, &f->intr_installed) == -1)
3096 goto out_free_root_name;
3097
3098 root->parent = NULL;
3099 root->nodeid = FUSE_ROOT_ID;
3100 root->generation = 0;
3101 root->refctr = 1;
3102 root->nlookup = 1;
3103 hash_id(f, root);
3104
3105 return f;
3106
3107 out_free_root_name:
3108 free(root->name);
3109 out_free_root:
3110 free(root);
3111 out_free_id_table:
3112 free(f->id_table);
3113 out_free_name_table:
3114 free(f->name_table);
3115 out_free_session:
3116 fuse_session_destroy(f->se);
3117 out_free_fs:
3118 /* Horrible compatibility hack to stop the destructor from being
3119 called on the filesystem without init being called first */
3120 fs->op.destroy = NULL;
3121 fuse_fs_destroy(f->fs);
3122#ifdef __SOLARIS__
3123 free(f->conf.modules);
3124#endif /* __SOLARIS__ */
3125 out_free:
3126 free(f);
3127 out_delete_context_key:
3128 fuse_delete_context_key();
3129 out:
3130 return NULL;
3131}
3132
3133void fuse_destroy(struct fuse *f)
3134{
3135 size_t i;
3136
3137 if (f->conf.intr && f->intr_installed)
3138 fuse_restore_intr_signal(f->conf.intr_signal);
3139
3140 if (f->fs) {
3141 struct fuse_context_i *c = fuse_get_context_internal();
3142
3143 memset(c, 0, sizeof(*c));
3144 c->ctx.fuse = f;
3145
3146 for (i = 0; i < f->id_table_size; i++) {
3147 struct node *node;
3148
3149 for (node = f->id_table[i]; node != NULL; node = node->id_next) {
3150 if (node->is_hidden) {
3151 char *path = get_path(f, node->nodeid);
3152 if (path) {
3153 fuse_fs_unlink(f->fs, path);
3154 free(path);
3155 }
3156 }
3157 }
3158 }
3159 }
3160 for (i = 0; i < f->id_table_size; i++) {
3161 struct node *node;
3162 struct node *next;
3163
3164 for (node = f->id_table[i]; node != NULL; node = next) {
3165 next = node->id_next;
3166 free_node(node);
3167 }
3168 }
3169 free(f->id_table);
3170 free(f->name_table);
3171 pthread_mutex_destroy(&f->lock);
3172 pthread_rwlock_destroy(&f->tree_lock);
3173 fuse_session_destroy(f->se);
3174#ifdef __SOLARIS__
3175 free(f->conf.modules);
3176#endif /* __SOLARIS__ */
3177 free(f);
3178 fuse_delete_context_key();
3179}
3180