Allow IPv6 address entry in tools>ping - Loosens valid character check
[tomato/davidwu.git] / release / src / router / ntfs-3g / libfuse-lite / fuse.c
blobd55c9df5fde0dd875fd41030d14f45c2170efb2f
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU LGPLv2.
6 See the file COPYING.LIB
7 */
9 #ifdef __SOLARIS__
10 /* For pthread_rwlock_t */
11 #define _GNU_SOURCE
12 #endif /* __SOLARIS__ */
14 #include "config.h"
15 #include "fuse_i.h"
16 #include "fuse_lowlevel.h"
17 #include "fuse_opt.h"
18 #include "fuse_misc.h"
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>
36 #ifdef __SOLARIS__
37 #define FUSE_MAX_PATH 4096
38 #endif /* __SOLARIS__ */
40 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
42 #define FUSE_UNKNOWN_INO 0xffffffff
43 #define OFFSET_MAX 0x7fffffffffffffffLL
45 struct 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__ */
72 struct fuse_fs {
73 struct fuse_operations op;
74 void *user_data;
75 #ifdef __SOLARIS__
76 struct fuse_module *m;
77 #endif /* __SOLARIS__ */
80 #ifdef __SOLARIS__
81 struct fusemod_so {
82 void *handle;
83 int ctr;
85 #endif /* __SOLARIS__ */
87 struct 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 int utime_omit_ok;
104 struct lock {
105 int type;
106 off_t start;
107 off_t end;
108 pid_t pid;
109 uint64_t owner;
110 struct lock *next;
113 struct 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 int is_hidden;
124 #ifdef __SOLARIS__
125 struct timespec stat_updated;
126 struct timespec mtime;
127 off_t size;
128 int cache_valid;
129 #endif /* __SOLARIS__ */
130 struct lock *locks;
133 struct 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;
148 struct fuse_context_i {
149 struct fuse_context ctx;
150 fuse_req_t req;
153 static pthread_key_t fuse_context_key;
154 static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
155 static int fuse_context_ref;
157 #ifdef __SOLARIS__
159 static struct fusemod_so *fuse_current_so;
160 static struct fuse_module *fuse_modules;
162 static int fuse_load_so_name(const char *soname)
164 struct fusemod_so *so;
166 so = calloc(1, sizeof(struct fusemod_so));
167 if (!so) {
168 fprintf(stderr, "fuse: memory allocation failed\n");
169 return -1;
172 fuse_current_so = so;
173 so->handle = dlopen(soname, RTLD_NOW);
174 fuse_current_so = NULL;
175 if (!so->handle) {
176 fprintf(stderr, "fuse: %s\n", dlerror());
177 goto err;
179 if (!so->ctr) {
180 fprintf(stderr, "fuse: %s did not register any modules", soname);
181 goto err;
183 return 0;
185 err:
186 if (so->handle)
187 dlclose(so->handle);
188 free(so);
189 return -1;
192 static int fuse_load_so_module(const char *module)
194 int res;
195 char *soname = malloc(strlen(module) + 64);
196 if (!soname) {
197 fprintf(stderr, "fuse: memory allocation failed\n");
198 return -1;
200 sprintf(soname, "libfusemod_%s.so", module);
201 res = fuse_load_so_name(soname);
202 free(soname);
203 return res;
206 static struct fuse_module *fuse_find_module(const char *module)
208 struct fuse_module *m;
209 for (m = fuse_modules; m; m = m->next) {
210 if (strcmp(module, m->name) == 0) {
211 m->ctr++;
212 break;
215 return m;
218 static struct fuse_module *fuse_get_module(const char *module)
220 struct fuse_module *m;
222 pthread_mutex_lock(&fuse_context_lock);
223 m = fuse_find_module(module);
224 if (!m) {
225 int err = fuse_load_so_module(module);
226 if (!err)
227 m = fuse_find_module(module);
229 pthread_mutex_unlock(&fuse_context_lock);
230 return m;
233 static void fuse_put_module(struct fuse_module *m)
235 pthread_mutex_lock(&fuse_context_lock);
236 assert(m->ctr > 0);
237 m->ctr--;
238 if (!m->ctr && m->so) {
239 struct fusemod_so *so = m->so;
240 assert(so->ctr > 0);
241 so->ctr--;
242 if (!so->ctr) {
243 struct fuse_module **mp;
244 for (mp = &fuse_modules; *mp;) {
245 if ((*mp)->so == so)
246 *mp = (*mp)->next;
247 else
248 mp = &(*mp)->next;
250 dlclose(so->handle);
251 free(so);
254 pthread_mutex_unlock(&fuse_context_lock);
256 #endif /* __SOLARIS__ */
258 static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
260 size_t hash = nodeid % f->id_table_size;
261 struct node *node;
263 for (node = f->id_table[hash]; node != NULL; node = node->id_next)
264 if (node->nodeid == nodeid)
265 return node;
267 return NULL;
270 static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
272 struct node *node = get_node_nocheck(f, nodeid);
273 if (!node) {
274 fprintf(stderr, "fuse internal error: node %llu not found\n",
275 (unsigned long long) nodeid);
276 abort();
278 return node;
281 static void free_node(struct node *node)
283 free(node->name);
284 free(node);
287 static void unhash_id(struct fuse *f, struct node *node)
289 size_t hash = node->nodeid % f->id_table_size;
290 struct node **nodep = &f->id_table[hash];
292 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
293 if (*nodep == node) {
294 *nodep = node->id_next;
295 return;
299 static void hash_id(struct fuse *f, struct node *node)
301 size_t hash = node->nodeid % f->id_table_size;
302 node->id_next = f->id_table[hash];
303 f->id_table[hash] = node;
306 static unsigned int name_hash(struct fuse *f, fuse_ino_t parent,
307 const char *name)
309 unsigned int hash = *name;
311 if (hash)
312 for (name += 1; *name != '\0'; name++)
313 hash = (hash << 5) - hash + *name;
315 return (hash + parent) % f->name_table_size;
318 static void unref_node(struct fuse *f, struct node *node);
320 static void unhash_name(struct fuse *f, struct node *node)
322 if (node->name) {
323 size_t hash = name_hash(f, node->parent->nodeid, node->name);
324 struct node **nodep = &f->name_table[hash];
326 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
327 if (*nodep == node) {
328 *nodep = node->name_next;
329 node->name_next = NULL;
330 unref_node(f, node->parent);
331 free(node->name);
332 node->name = NULL;
333 node->parent = NULL;
334 return;
336 fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n",
337 (unsigned long long) node->nodeid);
338 abort();
342 static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
343 const char *name)
345 size_t hash = name_hash(f, parentid, name);
346 struct node *parent = get_node(f, parentid);
347 node->name = strdup(name);
348 if (node->name == NULL)
349 return -1;
351 parent->refctr ++;
352 node->parent = parent;
353 node->name_next = f->name_table[hash];
354 f->name_table[hash] = node;
355 return 0;
358 static void delete_node(struct fuse *f, struct node *node)
360 if (f->conf.debug)
361 fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid);
363 assert(!node->name);
364 unhash_id(f, node);
365 free_node(node);
368 static void unref_node(struct fuse *f, struct node *node)
370 assert(node->refctr > 0);
371 node->refctr --;
372 if (!node->refctr)
373 delete_node(f, node);
376 static fuse_ino_t next_id(struct fuse *f)
378 do {
379 f->ctr = (f->ctr + 1) & 0xffffffff;
380 if (!f->ctr)
381 f->generation ++;
382 } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
383 get_node_nocheck(f, f->ctr) != NULL);
384 return f->ctr;
387 static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
388 const char *name)
390 size_t hash = name_hash(f, parent, name);
391 struct node *node;
393 for (node = f->name_table[hash]; node != NULL; node = node->name_next)
394 if (node->parent->nodeid == parent && strcmp(node->name, name) == 0)
395 return node;
397 return NULL;
400 static struct node *find_node(struct fuse *f, fuse_ino_t parent,
401 const char *name)
403 struct node *node;
405 pthread_mutex_lock(&f->lock);
406 node = lookup_node(f, parent, name);
407 if (node == NULL) {
408 node = (struct node *) calloc(1, sizeof(struct node));
409 if (node == NULL)
410 goto out_err;
412 node->refctr = 1;
413 node->nodeid = next_id(f);
414 node->open_count = 0;
415 node->is_hidden = 0;
416 node->generation = f->generation;
417 if (hash_name(f, node, parent, name) == -1) {
418 free(node);
419 node = NULL;
420 goto out_err;
422 hash_id(f, node);
424 node->nlookup ++;
425 out_err:
426 pthread_mutex_unlock(&f->lock);
427 return node;
430 #ifndef __SOLARIS__
431 static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
432 #else /* __SOLARIS__ */
433 static char *add_name(char *buf, char *s, const char *name)
434 #endif /* __SOLARIS__ */
436 size_t len = strlen(name);
438 #ifndef __SOLARIS__
439 if (s - len <= *buf) {
440 unsigned pathlen = *bufsize - (s - *buf);
441 unsigned newbufsize = *bufsize;
442 char *newbuf;
444 while (newbufsize < pathlen + len + 1) {
445 if (newbufsize >= 0x80000000)
446 newbufsize = 0xffffffff;
447 else
448 newbufsize *= 2;
451 newbuf = realloc(*buf, newbufsize);
452 if (newbuf == NULL)
453 return NULL;
455 *buf = newbuf;
456 s = newbuf + newbufsize - pathlen;
457 memmove(s, newbuf + *bufsize - pathlen, pathlen);
458 *bufsize = newbufsize;
460 s -= len;
461 #else /* ! __SOLARIS__ */
462 s -= len;
463 if (s <= buf) {
464 fprintf(stderr, "fuse: path too long: ...%s\n", s + len);
465 return NULL;
467 #endif /* __SOLARIS__ */
468 strncpy(s, name, len);
469 s--;
470 *s = '/';
472 return s;
475 static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
477 #ifdef __SOLARIS__
478 char buf[FUSE_MAX_PATH];
479 char *s = buf + FUSE_MAX_PATH - 1;
480 struct node *node;
482 *s = '\0';
484 if (name != NULL) {
485 s = add_name(buf, s, name);
486 if (s == NULL)
487 return NULL;
490 pthread_mutex_lock(&f->lock);
491 for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
492 node = node->parent) {
493 if (node->name == NULL) {
494 s = NULL;
495 break;
498 s = add_name(buf, s, node->name);
499 if (s == NULL)
500 break;
502 pthread_mutex_unlock(&f->lock);
504 if (node == NULL || s == NULL)
505 return NULL;
506 else if (*s == '\0')
507 return strdup("/");
508 else
509 return strdup(s);
511 #else /* __SOLARIS__ */
513 unsigned bufsize = 256;
514 char *buf;
515 char *s;
516 struct node *node;
518 buf = malloc(bufsize);
519 if (buf == NULL)
520 return NULL;
522 s = buf + bufsize - 1;
523 *s = '\0';
525 if (name != NULL) {
526 s = add_name(&buf, &bufsize, s, name);
527 if (s == NULL)
528 goto out_free;
531 pthread_mutex_lock(&f->lock);
532 for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
533 node = node->parent) {
534 if (node->name == NULL) {
535 s = NULL;
536 break;
539 s = add_name(&buf, &bufsize, s, node->name);
540 if (s == NULL)
541 break;
543 pthread_mutex_unlock(&f->lock);
545 if (node == NULL || s == NULL)
546 goto out_free;
548 if (s[0])
549 memmove(buf, s, bufsize - (s - buf));
550 else
551 strcpy(buf, "/");
552 return buf;
554 out_free:
555 free(buf);
556 return NULL;
557 #endif /* __SOLARIS__ */
560 static char *get_path(struct fuse *f, fuse_ino_t nodeid)
562 return get_path_name(f, nodeid, NULL);
565 static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
567 struct node *node;
568 if (nodeid == FUSE_ROOT_ID)
569 return;
570 pthread_mutex_lock(&f->lock);
571 node = get_node(f, nodeid);
572 assert(node->nlookup >= nlookup);
573 node->nlookup -= nlookup;
574 if (!node->nlookup) {
575 unhash_name(f, node);
576 unref_node(f, node);
578 pthread_mutex_unlock(&f->lock);
581 static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
583 struct node *node;
585 pthread_mutex_lock(&f->lock);
586 node = lookup_node(f, dir, name);
587 if (node != NULL)
588 unhash_name(f, node);
589 pthread_mutex_unlock(&f->lock);
592 static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
593 fuse_ino_t newdir, const char *newname, int hide)
595 struct node *node;
596 struct node *newnode;
597 int err = 0;
599 pthread_mutex_lock(&f->lock);
600 node = lookup_node(f, olddir, oldname);
601 newnode = lookup_node(f, newdir, newname);
602 if (node == NULL)
603 goto out;
605 if (newnode != NULL) {
606 if (hide) {
607 fprintf(stderr, "fuse: hidden file got created during hiding\n");
608 err = -EBUSY;
609 goto out;
611 unhash_name(f, newnode);
614 unhash_name(f, node);
615 if (hash_name(f, node, newdir, newname) == -1) {
616 err = -ENOMEM;
617 goto out;
620 if (hide)
621 node->is_hidden = 1;
623 out:
624 pthread_mutex_unlock(&f->lock);
625 return err;
628 static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
630 if (!f->conf.use_ino)
631 stbuf->st_ino = nodeid;
632 if (f->conf.set_mode)
633 stbuf->st_mode = (stbuf->st_mode & S_IFMT) | (0777 & ~f->conf.umask);
634 if (f->conf.set_uid)
635 stbuf->st_uid = f->conf.uid;
636 if (f->conf.set_gid)
637 stbuf->st_gid = f->conf.gid;
640 static struct fuse *req_fuse(fuse_req_t req)
642 return (struct fuse *) fuse_req_userdata(req);
645 static void fuse_intr_sighandler(int sig)
647 (void) sig;
648 /* Nothing to do */
651 struct fuse_intr_data {
652 pthread_t id;
653 pthread_cond_t cond;
654 int finished;
657 static void fuse_interrupt(fuse_req_t req, void *d_)
659 struct fuse_intr_data *d = d_;
660 struct fuse *f = req_fuse(req);
662 if (d->id == pthread_self())
663 return;
665 pthread_mutex_lock(&f->lock);
666 while (!d->finished) {
667 struct timeval now;
668 struct timespec timeout;
670 pthread_kill(d->id, f->conf.intr_signal);
671 gettimeofday(&now, NULL);
672 timeout.tv_sec = now.tv_sec + 1;
673 timeout.tv_nsec = now.tv_usec * 1000;
674 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
676 pthread_mutex_unlock(&f->lock);
679 static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
680 struct fuse_intr_data *d)
682 pthread_mutex_lock(&f->lock);
683 d->finished = 1;
684 pthread_cond_broadcast(&d->cond);
685 pthread_mutex_unlock(&f->lock);
686 fuse_req_interrupt_func(req, NULL, NULL);
687 pthread_cond_destroy(&d->cond);
690 static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
692 d->id = pthread_self();
693 pthread_cond_init(&d->cond, NULL);
694 d->finished = 0;
695 fuse_req_interrupt_func(req, fuse_interrupt, d);
698 static void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
699 struct fuse_intr_data *d)
701 if (f->conf.intr)
702 fuse_do_finish_interrupt(f, req, d);
705 static void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
706 struct fuse_intr_data *d)
708 if (f->conf.intr)
709 fuse_do_prepare_interrupt(req, d);
712 int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
714 fuse_get_context()->private_data = fs->user_data;
715 if (fs->op.getattr)
716 return fs->op.getattr(path, buf);
717 else
718 return -ENOSYS;
721 int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
722 struct fuse_file_info *fi)
724 fuse_get_context()->private_data = fs->user_data;
725 if (fs->op.fgetattr)
726 return fs->op.fgetattr(path, buf, fi);
727 else if (fs->op.getattr)
728 return fs->op.getattr(path, buf);
729 else
730 return -ENOSYS;
733 int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
734 const char *newpath)
736 fuse_get_context()->private_data = fs->user_data;
737 if (fs->op.rename)
738 return fs->op.rename(oldpath, newpath);
739 else
740 return -ENOSYS;
743 int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
745 fuse_get_context()->private_data = fs->user_data;
746 if (fs->op.unlink)
747 return fs->op.unlink(path);
748 else
749 return -ENOSYS;
752 int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
754 fuse_get_context()->private_data = fs->user_data;
755 if (fs->op.rmdir)
756 return fs->op.rmdir(path);
757 else
758 return -ENOSYS;
761 int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
763 fuse_get_context()->private_data = fs->user_data;
764 if (fs->op.symlink)
765 return fs->op.symlink(linkname, path);
766 else
767 return -ENOSYS;
770 int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
772 fuse_get_context()->private_data = fs->user_data;
773 if (fs->op.link)
774 return fs->op.link(oldpath, newpath);
775 else
776 return -ENOSYS;
779 int fuse_fs_release(struct fuse_fs *fs, const char *path,
780 struct fuse_file_info *fi)
782 fuse_get_context()->private_data = fs->user_data;
783 if (fs->op.release)
784 return fs->op.release(path, fi);
785 else
786 return 0;
789 int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
790 struct fuse_file_info *fi)
792 fuse_get_context()->private_data = fs->user_data;
793 if (fs->op.opendir)
794 return fs->op.opendir(path, fi);
795 else
796 return 0;
799 int fuse_fs_open(struct fuse_fs *fs, const char *path,
800 struct fuse_file_info *fi)
802 fuse_get_context()->private_data = fs->user_data;
803 if (fs->op.open)
804 return fs->op.open(path, fi);
805 else
806 return 0;
809 int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
810 off_t off, struct fuse_file_info *fi)
812 fuse_get_context()->private_data = fs->user_data;
813 if (fs->op.read)
814 return fs->op.read(path, buf, size, off, fi);
815 else
816 return -ENOSYS;
819 int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf,
820 size_t size, off_t off, struct fuse_file_info *fi)
822 fuse_get_context()->private_data = fs->user_data;
823 if (fs->op.write)
824 return fs->op.write(path, buf, size, off, fi);
825 else
826 return -ENOSYS;
829 int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
830 struct fuse_file_info *fi)
832 fuse_get_context()->private_data = fs->user_data;
833 if (fs->op.fsync)
834 return fs->op.fsync(path, datasync, fi);
835 else
836 return -ENOSYS;
839 int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
840 struct fuse_file_info *fi)
842 fuse_get_context()->private_data = fs->user_data;
843 if (fs->op.fsyncdir)
844 return fs->op.fsyncdir(path, datasync, fi);
845 else
846 return -ENOSYS;
849 int fuse_fs_flush(struct fuse_fs *fs, const char *path,
850 struct fuse_file_info *fi)
852 fuse_get_context()->private_data = fs->user_data;
853 if (fs->op.flush)
854 return fs->op.flush(path, fi);
855 else
856 return -ENOSYS;
859 int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
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;
871 int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
872 struct fuse_file_info *fi)
874 fuse_get_context()->private_data = fs->user_data;
875 if (fs->op.releasedir)
876 return fs->op.releasedir(path, fi);
877 else
878 return 0;
881 int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
882 fuse_fill_dir_t filler, off_t off,
883 struct fuse_file_info *fi)
885 fuse_get_context()->private_data = fs->user_data;
886 if (fs->op.readdir)
887 return fs->op.readdir(path, buf, filler, off, fi);
888 else
889 return -ENOSYS;
892 int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
893 struct fuse_file_info *fi)
895 fuse_get_context()->private_data = fs->user_data;
896 if (fs->op.create)
897 return fs->op.create(path, mode, fi);
898 else
899 return -ENOSYS;
902 int fuse_fs_lock(struct fuse_fs *fs, const char *path,
903 struct fuse_file_info *fi, int cmd, struct flock *lock)
905 fuse_get_context()->private_data = fs->user_data;
906 if (fs->op.lock)
907 return fs->op.lock(path, fi, cmd, lock);
908 else
909 return -ENOSYS;
912 int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
914 fuse_get_context()->private_data = fs->user_data;
915 if (fs->op.chown)
916 return fs->op.chown(path, uid, gid);
917 else
918 return -ENOSYS;
921 int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
923 fuse_get_context()->private_data = fs->user_data;
924 if (fs->op.truncate)
925 return fs->op.truncate(path, size);
926 else
927 return -ENOSYS;
930 int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
931 struct fuse_file_info *fi)
933 fuse_get_context()->private_data = fs->user_data;
934 if (fs->op.ftruncate)
935 return fs->op.ftruncate(path, size, fi);
936 else if (fs->op.truncate)
937 return fs->op.truncate(path, size);
938 else
939 return -ENOSYS;
942 int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
943 const struct timespec tv[2])
945 fuse_get_context()->private_data = fs->user_data;
946 if (fs->op.utimens)
947 return fs->op.utimens(path, tv);
948 else if(fs->op.utime) {
949 struct utimbuf buf;
950 buf.actime = tv[0].tv_sec;
951 buf.modtime = tv[1].tv_sec;
952 return fs->op.utime(path, &buf);
953 } else
954 return -ENOSYS;
957 int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
959 fuse_get_context()->private_data = fs->user_data;
960 if (fs->op.access)
961 return fs->op.access(path, mask);
962 else
963 return -ENOSYS;
966 int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
967 size_t len)
969 fuse_get_context()->private_data = fs->user_data;
970 if (fs->op.readlink)
971 return fs->op.readlink(path, buf, len);
972 else
973 return -ENOSYS;
976 int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
977 dev_t rdev)
979 fuse_get_context()->private_data = fs->user_data;
980 if (fs->op.mknod)
981 return fs->op.mknod(path, mode, rdev);
982 else
983 return -ENOSYS;
986 int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
988 fuse_get_context()->private_data = fs->user_data;
989 if (fs->op.mkdir)
990 return fs->op.mkdir(path, mode);
991 else
992 return -ENOSYS;
995 int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
996 const char *value, size_t size, int flags)
998 fuse_get_context()->private_data = fs->user_data;
999 if (fs->op.setxattr)
1000 return fs->op.setxattr(path, name, value, size, flags);
1001 else
1002 return -ENOSYS;
1005 int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
1006 char *value, size_t size)
1008 fuse_get_context()->private_data = fs->user_data;
1009 if (fs->op.getxattr)
1010 return fs->op.getxattr(path, name, value, size);
1011 else
1012 return -ENOSYS;
1015 int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
1016 size_t size)
1018 fuse_get_context()->private_data = fs->user_data;
1019 if (fs->op.listxattr)
1020 return fs->op.listxattr(path, list, size);
1021 else
1022 return -ENOSYS;
1025 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
1026 uint64_t *idx)
1028 fuse_get_context()->private_data = fs->user_data;
1029 if (fs->op.bmap)
1030 return fs->op.bmap(path, blocksize, idx);
1031 else
1032 return -ENOSYS;
1035 int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
1037 fuse_get_context()->private_data = fs->user_data;
1038 if (fs->op.removexattr)
1039 return fs->op.removexattr(path, name);
1040 else
1041 return -ENOSYS;
1044 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
1046 struct node *node;
1047 int isopen = 0;
1048 pthread_mutex_lock(&f->lock);
1049 node = lookup_node(f, dir, name);
1050 if (node && node->open_count > 0)
1051 isopen = 1;
1052 pthread_mutex_unlock(&f->lock);
1053 return isopen;
1056 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
1057 char *newname, size_t bufsize)
1059 struct stat buf;
1060 struct node *node;
1061 struct node *newnode;
1062 char *newpath;
1063 int res;
1064 int failctr = 10;
1066 do {
1067 pthread_mutex_lock(&f->lock);
1068 node = lookup_node(f, dir, oldname);
1069 if (node == NULL) {
1070 pthread_mutex_unlock(&f->lock);
1071 return NULL;
1073 do {
1074 f->hidectr ++;
1075 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
1076 (unsigned int) node->nodeid, f->hidectr);
1077 newnode = lookup_node(f, dir, newname);
1078 } while(newnode);
1079 pthread_mutex_unlock(&f->lock);
1081 newpath = get_path_name(f, dir, newname);
1082 if (!newpath)
1083 break;
1085 res = fuse_fs_getattr(f->fs, newpath, &buf);
1086 if (res == -ENOENT)
1087 break;
1088 free(newpath);
1089 newpath = NULL;
1090 } while(res == 0 && --failctr);
1092 return newpath;
1095 static int hide_node(struct fuse *f, const char *oldpath,
1096 fuse_ino_t dir, const char *oldname)
1098 char newname[64];
1099 char *newpath;
1100 int err = -EBUSY;
1102 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
1103 if (newpath) {
1104 err = fuse_fs_rename(f->fs, oldpath, newpath);
1105 if (!err)
1106 err = rename_node(f, dir, oldname, dir, newname, 1);
1107 free(newpath);
1109 return err;
1112 #ifdef __SOLARIS__
1114 static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
1116 return stbuf->st_mtime == ts->tv_sec && ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
1119 #ifndef CLOCK_MONOTONIC
1120 #define CLOCK_MONOTONIC CLOCK_REALTIME
1121 #endif
1123 static void curr_time(struct timespec *now)
1125 static clockid_t clockid = CLOCK_MONOTONIC;
1126 int res = clock_gettime(clockid, now);
1127 if (res == -1 && errno == EINVAL) {
1128 clockid = CLOCK_REALTIME;
1129 res = clock_gettime(clockid, now);
1131 if (res == -1) {
1132 perror("fuse: clock_gettime");
1133 abort();
1137 static void update_stat(struct node *node, const struct stat *stbuf)
1139 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
1140 stbuf->st_size != node->size))
1141 node->cache_valid = 0;
1142 node->mtime.tv_sec = stbuf->st_mtime;
1143 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
1144 node->size = stbuf->st_size;
1145 curr_time(&node->stat_updated);
1148 #endif /* __SOLARIS__ */
1150 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
1151 const char *name, const char *path,
1152 struct fuse_entry_param *e, struct fuse_file_info *fi)
1154 int res;
1156 memset(e, 0, sizeof(struct fuse_entry_param));
1157 if (fi)
1158 res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
1159 else
1160 res = fuse_fs_getattr(f->fs, path, &e->attr);
1161 if (res == 0) {
1162 struct node *node;
1164 node = find_node(f, nodeid, name);
1165 if (node == NULL)
1166 res = -ENOMEM;
1167 else {
1168 e->ino = node->nodeid;
1169 e->generation = node->generation;
1170 e->entry_timeout = f->conf.entry_timeout;
1171 e->attr_timeout = f->conf.attr_timeout;
1172 #ifdef __SOLARIS__
1173 if (f->conf.auto_cache) {
1174 pthread_mutex_lock(&f->lock);
1175 update_stat(node, &e->attr);
1176 pthread_mutex_unlock(&f->lock);
1178 #endif /* __SOLARIS__ */
1179 set_stat(f, e->ino, &e->attr);
1180 if (f->conf.debug)
1181 fprintf(stderr, " NODEID: %lu\n", (unsigned long) e->ino);
1184 return res;
1187 static struct fuse_context_i *fuse_get_context_internal(void)
1189 struct fuse_context_i *c;
1191 c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
1192 if (c == NULL) {
1193 c = (struct fuse_context_i *) malloc(sizeof(struct fuse_context_i));
1194 if (c == NULL) {
1195 /* This is hard to deal with properly, so just abort. If
1196 memory is so low that the context cannot be allocated,
1197 there's not much hope for the filesystem anyway */
1198 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
1199 abort();
1201 pthread_setspecific(fuse_context_key, c);
1203 return c;
1206 static void fuse_freecontext(void *data)
1208 free(data);
1211 static int fuse_create_context_key(void)
1213 int err = 0;
1214 pthread_mutex_lock(&fuse_context_lock);
1215 if (!fuse_context_ref) {
1216 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
1217 if (err) {
1218 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
1219 strerror(err));
1220 pthread_mutex_unlock(&fuse_context_lock);
1221 return -1;
1224 fuse_context_ref++;
1225 pthread_mutex_unlock(&fuse_context_lock);
1226 return 0;
1229 static void fuse_delete_context_key(void)
1231 pthread_mutex_lock(&fuse_context_lock);
1232 fuse_context_ref--;
1233 if (!fuse_context_ref) {
1234 free(pthread_getspecific(fuse_context_key));
1235 pthread_key_delete(fuse_context_key);
1237 pthread_mutex_unlock(&fuse_context_lock);
1240 static struct fuse *req_fuse_prepare(fuse_req_t req)
1242 struct fuse_context_i *c = fuse_get_context_internal();
1243 const struct fuse_ctx *ctx = fuse_req_ctx(req);
1244 c->req = req;
1245 c->ctx.fuse = req_fuse(req);
1246 c->ctx.uid = ctx->uid;
1247 c->ctx.gid = ctx->gid;
1248 c->ctx.pid = ctx->pid;
1249 #ifdef POSIXACLS
1250 c->ctx.umask = ctx->umask;
1251 #endif
1252 return c->ctx.fuse;
1255 #ifndef __SOLARIS__
1256 static void reply_err(fuse_req_t req, int err)
1257 #else /* __SOLARIS__ */
1258 static inline void reply_err(fuse_req_t req, int err)
1259 #endif /* __SOLARIS__ */
1261 /* fuse_reply_err() uses non-negated errno values */
1262 fuse_reply_err(req, -err);
1265 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
1266 int err)
1268 if (!err) {
1269 struct fuse *f = req_fuse(req);
1270 if (fuse_reply_entry(req, e) == -ENOENT)
1271 forget_node(f, e->ino, 1);
1272 } else
1273 reply_err(req, err);
1276 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
1278 fuse_get_context()->private_data = fs->user_data;
1279 if (fs->op.init)
1280 fs->user_data = fs->op.init(conn);
1283 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
1285 struct fuse *f = (struct fuse *) data;
1286 struct fuse_context_i *c = fuse_get_context_internal();
1288 memset(c, 0, sizeof(*c));
1289 c->ctx.fuse = f;
1290 fuse_fs_init(f->fs, conn);
1293 void fuse_fs_destroy(struct fuse_fs *fs)
1295 fuse_get_context()->private_data = fs->user_data;
1296 if (fs->op.destroy)
1297 fs->op.destroy(fs->user_data);
1298 #ifdef __SOLARIS__
1299 if (fs->m)
1300 fuse_put_module(fs->m);
1301 #endif /* __SOLARIS__ */
1302 free(fs);
1305 static void fuse_lib_destroy(void *data)
1307 struct fuse *f = (struct fuse *) data;
1308 struct fuse_context_i *c = fuse_get_context_internal();
1310 memset(c, 0, sizeof(*c));
1311 c->ctx.fuse = f;
1312 fuse_fs_destroy(f->fs);
1313 f->fs = NULL;
1316 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
1317 const char *name)
1319 struct fuse *f = req_fuse_prepare(req);
1320 struct fuse_entry_param e;
1321 char *path;
1322 int err;
1324 err = -ENOENT;
1325 pthread_rwlock_rdlock(&f->tree_lock);
1326 path = get_path_name(f, parent, name);
1327 if (path != NULL) {
1328 struct fuse_intr_data d;
1329 if (f->conf.debug)
1330 fprintf(stderr, "LOOKUP %s\n", path);
1331 fuse_prepare_interrupt(f, req, &d);
1332 err = lookup_path(f, parent, name, path, &e, NULL);
1333 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
1334 e.ino = 0;
1335 e.entry_timeout = f->conf.negative_timeout;
1336 err = 0;
1338 fuse_finish_interrupt(f, req, &d);
1339 free(path);
1341 pthread_rwlock_unlock(&f->tree_lock);
1342 reply_entry(req, &e, err);
1345 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
1346 unsigned long nlookup)
1348 struct fuse *f = req_fuse(req);
1349 if (f->conf.debug)
1350 fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino, nlookup);
1351 forget_node(f, ino, nlookup);
1352 fuse_reply_none(req);
1355 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
1356 struct fuse_file_info *fi)
1358 struct fuse *f = req_fuse_prepare(req);
1359 struct stat buf;
1360 char *path;
1361 int err;
1363 (void) fi;
1364 memset(&buf, 0, sizeof(buf));
1366 err = -ENOENT;
1367 pthread_rwlock_rdlock(&f->tree_lock);
1368 path = get_path(f, ino);
1369 if (path != NULL) {
1370 struct fuse_intr_data d;
1371 fuse_prepare_interrupt(f, req, &d);
1372 err = fuse_fs_getattr(f->fs, path, &buf);
1373 fuse_finish_interrupt(f, req, &d);
1374 free(path);
1376 pthread_rwlock_unlock(&f->tree_lock);
1377 if (!err) {
1378 #ifdef __SOLARIS__
1379 if (f->conf.auto_cache) {
1380 pthread_mutex_lock(&f->lock);
1381 update_stat(get_node(f, ino), &buf);
1382 pthread_mutex_unlock(&f->lock);
1384 #endif /* __SOLARIS__ */
1385 set_stat(f, ino, &buf);
1386 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
1387 } else
1388 reply_err(req, err);
1391 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
1393 fuse_get_context()->private_data = fs->user_data;
1394 if (fs->op.chmod)
1395 return fs->op.chmod(path, mode);
1396 else
1397 return -ENOSYS;
1400 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
1401 int valid, struct fuse_file_info *fi)
1403 struct fuse *f = req_fuse_prepare(req);
1404 struct stat buf;
1405 char *path;
1406 int err;
1408 err = -ENOENT;
1409 pthread_rwlock_rdlock(&f->tree_lock);
1410 path = get_path(f, ino);
1411 if (path != NULL) {
1412 struct fuse_intr_data d;
1413 fuse_prepare_interrupt(f, req, &d);
1414 err = 0;
1415 if (!err && (valid & FUSE_SET_ATTR_MODE))
1416 err = fuse_fs_chmod(f->fs, path, attr->st_mode);
1417 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
1418 uid_t uid =
1419 (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1;
1420 gid_t gid =
1421 (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1;
1422 err = fuse_fs_chown(f->fs, path, uid, gid);
1424 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
1425 if (fi)
1426 err = fuse_fs_ftruncate(f->fs, path, attr->st_size, fi);
1427 else
1428 err = fuse_fs_truncate(f->fs, path, attr->st_size);
1430 #ifdef HAVE_UTIMENSAT
1431 if (!err && f->utime_omit_ok &&
1432 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
1433 struct timespec tv[2];
1435 tv[0].tv_sec = 0;
1436 tv[1].tv_sec = 0;
1437 tv[0].tv_nsec = UTIME_OMIT;
1438 tv[1].tv_nsec = UTIME_OMIT;
1440 if (valid & FUSE_SET_ATTR_ATIME_NOW)
1441 tv[0].tv_nsec = UTIME_NOW;
1442 else if (valid & FUSE_SET_ATTR_ATIME)
1443 tv[0] = attr->st_atim;
1445 if (valid & FUSE_SET_ATTR_MTIME_NOW)
1446 tv[1].tv_nsec = UTIME_NOW;
1447 else if (valid & FUSE_SET_ATTR_MTIME)
1448 tv[1] = attr->st_mtim;
1450 err = fuse_fs_utimens(f->fs, path, tv);
1451 } else
1452 #endif
1453 if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
1454 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
1455 struct timespec tv[2];
1456 tv[0].tv_sec = attr->st_atime;
1457 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
1458 tv[1].tv_sec = attr->st_mtime;
1459 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
1460 err = fuse_fs_utimens(f->fs, path, tv);
1462 if (!err)
1463 err = fuse_fs_getattr(f->fs, path, &buf);
1464 fuse_finish_interrupt(f, req, &d);
1465 free(path);
1467 pthread_rwlock_unlock(&f->tree_lock);
1468 if (!err) {
1469 #ifdef __SOLARIS__
1470 if (f->conf.auto_cache) {
1471 pthread_mutex_lock(&f->lock);
1472 update_stat(get_node(f, ino), &buf);
1473 pthread_mutex_unlock(&f->lock);
1475 #endif /* __SOLARIS__ */
1476 set_stat(f, ino, &buf);
1477 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
1478 } else
1479 reply_err(req, err);
1482 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
1484 struct fuse *f = req_fuse_prepare(req);
1485 char *path;
1486 int err;
1488 err = -ENOENT;
1489 pthread_rwlock_rdlock(&f->tree_lock);
1490 path = get_path(f, ino);
1491 if (path != NULL) {
1492 struct fuse_intr_data d;
1493 if (f->conf.debug)
1494 fprintf(stderr, "ACCESS %s 0%o\n", path, mask);
1495 fuse_prepare_interrupt(f, req, &d);
1496 err = fuse_fs_access(f->fs, path, mask);
1497 fuse_finish_interrupt(f, req, &d);
1498 free(path);
1500 pthread_rwlock_unlock(&f->tree_lock);
1501 reply_err(req, err);
1504 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
1506 struct fuse *f = req_fuse_prepare(req);
1507 char linkname[PATH_MAX + 1];
1508 char *path;
1509 int err;
1511 err = -ENOENT;
1512 pthread_rwlock_rdlock(&f->tree_lock);
1513 path = get_path(f, ino);
1514 if (path != NULL) {
1515 struct fuse_intr_data d;
1516 fuse_prepare_interrupt(f, req, &d);
1517 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
1518 fuse_finish_interrupt(f, req, &d);
1519 free(path);
1521 pthread_rwlock_unlock(&f->tree_lock);
1522 if (!err) {
1523 linkname[PATH_MAX] = '\0';
1524 fuse_reply_readlink(req, linkname);
1525 } else
1526 reply_err(req, err);
1529 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
1530 mode_t mode, dev_t rdev)
1532 struct fuse *f = req_fuse_prepare(req);
1533 struct fuse_entry_param e;
1534 char *path;
1535 int err;
1537 err = -ENOENT;
1538 pthread_rwlock_rdlock(&f->tree_lock);
1539 path = get_path_name(f, parent, name);
1540 if (path) {
1541 struct fuse_intr_data d;
1542 if (f->conf.debug)
1543 fprintf(stderr, "MKNOD %s\n", path);
1544 fuse_prepare_interrupt(f, req, &d);
1545 err = -ENOSYS;
1546 if (S_ISREG(mode)) {
1547 struct fuse_file_info fi;
1549 memset(&fi, 0, sizeof(fi));
1550 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
1551 err = fuse_fs_create(f->fs, path, mode, &fi);
1552 if (!err) {
1553 err = lookup_path(f, parent, name, path, &e, &fi);
1554 fuse_fs_release(f->fs, path, &fi);
1557 if (err == -ENOSYS) {
1558 err = fuse_fs_mknod(f->fs, path, mode, rdev);
1559 if (!err)
1560 err = lookup_path(f, parent, name, path, &e, NULL);
1562 fuse_finish_interrupt(f, req, &d);
1563 free(path);
1565 pthread_rwlock_unlock(&f->tree_lock);
1566 reply_entry(req, &e, err);
1569 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
1570 mode_t mode)
1572 struct fuse *f = req_fuse_prepare(req);
1573 struct fuse_entry_param e;
1574 char *path;
1575 int err;
1577 err = -ENOENT;
1578 pthread_rwlock_rdlock(&f->tree_lock);
1579 path = get_path_name(f, parent, name);
1580 if (path != NULL) {
1581 struct fuse_intr_data d;
1582 if (f->conf.debug)
1583 fprintf(stderr, "MKDIR %s\n", path);
1584 fuse_prepare_interrupt(f, req, &d);
1585 err = fuse_fs_mkdir(f->fs, path, mode);
1586 if (!err)
1587 err = lookup_path(f, parent, name, path, &e, NULL);
1588 fuse_finish_interrupt(f, req, &d);
1589 free(path);
1591 pthread_rwlock_unlock(&f->tree_lock);
1592 reply_entry(req, &e, err);
1595 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
1596 const char *name)
1598 struct fuse *f = req_fuse_prepare(req);
1599 char *path;
1600 int err;
1602 err = -ENOENT;
1603 pthread_rwlock_wrlock(&f->tree_lock);
1604 path = get_path_name(f, parent, name);
1605 if (path != NULL) {
1606 struct fuse_intr_data d;
1607 if (f->conf.debug)
1608 fprintf(stderr, "UNLINK %s\n", path);
1609 fuse_prepare_interrupt(f, req, &d);
1610 if (!f->conf.hard_remove && is_open(f, parent, name))
1611 err = hide_node(f, path, parent, name);
1612 else {
1613 err = fuse_fs_unlink(f->fs, path);
1614 if (!err)
1615 remove_node(f, parent, name);
1617 fuse_finish_interrupt(f, req, &d);
1618 free(path);
1620 pthread_rwlock_unlock(&f->tree_lock);
1621 reply_err(req, err);
1624 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
1626 struct fuse *f = req_fuse_prepare(req);
1627 char *path;
1628 int err;
1630 err = -ENOENT;
1631 pthread_rwlock_wrlock(&f->tree_lock);
1632 path = get_path_name(f, parent, name);
1633 if (path != NULL) {
1634 struct fuse_intr_data d;
1635 if (f->conf.debug)
1636 fprintf(stderr, "RMDIR %s\n", path);
1637 fuse_prepare_interrupt(f, req, &d);
1638 err = fuse_fs_rmdir(f->fs, path);
1639 fuse_finish_interrupt(f, req, &d);
1640 if (!err)
1641 remove_node(f, parent, name);
1642 free(path);
1644 pthread_rwlock_unlock(&f->tree_lock);
1645 reply_err(req, err);
1648 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
1649 fuse_ino_t parent, const char *name)
1651 struct fuse *f = req_fuse_prepare(req);
1652 struct fuse_entry_param e;
1653 char *path;
1654 int err;
1656 err = -ENOENT;
1657 pthread_rwlock_rdlock(&f->tree_lock);
1658 path = get_path_name(f, parent, name);
1659 if (path != NULL) {
1660 struct fuse_intr_data d;
1661 if (f->conf.debug)
1662 fprintf(stderr, "SYMLINK %s\n", path);
1663 fuse_prepare_interrupt(f, req, &d);
1664 err = fuse_fs_symlink(f->fs, linkname, path);
1665 if (!err)
1666 err = lookup_path(f, parent, name, path, &e, NULL);
1667 fuse_finish_interrupt(f, req, &d);
1668 free(path);
1670 pthread_rwlock_unlock(&f->tree_lock);
1671 reply_entry(req, &e, err);
1674 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
1675 const char *oldname, fuse_ino_t newdir,
1676 const char *newname)
1678 struct fuse *f = req_fuse_prepare(req);
1679 char *oldpath;
1680 char *newpath;
1681 int err;
1683 err = -ENOENT;
1684 pthread_rwlock_wrlock(&f->tree_lock);
1685 oldpath = get_path_name(f, olddir, oldname);
1686 if (oldpath != NULL) {
1687 newpath = get_path_name(f, newdir, newname);
1688 if (newpath != NULL) {
1689 struct fuse_intr_data d;
1690 if (f->conf.debug)
1691 fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath);
1692 err = 0;
1693 fuse_prepare_interrupt(f, req, &d);
1694 if (!f->conf.hard_remove && is_open(f, newdir, newname))
1695 err = hide_node(f, newpath, newdir, newname);
1696 if (!err) {
1697 err = fuse_fs_rename(f->fs, oldpath, newpath);
1698 if (!err)
1699 err = rename_node(f, olddir, oldname, newdir, newname, 0);
1701 fuse_finish_interrupt(f, req, &d);
1702 free(newpath);
1704 free(oldpath);
1706 pthread_rwlock_unlock(&f->tree_lock);
1707 reply_err(req, err);
1710 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
1711 const char *newname)
1713 struct fuse *f = req_fuse_prepare(req);
1714 struct fuse_entry_param e;
1715 char *oldpath;
1716 char *newpath;
1717 int err;
1719 err = -ENOENT;
1720 pthread_rwlock_rdlock(&f->tree_lock);
1721 oldpath = get_path(f, ino);
1722 if (oldpath != NULL) {
1723 newpath = get_path_name(f, newparent, newname);
1724 if (newpath != NULL) {
1725 struct fuse_intr_data d;
1726 if (f->conf.debug)
1727 fprintf(stderr, "LINK %s\n", newpath);
1728 fuse_prepare_interrupt(f, req, &d);
1729 err = fuse_fs_link(f->fs, oldpath, newpath);
1730 if (!err)
1731 err = lookup_path(f, newparent, newname, newpath, &e, NULL);
1732 fuse_finish_interrupt(f, req, &d);
1733 free(newpath);
1735 free(oldpath);
1737 pthread_rwlock_unlock(&f->tree_lock);
1738 reply_entry(req, &e, err);
1741 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
1742 struct fuse_file_info *fi)
1744 struct node *node;
1745 int unlink_hidden = 0;
1747 fuse_fs_release(f->fs, path ? path : "-", fi);
1749 pthread_mutex_lock(&f->lock);
1750 node = get_node(f, ino);
1751 assert(node->open_count > 0);
1752 --node->open_count;
1753 if (node->is_hidden && !node->open_count) {
1754 unlink_hidden = 1;
1755 node->is_hidden = 0;
1757 pthread_mutex_unlock(&f->lock);
1759 if(unlink_hidden && path)
1760 fuse_fs_unlink(f->fs, path);
1763 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
1764 const char *name, mode_t mode,
1765 struct fuse_file_info *fi)
1767 struct fuse *f = req_fuse_prepare(req);
1768 struct fuse_intr_data d;
1769 struct fuse_entry_param e;
1770 char *path;
1771 int err;
1773 err = -ENOENT;
1774 pthread_rwlock_rdlock(&f->tree_lock);
1775 path = get_path_name(f, parent, name);
1776 if (path) {
1777 fuse_prepare_interrupt(f, req, &d);
1778 err = fuse_fs_create(f->fs, path, mode, fi);
1779 if (!err) {
1780 err = lookup_path(f, parent, name, path, &e, fi);
1781 if (err)
1782 fuse_fs_release(f->fs, path, fi);
1783 else if (!S_ISREG(e.attr.st_mode)) {
1784 err = -EIO;
1785 fuse_fs_release(f->fs, path, fi);
1786 forget_node(f, e.ino, 1);
1787 } else {
1788 if (f->conf.direct_io)
1789 fi->direct_io = 1;
1790 if (f->conf.kernel_cache)
1791 fi->keep_cache = 1;
1795 fuse_finish_interrupt(f, req, &d);
1797 if (!err) {
1798 pthread_mutex_lock(&f->lock);
1799 get_node(f, e.ino)->open_count++;
1800 pthread_mutex_unlock(&f->lock);
1801 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
1802 /* The open syscall was interrupted, so it must be cancelled */
1803 fuse_prepare_interrupt(f, req, &d);
1804 fuse_do_release(f, e.ino, path, fi);
1805 fuse_finish_interrupt(f, req, &d);
1806 forget_node(f, e.ino, 1);
1807 } else if (f->conf.debug) {
1808 fprintf(stderr, " CREATE[%llu] flags: 0x%x %s\n",
1809 (unsigned long long) fi->fh, fi->flags, path);
1811 } else
1812 reply_err(req, err);
1814 if (path)
1815 free(path);
1817 pthread_rwlock_unlock(&f->tree_lock);
1820 #ifdef __SOLARIS__
1822 static double diff_timespec(const struct timespec *t1,
1823 const struct timespec *t2)
1825 return (t1->tv_sec - t2->tv_sec) +
1826 ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
1829 static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
1830 struct fuse_file_info *fi)
1832 struct node *node;
1834 pthread_mutex_lock(&f->lock);
1835 node = get_node(f, ino);
1836 if (node->cache_valid) {
1837 struct timespec now;
1839 curr_time(&now);
1840 if (diff_timespec(&now, &node->stat_updated) > f->conf.ac_attr_timeout) {
1841 struct stat stbuf;
1842 int err;
1843 pthread_mutex_unlock(&f->lock);
1844 err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
1845 pthread_mutex_lock(&f->lock);
1846 if (!err)
1847 update_stat(node, &stbuf);
1848 else
1849 node->cache_valid = 0;
1852 if (node->cache_valid)
1853 fi->keep_cache = 1;
1855 node->cache_valid = 1;
1856 pthread_mutex_unlock(&f->lock);
1859 #endif /* __SOLARIS__ */
1861 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
1862 struct fuse_file_info *fi)
1864 struct fuse *f = req_fuse_prepare(req);
1865 struct fuse_intr_data d;
1866 char *path = NULL;
1867 int err = 0;
1869 err = -ENOENT;
1870 pthread_rwlock_rdlock(&f->tree_lock);
1871 path = get_path(f, ino);
1872 if (path) {
1873 fuse_prepare_interrupt(f, req, &d);
1874 err = fuse_fs_open(f->fs, path, fi);
1875 if (!err) {
1876 if (f->conf.direct_io)
1877 fi->direct_io = 1;
1878 if (f->conf.kernel_cache)
1879 fi->keep_cache = 1;
1880 #ifdef __SOLARIS__
1882 if (f->conf.auto_cache)
1883 open_auto_cache(f, ino, path, fi);
1884 #endif /* __SOLARIS__ */
1886 fuse_finish_interrupt(f, req, &d);
1888 if (!err) {
1889 pthread_mutex_lock(&f->lock);
1890 get_node(f, ino)->open_count++;
1891 pthread_mutex_unlock(&f->lock);
1892 if (fuse_reply_open(req, fi) == -ENOENT) {
1893 /* The open syscall was interrupted, so it must be cancelled */
1894 fuse_prepare_interrupt(f, req, &d);
1895 fuse_do_release(f, ino, path, fi);
1896 fuse_finish_interrupt(f, req, &d);
1897 } else if (f->conf.debug) {
1898 fprintf(stderr, "OPEN[%llu] flags: 0x%x %s\n",
1899 (unsigned long long) fi->fh, fi->flags, path);
1901 } else
1902 reply_err(req, err);
1904 if (path)
1905 free(path);
1906 pthread_rwlock_unlock(&f->tree_lock);
1909 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
1910 off_t off, struct fuse_file_info *fi)
1912 struct fuse *f = req_fuse_prepare(req);
1913 char *path;
1914 char *buf;
1915 int res;
1917 buf = (char *) malloc(size);
1918 if (buf == NULL) {
1919 reply_err(req, -ENOMEM);
1920 return;
1923 res = -ENOENT;
1924 pthread_rwlock_rdlock(&f->tree_lock);
1925 path = get_path(f, ino);
1926 if (path != NULL) {
1927 struct fuse_intr_data d;
1928 if (f->conf.debug)
1929 fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",
1930 (unsigned long long) fi->fh, (unsigned long) size,
1931 (unsigned long long) off);
1933 fuse_prepare_interrupt(f, req, &d);
1934 res = fuse_fs_read(f->fs, path, buf, size, off, fi);
1935 fuse_finish_interrupt(f, req, &d);
1936 free(path);
1938 pthread_rwlock_unlock(&f->tree_lock);
1940 if (res >= 0) {
1941 if (f->conf.debug)
1942 fprintf(stderr, " READ[%llu] %u bytes\n",
1943 (unsigned long long)fi->fh, res);
1944 if ((size_t) res > size)
1945 fprintf(stderr, "fuse: read too many bytes");
1946 fuse_reply_buf(req, buf, res);
1947 } else
1948 reply_err(req, res);
1950 free(buf);
1953 static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
1954 size_t size, off_t off, struct fuse_file_info *fi)
1956 struct fuse *f = req_fuse_prepare(req);
1957 char *path;
1958 int res;
1960 res = -ENOENT;
1961 pthread_rwlock_rdlock(&f->tree_lock);
1962 path = get_path(f, ino);
1963 if (path != NULL) {
1964 struct fuse_intr_data d;
1965 if (f->conf.debug)
1966 fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n",
1967 fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
1968 (unsigned long) size, (unsigned long long) off);
1970 fuse_prepare_interrupt(f, req, &d);
1971 res = fuse_fs_write(f->fs, path, buf, size, off, fi);
1972 fuse_finish_interrupt(f, req, &d);
1973 free(path);
1975 pthread_rwlock_unlock(&f->tree_lock);
1977 if (res >= 0) {
1978 if (f->conf.debug)
1979 fprintf(stderr, " WRITE%s[%llu] %u bytes\n",
1980 fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
1981 res);
1982 if ((size_t) res > size)
1983 fprintf(stderr, "fuse: wrote too many bytes");
1984 fuse_reply_write(req, res);
1985 } else
1986 reply_err(req, res);
1989 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
1990 struct fuse_file_info *fi)
1992 struct fuse *f = req_fuse_prepare(req);
1993 char *path;
1994 int err;
1996 err = -ENOENT;
1997 pthread_rwlock_rdlock(&f->tree_lock);
1998 path = get_path(f, ino);
1999 if (path != NULL) {
2000 struct fuse_intr_data d;
2001 if (f->conf.debug)
2002 fprintf(stderr, "FSYNC[%llu]\n", (unsigned long long) fi->fh);
2003 fuse_prepare_interrupt(f, req, &d);
2004 err = fuse_fs_fsync(f->fs, path, datasync, fi);
2005 fuse_finish_interrupt(f, req, &d);
2006 free(path);
2008 pthread_rwlock_unlock(&f->tree_lock);
2009 reply_err(req, err);
2012 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
2013 struct fuse_file_info *fi)
2015 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
2016 memset(fi, 0, sizeof(struct fuse_file_info));
2017 fi->fh = dh->fh;
2018 fi->fh_old = dh->fh;
2019 return dh;
2022 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
2023 struct fuse_file_info *llfi)
2025 struct fuse *f = req_fuse_prepare(req);
2026 struct fuse_intr_data d;
2027 struct fuse_dh *dh;
2028 struct fuse_file_info fi;
2029 char *path;
2030 int err;
2032 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
2033 if (dh == NULL) {
2034 reply_err(req, -ENOMEM);
2035 return;
2037 memset(dh, 0, sizeof(struct fuse_dh));
2038 dh->fuse = f;
2039 dh->contents = NULL;
2040 dh->len = 0;
2041 dh->filled = 0;
2042 dh->nodeid = ino;
2043 fuse_mutex_init(&dh->lock);
2045 llfi->fh = (uintptr_t) dh;
2047 memset(&fi, 0, sizeof(fi));
2048 fi.flags = llfi->flags;
2050 err = -ENOENT;
2051 pthread_rwlock_rdlock(&f->tree_lock);
2052 path = get_path(f, ino);
2053 if (path != NULL) {
2054 fuse_prepare_interrupt(f, req, &d);
2055 err = fuse_fs_opendir(f->fs, path, &fi);
2056 fuse_finish_interrupt(f, req, &d);
2057 dh->fh = fi.fh;
2059 if (!err) {
2060 if (fuse_reply_open(req, llfi) == -ENOENT) {
2061 /* The opendir syscall was interrupted, so it must be cancelled */
2062 fuse_prepare_interrupt(f, req, &d);
2063 fuse_fs_releasedir(f->fs, path, &fi);
2064 fuse_finish_interrupt(f, req, &d);
2065 pthread_mutex_destroy(&dh->lock);
2066 free(dh);
2068 } else {
2069 reply_err(req, err);
2070 #ifndef __SOLARIS__
2071 pthread_mutex_destroy(&dh->lock);
2072 #endif /* ! __SOLARIS__ */
2073 free(dh);
2075 free(path);
2076 pthread_rwlock_unlock(&f->tree_lock);
2079 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
2081 if (minsize > dh->size) {
2082 char *newptr;
2083 unsigned newsize = dh->size;
2084 if (!newsize)
2085 newsize = 1024;
2086 #ifndef __SOLARIS__
2087 while (newsize < minsize) {
2088 if (newsize >= 0x80000000)
2089 newsize = 0xffffffff;
2090 else
2091 newsize *= 2;
2093 #else /* __SOLARIS__ */
2094 while (newsize < minsize)
2095 newsize *= 2;
2096 #endif /* __SOLARIS__ */
2098 newptr = (char *) realloc(dh->contents, newsize);
2099 if (!newptr) {
2100 dh->error = -ENOMEM;
2101 return -1;
2103 dh->contents = newptr;
2104 dh->size = newsize;
2106 return 0;
2109 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
2110 off_t off)
2112 struct fuse_dh *dh = (struct fuse_dh *) dh_;
2113 struct stat stbuf;
2114 size_t newlen;
2116 if (statp)
2117 stbuf = *statp;
2118 else {
2119 memset(&stbuf, 0, sizeof(stbuf));
2120 stbuf.st_ino = FUSE_UNKNOWN_INO;
2123 if (!dh->fuse->conf.use_ino) {
2124 stbuf.st_ino = FUSE_UNKNOWN_INO;
2125 if (dh->fuse->conf.readdir_ino) {
2126 struct node *node;
2127 pthread_mutex_lock(&dh->fuse->lock);
2128 node = lookup_node(dh->fuse, dh->nodeid, name);
2129 if (node)
2130 stbuf.st_ino = (ino_t) node->nodeid;
2131 pthread_mutex_unlock(&dh->fuse->lock);
2135 if (off) {
2136 if (extend_contents(dh, dh->needlen) == -1)
2137 return 1;
2139 dh->filled = 0;
2140 newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len,
2141 dh->needlen - dh->len, name,
2142 &stbuf, off);
2143 if (newlen > dh->needlen)
2144 return 1;
2145 } else {
2146 newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
2147 if (extend_contents(dh, newlen) == -1)
2148 return 1;
2150 fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len,
2151 name, &stbuf, newlen);
2153 dh->len = newlen;
2154 return 0;
2157 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2158 size_t size, off_t off, struct fuse_dh *dh,
2159 struct fuse_file_info *fi)
2161 int err = -ENOENT;
2162 char *path;
2163 pthread_rwlock_rdlock(&f->tree_lock);
2164 path = get_path(f, ino);
2165 if (path != NULL) {
2166 struct fuse_intr_data d;
2168 dh->len = 0;
2169 dh->error = 0;
2170 dh->needlen = size;
2171 dh->filled = 1;
2172 dh->req = req;
2173 fuse_prepare_interrupt(f, req, &d);
2174 err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
2175 fuse_finish_interrupt(f, req, &d);
2176 dh->req = NULL;
2177 if (!err)
2178 err = dh->error;
2179 if (err)
2180 dh->filled = 0;
2181 free(path);
2183 pthread_rwlock_unlock(&f->tree_lock);
2184 return err;
2187 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
2188 off_t off, struct fuse_file_info *llfi)
2190 struct fuse *f = req_fuse_prepare(req);
2191 struct fuse_file_info fi;
2192 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
2194 pthread_mutex_lock(&dh->lock);
2195 /* According to SUS, directory contents need to be refreshed on
2196 rewinddir() */
2197 if (!off)
2198 dh->filled = 0;
2200 if (!dh->filled) {
2201 int err = readdir_fill(f, req, ino, size, off, dh, &fi);
2202 if (err) {
2203 reply_err(req, err);
2204 goto out;
2207 if (dh->filled) {
2208 if (off < dh->len) {
2209 if (off + size > dh->len)
2210 size = dh->len - off;
2211 } else
2212 size = 0;
2213 } else {
2214 size = dh->len;
2215 off = 0;
2217 fuse_reply_buf(req, dh->contents + off, size);
2218 out:
2219 pthread_mutex_unlock(&dh->lock);
2222 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
2223 struct fuse_file_info *llfi)
2225 struct fuse *f = req_fuse_prepare(req);
2226 struct fuse_intr_data d;
2227 struct fuse_file_info fi;
2228 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
2229 char *path;
2231 pthread_rwlock_rdlock(&f->tree_lock);
2232 path = get_path(f, ino);
2233 fuse_prepare_interrupt(f, req, &d);
2234 fuse_fs_releasedir(f->fs, path ? path : "-", &fi);
2235 fuse_finish_interrupt(f, req, &d);
2236 if (path)
2237 free(path);
2238 pthread_rwlock_unlock(&f->tree_lock);
2239 pthread_mutex_lock(&dh->lock);
2240 pthread_mutex_unlock(&dh->lock);
2241 pthread_mutex_destroy(&dh->lock);
2242 free(dh->contents);
2243 free(dh);
2244 reply_err(req, 0);
2247 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
2248 struct fuse_file_info *llfi)
2250 struct fuse *f = req_fuse_prepare(req);
2251 struct fuse_file_info fi;
2252 char *path;
2253 int err;
2255 get_dirhandle(llfi, &fi);
2257 err = -ENOENT;
2258 pthread_rwlock_rdlock(&f->tree_lock);
2259 path = get_path(f, ino);
2260 if (path != NULL) {
2261 struct fuse_intr_data d;
2262 fuse_prepare_interrupt(f, req, &d);
2263 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
2264 fuse_finish_interrupt(f, req, &d);
2265 free(path);
2267 pthread_rwlock_unlock(&f->tree_lock);
2268 reply_err(req, err);
2271 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
2273 struct fuse *f = req_fuse_prepare(req);
2274 struct statvfs buf;
2275 char *path;
2276 int err;
2278 memset(&buf, 0, sizeof(buf));
2279 pthread_rwlock_rdlock(&f->tree_lock);
2280 if (!ino) {
2281 err = -ENOMEM;
2282 path = strdup("/");
2283 } else {
2284 err = -ENOENT;
2285 path = get_path(f, ino);
2287 if (path) {
2288 struct fuse_intr_data d;
2289 fuse_prepare_interrupt(f, req, &d);
2290 err = fuse_fs_statfs(f->fs, path, &buf);
2291 fuse_finish_interrupt(f, req, &d);
2292 free(path);
2294 pthread_rwlock_unlock(&f->tree_lock);
2296 if (!err)
2297 fuse_reply_statfs(req, &buf);
2298 else
2299 reply_err(req, err);
2302 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
2303 const char *value, size_t size, int flags)
2305 struct fuse *f = req_fuse_prepare(req);
2306 char *path;
2307 int err;
2309 err = -ENOENT;
2310 pthread_rwlock_rdlock(&f->tree_lock);
2311 path = get_path(f, ino);
2312 if (path != NULL) {
2313 struct fuse_intr_data d;
2314 fuse_prepare_interrupt(f, req, &d);
2315 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
2316 fuse_finish_interrupt(f, req, &d);
2317 free(path);
2319 pthread_rwlock_unlock(&f->tree_lock);
2320 reply_err(req, err);
2323 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2324 const char *name, char *value, size_t size)
2326 int err;
2327 char *path;
2329 err = -ENOENT;
2330 pthread_rwlock_rdlock(&f->tree_lock);
2331 path = get_path(f, ino);
2332 if (path != NULL) {
2333 struct fuse_intr_data d;
2334 fuse_prepare_interrupt(f, req, &d);
2335 err = fuse_fs_getxattr(f->fs, path, name, value, size);
2336 fuse_finish_interrupt(f, req, &d);
2337 free(path);
2339 pthread_rwlock_unlock(&f->tree_lock);
2340 return err;
2343 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
2344 size_t size)
2346 struct fuse *f = req_fuse_prepare(req);
2347 int res;
2349 if (size) {
2350 char *value = (char *) malloc(size);
2351 if (value == NULL) {
2352 reply_err(req, -ENOMEM);
2353 return;
2355 res = common_getxattr(f, req, ino, name, value, size);
2356 if (res > 0)
2357 fuse_reply_buf(req, value, res);
2358 else
2359 reply_err(req, res);
2360 free(value);
2361 } else {
2362 res = common_getxattr(f, req, ino, name, NULL, 0);
2363 if (res >= 0)
2364 fuse_reply_xattr(req, res);
2365 else
2366 reply_err(req, res);
2370 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2371 char *list, size_t size)
2373 char *path;
2374 int err;
2376 err = -ENOENT;
2377 pthread_rwlock_rdlock(&f->tree_lock);
2378 path = get_path(f, ino);
2379 if (path != NULL) {
2380 struct fuse_intr_data d;
2381 fuse_prepare_interrupt(f, req, &d);
2382 err = fuse_fs_listxattr(f->fs, path, list, size);
2383 fuse_finish_interrupt(f, req, &d);
2384 free(path);
2386 pthread_rwlock_unlock(&f->tree_lock);
2387 return err;
2390 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
2392 struct fuse *f = req_fuse_prepare(req);
2393 int res;
2395 if (size) {
2396 char *list = (char *) malloc(size);
2397 if (list == NULL) {
2398 reply_err(req, -ENOMEM);
2399 return;
2401 res = common_listxattr(f, req, ino, list, size);
2402 if (res > 0)
2403 fuse_reply_buf(req, list, res);
2404 else
2405 reply_err(req, res);
2406 free(list);
2407 } else {
2408 res = common_listxattr(f, req, ino, NULL, 0);
2409 if (res >= 0)
2410 fuse_reply_xattr(req, res);
2411 else
2412 reply_err(req, res);
2416 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
2417 const char *name)
2419 struct fuse *f = req_fuse_prepare(req);
2420 char *path;
2421 int err;
2423 err = -ENOENT;
2424 pthread_rwlock_rdlock(&f->tree_lock);
2425 path = get_path(f, ino);
2426 if (path != NULL) {
2427 struct fuse_intr_data d;
2428 fuse_prepare_interrupt(f, req, &d);
2429 err = fuse_fs_removexattr(f->fs, path, name);
2430 fuse_finish_interrupt(f, req, &d);
2431 free(path);
2433 pthread_rwlock_unlock(&f->tree_lock);
2434 reply_err(req, err);
2437 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
2439 struct lock *l;
2441 for (l = node->locks; l; l = l->next)
2442 if (l->owner != lock->owner &&
2443 lock->start <= l->end && l->start <= lock->end &&
2444 (l->type == F_WRLCK || lock->type == F_WRLCK))
2445 break;
2447 return l;
2450 static void delete_lock(struct lock **lockp)
2452 struct lock *l = *lockp;
2453 *lockp = l->next;
2454 free(l);
2457 static void insert_lock(struct lock **pos, struct lock *lock)
2459 lock->next = *pos;
2460 *pos = lock;
2463 static int locks_insert(struct node *node, struct lock *lock)
2465 struct lock **lp;
2466 struct lock *newl1 = NULL;
2467 struct lock *newl2 = NULL;
2469 if (lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX) {
2470 newl1 = malloc(sizeof(struct lock));
2471 newl2 = malloc(sizeof(struct lock));
2473 if (!newl1 || !newl2) {
2474 free(newl1);
2475 free(newl2);
2476 return -ENOLCK;
2480 for (lp = &node->locks; *lp;) {
2481 struct lock *l = *lp;
2482 if (l->owner != lock->owner)
2483 goto skip;
2485 if (lock->type == l->type) {
2486 if (l->end < lock->start - 1)
2487 goto skip;
2488 if (lock->end < l->start - 1)
2489 break;
2490 if (l->start <= lock->start && lock->end <= l->end)
2491 goto out;
2492 if (l->start < lock->start)
2493 lock->start = l->start;
2494 if (lock->end < l->end)
2495 lock->end = l->end;
2496 goto delete;
2497 } else {
2498 if (l->end < lock->start)
2499 goto skip;
2500 if (lock->end < l->start)
2501 break;
2502 if (lock->start <= l->start && l->end <= lock->end)
2503 goto delete;
2504 if (l->end <= lock->end) {
2505 l->end = lock->start - 1;
2506 goto skip;
2508 if (lock->start <= l->start) {
2509 l->start = lock->end + 1;
2510 break;
2512 *newl2 = *l;
2513 newl2->start = lock->end + 1;
2514 l->end = lock->start - 1;
2515 insert_lock(&l->next, newl2);
2516 newl2 = NULL;
2518 skip:
2519 lp = &l->next;
2520 continue;
2522 delete:
2523 delete_lock(lp);
2525 if (lock->type != F_UNLCK) {
2526 *newl1 = *lock;
2527 insert_lock(lp, newl1);
2528 newl1 = NULL;
2530 out:
2531 free(newl1);
2532 free(newl2);
2533 return 0;
2536 static void flock_to_lock(struct flock *flock, struct lock *lock)
2538 memset(lock, 0, sizeof(struct lock));
2539 lock->type = flock->l_type;
2540 lock->start = flock->l_start;
2541 lock->end = flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
2542 lock->pid = flock->l_pid;
2545 static void lock_to_flock(struct lock *lock, struct flock *flock)
2547 flock->l_type = lock->type;
2548 flock->l_start = lock->start;
2549 flock->l_len = (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
2550 flock->l_pid = lock->pid;
2553 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2554 const char *path, struct fuse_file_info *fi)
2556 struct fuse_intr_data d;
2557 struct flock lock;
2558 struct lock l;
2559 int err;
2560 int errlock;
2562 fuse_prepare_interrupt(f, req, &d);
2563 memset(&lock, 0, sizeof(lock));
2564 lock.l_type = F_UNLCK;
2565 lock.l_whence = SEEK_SET;
2566 err = fuse_fs_flush(f->fs, path, fi);
2567 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
2568 fuse_finish_interrupt(f, req, &d);
2570 if (errlock != -ENOSYS) {
2571 flock_to_lock(&lock, &l);
2572 l.owner = fi->lock_owner;
2573 pthread_mutex_lock(&f->lock);
2574 locks_insert(get_node(f, ino), &l);
2575 pthread_mutex_unlock(&f->lock);
2577 /* if op.lock() is defined FLUSH is needed regardless of op.flush() */
2578 if (err == -ENOSYS)
2579 err = 0;
2581 return err;
2584 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
2585 struct fuse_file_info *fi)
2587 struct fuse *f = req_fuse_prepare(req);
2588 struct fuse_intr_data d;
2589 char *path;
2590 int err = 0;
2592 pthread_rwlock_rdlock(&f->tree_lock);
2593 path = get_path(f, ino);
2594 if (f->conf.debug)
2595 fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n",
2596 fi->flush ? "+FLUSH" : "",
2597 (unsigned long long) fi->fh, fi->flags);
2599 if (fi->flush) {
2600 err = fuse_flush_common(f, req, ino, path, fi);
2601 if (err == -ENOSYS)
2602 err = 0;
2605 fuse_prepare_interrupt(f, req, &d);
2606 fuse_do_release(f, ino, path, fi);
2607 fuse_finish_interrupt(f, req, &d);
2608 free(path);
2609 pthread_rwlock_unlock(&f->tree_lock);
2611 reply_err(req, err);
2614 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
2615 struct fuse_file_info *fi)
2617 struct fuse *f = req_fuse_prepare(req);
2618 char *path;
2619 int err;
2621 pthread_rwlock_rdlock(&f->tree_lock);
2622 path = get_path(f, ino);
2623 if (path && f->conf.debug)
2624 fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh);
2625 err = fuse_flush_common(f, req, ino, path, fi);
2626 free(path);
2627 pthread_rwlock_unlock(&f->tree_lock);
2628 reply_err(req, err);
2631 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
2632 struct fuse_file_info *fi, struct flock *lock,
2633 int cmd)
2635 struct fuse *f = req_fuse_prepare(req);
2636 char *path;
2637 int err;
2639 err = -ENOENT;
2640 pthread_rwlock_rdlock(&f->tree_lock);
2641 path = get_path(f, ino);
2642 if (path != NULL) {
2643 struct fuse_intr_data d;
2644 fuse_prepare_interrupt(f, req, &d);
2645 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
2646 fuse_finish_interrupt(f, req, &d);
2647 free(path);
2649 pthread_rwlock_unlock(&f->tree_lock);
2650 return err;
2653 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
2654 struct fuse_file_info *fi, struct flock *lock)
2656 int err;
2657 struct lock l;
2658 struct lock *conflict;
2659 struct fuse *f = req_fuse(req);
2661 flock_to_lock(lock, &l);
2662 l.owner = fi->lock_owner;
2663 pthread_mutex_lock(&f->lock);
2664 conflict = locks_conflict(get_node(f, ino), &l);
2665 if (conflict)
2666 lock_to_flock(conflict, lock);
2667 pthread_mutex_unlock(&f->lock);
2668 if (!conflict)
2669 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
2670 else
2671 err = 0;
2673 if (!err)
2674 fuse_reply_lock(req, lock);
2675 else
2676 reply_err(req, err);
2679 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
2680 struct fuse_file_info *fi, struct flock *lock,
2681 int should_sleep)
2683 int err = fuse_lock_common(req, ino, fi, lock, should_sleep ? F_SETLKW : F_SETLK);
2684 if (!err) {
2685 struct fuse *f = req_fuse(req);
2686 struct lock l;
2687 flock_to_lock(lock, &l);
2688 l.owner = fi->lock_owner;
2689 pthread_mutex_lock(&f->lock);
2690 locks_insert(get_node(f, ino), &l);
2691 pthread_mutex_unlock(&f->lock);
2693 reply_err(req, err);
2696 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
2697 uint64_t idx)
2699 struct fuse *f = req_fuse_prepare(req);
2700 struct fuse_intr_data d;
2701 char *path;
2702 int err;
2704 err = -ENOENT;
2705 pthread_rwlock_rdlock(&f->tree_lock);
2706 path = get_path(f, ino);
2707 if (path != NULL) {
2708 fuse_prepare_interrupt(f, req, &d);
2709 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
2710 fuse_finish_interrupt(f, req, &d);
2711 free(path);
2713 pthread_rwlock_unlock(&f->tree_lock);
2714 if (!err)
2715 fuse_reply_bmap(req, idx);
2716 else
2717 reply_err(req, err);
2720 static struct fuse_lowlevel_ops fuse_path_ops = {
2721 .init = fuse_lib_init,
2722 .destroy = fuse_lib_destroy,
2723 .lookup = fuse_lib_lookup,
2724 .forget = fuse_lib_forget,
2725 .getattr = fuse_lib_getattr,
2726 .setattr = fuse_lib_setattr,
2727 .access = fuse_lib_access,
2728 .readlink = fuse_lib_readlink,
2729 .mknod = fuse_lib_mknod,
2730 .mkdir = fuse_lib_mkdir,
2731 .unlink = fuse_lib_unlink,
2732 .rmdir = fuse_lib_rmdir,
2733 .symlink = fuse_lib_symlink,
2734 .rename = fuse_lib_rename,
2735 .link = fuse_lib_link,
2736 .create = fuse_lib_create,
2737 .open = fuse_lib_open,
2738 .read = fuse_lib_read,
2739 .write = fuse_lib_write,
2740 .flush = fuse_lib_flush,
2741 .release = fuse_lib_release,
2742 .fsync = fuse_lib_fsync,
2743 .opendir = fuse_lib_opendir,
2744 .readdir = fuse_lib_readdir,
2745 .releasedir = fuse_lib_releasedir,
2746 .fsyncdir = fuse_lib_fsyncdir,
2747 .statfs = fuse_lib_statfs,
2748 .setxattr = fuse_lib_setxattr,
2749 .getxattr = fuse_lib_getxattr,
2750 .listxattr = fuse_lib_listxattr,
2751 .removexattr = fuse_lib_removexattr,
2752 .getlk = fuse_lib_getlk,
2753 .setlk = fuse_lib_setlk,
2754 .bmap = fuse_lib_bmap,
2757 struct fuse_session *fuse_get_session(struct fuse *f)
2759 return f->se;
2762 int fuse_loop(struct fuse *f)
2764 if (f)
2765 return fuse_session_loop(f->se);
2766 else
2767 return -1;
2770 void fuse_exit(struct fuse *f)
2772 fuse_session_exit(f->se);
2775 struct fuse_context *fuse_get_context(void)
2777 return &fuse_get_context_internal()->ctx;
2780 int fuse_interrupted(void)
2782 return fuse_req_interrupted(fuse_get_context_internal()->req);
2785 enum {
2786 KEY_HELP,
2789 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
2791 static const struct fuse_opt fuse_lib_opts[] = {
2792 FUSE_OPT_KEY("-h", KEY_HELP),
2793 FUSE_OPT_KEY("--help", KEY_HELP),
2794 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
2795 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
2796 FUSE_LIB_OPT("debug", debug, 1),
2797 FUSE_LIB_OPT("-d", debug, 1),
2798 FUSE_LIB_OPT("hard_remove", hard_remove, 1),
2799 FUSE_LIB_OPT("use_ino", use_ino, 1),
2800 FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
2801 FUSE_LIB_OPT("direct_io", direct_io, 1),
2802 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
2803 #ifdef __SOLARIS__
2804 FUSE_LIB_OPT("auto_cache", auto_cache, 1),
2805 FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
2806 #endif /* __SOLARIS__ */
2807 FUSE_LIB_OPT("umask=", set_mode, 1),
2808 FUSE_LIB_OPT("umask=%o", umask, 0),
2809 FUSE_LIB_OPT("uid=", set_uid, 1),
2810 FUSE_LIB_OPT("uid=%d", uid, 0),
2811 FUSE_LIB_OPT("gid=", set_gid, 1),
2812 FUSE_LIB_OPT("gid=%d", gid, 0),
2813 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
2814 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
2815 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
2816 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
2817 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
2818 FUSE_LIB_OPT("intr", intr, 1),
2819 FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
2820 #ifdef __SOLARIS__
2821 FUSE_LIB_OPT("modules=%s", modules, 0),
2822 #endif /* __SOLARIS__ */
2823 FUSE_OPT_END
2826 static void fuse_lib_help(void)
2828 fprintf(stderr,
2829 " -o hard_remove immediate removal (don't hide files)\n"
2830 " -o use_ino let filesystem set inode numbers\n"
2831 " -o readdir_ino try to fill in d_ino in readdir\n"
2832 " -o direct_io use direct I/O\n"
2833 " -o kernel_cache cache files in kernel\n"
2834 #ifdef __SOLARIS__
2835 " -o [no]auto_cache enable caching based on modification times\n"
2836 #endif /* __SOLARIS__ */
2837 " -o umask=M set file permissions (octal)\n"
2838 " -o uid=N set file owner\n"
2839 " -o gid=N set file group\n"
2840 " -o entry_timeout=T cache timeout for names (1.0s)\n"
2841 " -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
2842 " -o attr_timeout=T cache timeout for attributes (1.0s)\n"
2843 " -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
2844 " -o intr allow requests to be interrupted\n"
2845 " -o intr_signal=NUM signal to send on interrupt (%i)\n"
2846 #ifdef __SOLARIS__
2847 " -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
2848 #endif /* __SOLARIS__ */
2849 "\n", FUSE_DEFAULT_INTR_SIGNAL);
2852 #ifdef __SOLARIS__
2854 static void fuse_lib_help_modules(void)
2856 struct fuse_module *m;
2857 fprintf(stderr, "\nModule options:\n");
2858 pthread_mutex_lock(&fuse_context_lock);
2859 for (m = fuse_modules; m; m = m->next) {
2860 struct fuse_fs *fs = NULL;
2861 struct fuse_fs *newfs;
2862 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
2863 if (fuse_opt_add_arg(&args, "") != -1 &&
2864 fuse_opt_add_arg(&args, "-h") != -1) {
2865 fprintf(stderr, "\n[%s]\n", m->name);
2866 newfs = m->factory(&args, &fs);
2867 assert(newfs == NULL);
2869 fuse_opt_free_args(&args);
2871 pthread_mutex_unlock(&fuse_context_lock);
2874 int fuse_is_lib_option(const char *opt)
2876 return fuse_lowlevel_is_lib_option(opt) ||
2877 fuse_opt_match(fuse_lib_opts, opt);
2880 #endif /* __SOLARIS__ */
2882 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
2883 struct fuse_args *outargs)
2885 (void) arg; (void) outargs;
2887 if (key == KEY_HELP) {
2888 struct fuse_config *conf = (struct fuse_config *) data;
2889 fuse_lib_help();
2890 conf->help = 1;
2893 return 1;
2896 static int fuse_init_intr_signal(int signum, int *installed)
2898 struct sigaction old_sa;
2900 if (sigaction(signum, NULL, &old_sa) == -1) {
2901 perror("fuse: cannot get old signal handler");
2902 return -1;
2905 if (old_sa.sa_handler == SIG_DFL) {
2906 struct sigaction sa;
2908 memset(&sa, 0, sizeof(struct sigaction));
2909 sa.sa_handler = fuse_intr_sighandler;
2910 sigemptyset(&sa.sa_mask);
2912 if (sigaction(signum, &sa, NULL) == -1) {
2913 perror("fuse: cannot set interrupt signal handler");
2914 return -1;
2916 *installed = 1;
2918 return 0;
2921 static void fuse_restore_intr_signal(int signum)
2923 struct sigaction sa;
2925 memset(&sa, 0, sizeof(struct sigaction));
2926 sa.sa_handler = SIG_DFL;
2927 sigaction(signum, &sa, NULL);
2930 #ifdef __SOLARIS__
2932 static int fuse_push_module(struct fuse *f, const char *module,
2933 struct fuse_args *args)
2935 struct fuse_fs *newfs;
2936 struct fuse_module *m = fuse_get_module(module);
2937 struct fuse_fs *fs[2];
2939 fs[0] = f->fs;
2940 fs[1] = NULL;
2941 if (!m)
2942 return -1;
2944 newfs = m->factory(args, fs);
2945 if (!newfs) {
2946 fuse_put_module(m);
2947 return -1;
2949 newfs->m = m;
2950 f->fs = newfs;
2951 return 0;
2954 #endif /* __SOLARIS__ */
2956 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
2957 void *user_data)
2959 struct fuse_fs *fs;
2961 if (sizeof(struct fuse_operations) < op_size) {
2962 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
2963 op_size = sizeof(struct fuse_operations);
2966 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
2967 if (!fs) {
2968 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
2969 return NULL;
2972 fs->user_data = user_data;
2973 if (op)
2974 memcpy(&fs->op, op, op_size);
2975 return fs;
2978 struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
2979 const struct fuse_operations *op, size_t op_size,
2980 void *user_data)
2982 struct fuse *f;
2983 struct node *root;
2984 struct fuse_fs *fs;
2985 struct fuse_lowlevel_ops llop = fuse_path_ops;
2987 if (fuse_create_context_key() == -1)
2988 goto out;
2990 f = (struct fuse *) calloc(1, sizeof(struct fuse));
2991 if (f == NULL) {
2992 fprintf(stderr, "fuse: failed to allocate fuse object\n");
2993 goto out_delete_context_key;
2996 fs = fuse_fs_new(op, op_size, user_data);
2997 if (!fs)
2998 goto out_free;
3000 f->fs = fs;
3001 f->utime_omit_ok = fs->op.flag_utime_omit_ok;
3003 /* Oh f**k, this is ugly! */
3004 if (!fs->op.lock) {
3005 llop.getlk = NULL;
3006 llop.setlk = NULL;
3009 f->conf.entry_timeout = 1.0;
3010 f->conf.attr_timeout = 1.0;
3011 f->conf.negative_timeout = 0.0;
3012 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
3014 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1)
3015 goto out_free_fs;
3017 #ifdef __SOLARIS__
3018 if (f->conf.modules) {
3019 char *module;
3020 char *next;
3022 for (module = f->conf.modules; module; module = next) {
3023 char *p;
3024 for (p = module; *p && *p != ':'; p++);
3025 next = *p ? p + 1 : NULL;
3026 *p = '\0';
3027 if (module[0] && fuse_push_module(f, module, args) == -1)
3028 goto out_free_fs;
3031 #endif /* __SOLARIS__ */
3033 if (!f->conf.ac_attr_timeout_set)
3034 f->conf.ac_attr_timeout = f->conf.attr_timeout;
3036 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
3038 * In FreeBSD, we always use these settings as inode numbers are needed to
3039 * make getcwd(3) work.
3041 f->conf.readdir_ino = 1;
3042 #endif
3044 f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
3046 if (f->se == NULL) {
3047 #ifdef __SOLARIS__
3048 if (f->conf.help)
3049 fuse_lib_help_modules();
3050 #endif /* __SOLARIS__ */
3051 goto out_free_fs;
3054 fuse_session_add_chan(f->se, ch);
3056 #ifndef __SOLARIS__
3057 if (f->conf.debug)
3058 fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
3059 #endif /* ! __SOLARIS__ */
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;
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;
3079 fuse_mutex_init(&f->lock);
3080 pthread_rwlock_init(&f->tree_lock, NULL);
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;
3088 root->name = strdup("/");
3089 if (root->name == NULL) {
3090 fprintf(stderr, "fuse: memory allocation failed\n");
3091 goto out_free_root;
3094 if (f->conf.intr &&
3095 fuse_init_intr_signal(f->conf.intr_signal, &f->intr_installed) == -1)
3096 goto out_free_root_name;
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);
3105 return f;
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;
3133 void fuse_destroy(struct fuse *f)
3135 size_t i;
3137 if (f->conf.intr && f->intr_installed)
3138 fuse_restore_intr_signal(f->conf.intr_signal);
3140 if (f->fs) {
3141 struct fuse_context_i *c = fuse_get_context_internal();
3143 memset(c, 0, sizeof(*c));
3144 c->ctx.fuse = f;
3146 for (i = 0; i < f->id_table_size; i++) {
3147 struct node *node;
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);
3160 for (i = 0; i < f->id_table_size; i++) {
3161 struct node *node;
3162 struct node *next;
3164 for (node = f->id_table[i]; node != NULL; node = next) {
3165 next = node->id_next;
3166 free_node(node);
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();