minidlna support now Samsung TV C550/C650 (thx amir909)
[tomato.git] / release / src / router / ntfs-3g / libfuse-lite / fuse.c
blobcf186ccdeebc5b2fda5a965a3abd54d0d4b1d303
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 #include "config.h"
10 #include "fuse_i.h"
11 #include "fuse_lowlevel.h"
12 #include "fuse_opt.h"
13 #include "fuse_misc.h"
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <stddef.h>
19 #include <unistd.h>
20 #include <time.h>
21 #include <fcntl.h>
22 #include <limits.h>
23 #include <errno.h>
24 #include <signal.h>
25 #include <dlfcn.h>
26 #include <assert.h>
27 #include <sys/param.h>
28 #include <sys/uio.h>
29 #include <sys/time.h>
31 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
33 #define FUSE_UNKNOWN_INO 0xffffffff
34 #define OFFSET_MAX 0x7fffffffffffffffLL
36 struct fuse_config {
37 unsigned int uid;
38 unsigned int gid;
39 unsigned int umask;
40 double entry_timeout;
41 double negative_timeout;
42 double attr_timeout;
43 double ac_attr_timeout;
44 int ac_attr_timeout_set;
45 int debug;
46 int hard_remove;
47 int use_ino;
48 int readdir_ino;
49 int set_mode;
50 int set_uid;
51 int set_gid;
52 int direct_io;
53 int kernel_cache;
54 int intr;
55 int intr_signal;
56 int help;
59 struct fuse_fs {
60 struct fuse_operations op;
61 void *user_data;
64 struct fuse {
65 struct fuse_session *se;
66 struct node **name_table;
67 size_t name_table_size;
68 struct node **id_table;
69 size_t id_table_size;
70 fuse_ino_t ctr;
71 unsigned int generation;
72 unsigned int hidectr;
73 pthread_mutex_t lock;
74 pthread_rwlock_t tree_lock;
75 struct fuse_config conf;
76 int intr_installed;
77 struct fuse_fs *fs;
78 int utime_omit_ok;
81 struct lock {
82 int type;
83 off_t start;
84 off_t end;
85 pid_t pid;
86 uint64_t owner;
87 struct lock *next;
90 struct node {
91 struct node *name_next;
92 struct node *id_next;
93 fuse_ino_t nodeid;
94 unsigned int generation;
95 int refctr;
96 struct node *parent;
97 char *name;
98 uint64_t nlookup;
99 int open_count;
100 int is_hidden;
101 struct lock *locks;
104 struct fuse_dh {
105 pthread_mutex_t lock;
106 struct fuse *fuse;
107 fuse_req_t req;
108 char *contents;
109 int allocated;
110 unsigned len;
111 unsigned size;
112 unsigned needlen;
113 int filled;
114 uint64_t fh;
115 int error;
116 fuse_ino_t nodeid;
119 struct fuse_context_i {
120 struct fuse_context ctx;
121 fuse_req_t req;
124 static pthread_key_t fuse_context_key;
125 static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
126 static int fuse_context_ref;
128 static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
130 size_t hash = nodeid % f->id_table_size;
131 struct node *node;
133 for (node = f->id_table[hash]; node != NULL; node = node->id_next)
134 if (node->nodeid == nodeid)
135 return node;
137 return NULL;
140 static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
142 struct node *node = get_node_nocheck(f, nodeid);
143 if (!node) {
144 fprintf(stderr, "fuse internal error: node %llu not found\n",
145 (unsigned long long) nodeid);
146 abort();
148 return node;
151 static void free_node(struct node *node)
153 free(node->name);
154 free(node);
157 static void unhash_id(struct fuse *f, struct node *node)
159 size_t hash = node->nodeid % f->id_table_size;
160 struct node **nodep = &f->id_table[hash];
162 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
163 if (*nodep == node) {
164 *nodep = node->id_next;
165 return;
169 static void hash_id(struct fuse *f, struct node *node)
171 size_t hash = node->nodeid % f->id_table_size;
172 node->id_next = f->id_table[hash];
173 f->id_table[hash] = node;
176 static unsigned int name_hash(struct fuse *f, fuse_ino_t parent,
177 const char *name)
179 unsigned int hash = *name;
181 if (hash)
182 for (name += 1; *name != '\0'; name++)
183 hash = (hash << 5) - hash + *name;
185 return (hash + parent) % f->name_table_size;
188 static void unref_node(struct fuse *f, struct node *node);
190 static void unhash_name(struct fuse *f, struct node *node)
192 if (node->name) {
193 size_t hash = name_hash(f, node->parent->nodeid, node->name);
194 struct node **nodep = &f->name_table[hash];
196 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
197 if (*nodep == node) {
198 *nodep = node->name_next;
199 node->name_next = NULL;
200 unref_node(f, node->parent);
201 free(node->name);
202 node->name = NULL;
203 node->parent = NULL;
204 return;
206 fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n",
207 (unsigned long long) node->nodeid);
208 abort();
212 static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
213 const char *name)
215 size_t hash = name_hash(f, parentid, name);
216 struct node *parent = get_node(f, parentid);
217 node->name = strdup(name);
218 if (node->name == NULL)
219 return -1;
221 parent->refctr ++;
222 node->parent = parent;
223 node->name_next = f->name_table[hash];
224 f->name_table[hash] = node;
225 return 0;
228 static void delete_node(struct fuse *f, struct node *node)
230 if (f->conf.debug)
231 fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid);
233 assert(!node->name);
234 unhash_id(f, node);
235 free_node(node);
238 static void unref_node(struct fuse *f, struct node *node)
240 assert(node->refctr > 0);
241 node->refctr --;
242 if (!node->refctr)
243 delete_node(f, node);
246 static fuse_ino_t next_id(struct fuse *f)
248 do {
249 f->ctr = (f->ctr + 1) & 0xffffffff;
250 if (!f->ctr)
251 f->generation ++;
252 } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
253 get_node_nocheck(f, f->ctr) != NULL);
254 return f->ctr;
257 static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
258 const char *name)
260 size_t hash = name_hash(f, parent, name);
261 struct node *node;
263 for (node = f->name_table[hash]; node != NULL; node = node->name_next)
264 if (node->parent->nodeid == parent && strcmp(node->name, name) == 0)
265 return node;
267 return NULL;
270 static struct node *find_node(struct fuse *f, fuse_ino_t parent,
271 const char *name)
273 struct node *node;
275 pthread_mutex_lock(&f->lock);
276 node = lookup_node(f, parent, name);
277 if (node == NULL) {
278 node = (struct node *) calloc(1, sizeof(struct node));
279 if (node == NULL)
280 goto out_err;
282 node->refctr = 1;
283 node->nodeid = next_id(f);
284 node->open_count = 0;
285 node->is_hidden = 0;
286 node->generation = f->generation;
287 if (hash_name(f, node, parent, name) == -1) {
288 free(node);
289 node = NULL;
290 goto out_err;
292 hash_id(f, node);
294 node->nlookup ++;
295 out_err:
296 pthread_mutex_unlock(&f->lock);
297 return node;
300 static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
302 size_t len = strlen(name);
304 if (s - len <= *buf) {
305 unsigned pathlen = *bufsize - (s - *buf);
306 unsigned newbufsize = *bufsize;
307 char *newbuf;
309 while (newbufsize < pathlen + len + 1) {
310 if (newbufsize >= 0x80000000)
311 newbufsize = 0xffffffff;
312 else
313 newbufsize *= 2;
316 newbuf = realloc(*buf, newbufsize);
317 if (newbuf == NULL)
318 return NULL;
320 *buf = newbuf;
321 s = newbuf + newbufsize - pathlen;
322 memmove(s, newbuf + *bufsize - pathlen, pathlen);
323 *bufsize = newbufsize;
325 s -= len;
326 strncpy(s, name, len);
327 s--;
328 *s = '/';
330 return s;
333 static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
335 unsigned bufsize = 256;
336 char *buf;
337 char *s;
338 struct node *node;
340 buf = malloc(bufsize);
341 if (buf == NULL)
342 return NULL;
344 s = buf + bufsize - 1;
345 *s = '\0';
347 if (name != NULL) {
348 s = add_name(&buf, &bufsize, s, name);
349 if (s == NULL)
350 goto out_free;
353 pthread_mutex_lock(&f->lock);
354 for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
355 node = node->parent) {
356 if (node->name == NULL) {
357 s = NULL;
358 break;
361 s = add_name(&buf, &bufsize, s, node->name);
362 if (s == NULL)
363 break;
365 pthread_mutex_unlock(&f->lock);
367 if (node == NULL || s == NULL)
368 goto out_free;
370 if (s[0])
371 memmove(buf, s, bufsize - (s - buf));
372 else
373 strcpy(buf, "/");
374 return buf;
376 out_free:
377 free(buf);
378 return NULL;
381 static char *get_path(struct fuse *f, fuse_ino_t nodeid)
383 return get_path_name(f, nodeid, NULL);
386 static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
388 struct node *node;
389 if (nodeid == FUSE_ROOT_ID)
390 return;
391 pthread_mutex_lock(&f->lock);
392 node = get_node(f, nodeid);
393 assert(node->nlookup >= nlookup);
394 node->nlookup -= nlookup;
395 if (!node->nlookup) {
396 unhash_name(f, node);
397 unref_node(f, node);
399 pthread_mutex_unlock(&f->lock);
402 static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
404 struct node *node;
406 pthread_mutex_lock(&f->lock);
407 node = lookup_node(f, dir, name);
408 if (node != NULL)
409 unhash_name(f, node);
410 pthread_mutex_unlock(&f->lock);
413 static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
414 fuse_ino_t newdir, const char *newname, int hide)
416 struct node *node;
417 struct node *newnode;
418 int err = 0;
420 pthread_mutex_lock(&f->lock);
421 node = lookup_node(f, olddir, oldname);
422 newnode = lookup_node(f, newdir, newname);
423 if (node == NULL)
424 goto out;
426 if (newnode != NULL) {
427 if (hide) {
428 fprintf(stderr, "fuse: hidden file got created during hiding\n");
429 err = -EBUSY;
430 goto out;
432 unhash_name(f, newnode);
435 unhash_name(f, node);
436 if (hash_name(f, node, newdir, newname) == -1) {
437 err = -ENOMEM;
438 goto out;
441 if (hide)
442 node->is_hidden = 1;
444 out:
445 pthread_mutex_unlock(&f->lock);
446 return err;
449 static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
451 if (!f->conf.use_ino)
452 stbuf->st_ino = nodeid;
453 if (f->conf.set_mode)
454 stbuf->st_mode = (stbuf->st_mode & S_IFMT) | (0777 & ~f->conf.umask);
455 if (f->conf.set_uid)
456 stbuf->st_uid = f->conf.uid;
457 if (f->conf.set_gid)
458 stbuf->st_gid = f->conf.gid;
461 static struct fuse *req_fuse(fuse_req_t req)
463 return (struct fuse *) fuse_req_userdata(req);
466 static void fuse_intr_sighandler(int sig)
468 (void) sig;
469 /* Nothing to do */
472 struct fuse_intr_data {
473 pthread_t id;
474 pthread_cond_t cond;
475 int finished;
478 static void fuse_interrupt(fuse_req_t req, void *d_)
480 struct fuse_intr_data *d = d_;
481 struct fuse *f = req_fuse(req);
483 if (d->id == pthread_self())
484 return;
486 pthread_mutex_lock(&f->lock);
487 while (!d->finished) {
488 struct timeval now;
489 struct timespec timeout;
491 pthread_kill(d->id, f->conf.intr_signal);
492 gettimeofday(&now, NULL);
493 timeout.tv_sec = now.tv_sec + 1;
494 timeout.tv_nsec = now.tv_usec * 1000;
495 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
497 pthread_mutex_unlock(&f->lock);
500 static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
501 struct fuse_intr_data *d)
503 pthread_mutex_lock(&f->lock);
504 d->finished = 1;
505 pthread_cond_broadcast(&d->cond);
506 pthread_mutex_unlock(&f->lock);
507 fuse_req_interrupt_func(req, NULL, NULL);
508 pthread_cond_destroy(&d->cond);
511 static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
513 d->id = pthread_self();
514 pthread_cond_init(&d->cond, NULL);
515 d->finished = 0;
516 fuse_req_interrupt_func(req, fuse_interrupt, d);
519 static void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
520 struct fuse_intr_data *d)
522 if (f->conf.intr)
523 fuse_do_finish_interrupt(f, req, d);
526 static void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
527 struct fuse_intr_data *d)
529 if (f->conf.intr)
530 fuse_do_prepare_interrupt(req, d);
533 int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
535 fuse_get_context()->private_data = fs->user_data;
536 if (fs->op.getattr)
537 return fs->op.getattr(path, buf);
538 else
539 return -ENOSYS;
542 int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
543 struct fuse_file_info *fi)
545 fuse_get_context()->private_data = fs->user_data;
546 if (fs->op.fgetattr)
547 return fs->op.fgetattr(path, buf, fi);
548 else if (fs->op.getattr)
549 return fs->op.getattr(path, buf);
550 else
551 return -ENOSYS;
554 int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
555 const char *newpath)
557 fuse_get_context()->private_data = fs->user_data;
558 if (fs->op.rename)
559 return fs->op.rename(oldpath, newpath);
560 else
561 return -ENOSYS;
564 int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
566 fuse_get_context()->private_data = fs->user_data;
567 if (fs->op.unlink)
568 return fs->op.unlink(path);
569 else
570 return -ENOSYS;
573 int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
575 fuse_get_context()->private_data = fs->user_data;
576 if (fs->op.rmdir)
577 return fs->op.rmdir(path);
578 else
579 return -ENOSYS;
582 int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
584 fuse_get_context()->private_data = fs->user_data;
585 if (fs->op.symlink)
586 return fs->op.symlink(linkname, path);
587 else
588 return -ENOSYS;
591 int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
593 fuse_get_context()->private_data = fs->user_data;
594 if (fs->op.link)
595 return fs->op.link(oldpath, newpath);
596 else
597 return -ENOSYS;
600 int fuse_fs_release(struct fuse_fs *fs, const char *path,
601 struct fuse_file_info *fi)
603 fuse_get_context()->private_data = fs->user_data;
604 if (fs->op.release)
605 return fs->op.release(path, fi);
606 else
607 return 0;
610 int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
611 struct fuse_file_info *fi)
613 fuse_get_context()->private_data = fs->user_data;
614 if (fs->op.opendir)
615 return fs->op.opendir(path, fi);
616 else
617 return 0;
620 int fuse_fs_open(struct fuse_fs *fs, const char *path,
621 struct fuse_file_info *fi)
623 fuse_get_context()->private_data = fs->user_data;
624 if (fs->op.open)
625 return fs->op.open(path, fi);
626 else
627 return 0;
630 int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
631 off_t off, struct fuse_file_info *fi)
633 fuse_get_context()->private_data = fs->user_data;
634 if (fs->op.read)
635 return fs->op.read(path, buf, size, off, fi);
636 else
637 return -ENOSYS;
640 int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf,
641 size_t size, off_t off, struct fuse_file_info *fi)
643 fuse_get_context()->private_data = fs->user_data;
644 if (fs->op.write)
645 return fs->op.write(path, buf, size, off, fi);
646 else
647 return -ENOSYS;
650 int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
651 struct fuse_file_info *fi)
653 fuse_get_context()->private_data = fs->user_data;
654 if (fs->op.fsync)
655 return fs->op.fsync(path, datasync, fi);
656 else
657 return -ENOSYS;
660 int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
661 struct fuse_file_info *fi)
663 fuse_get_context()->private_data = fs->user_data;
664 if (fs->op.fsyncdir)
665 return fs->op.fsyncdir(path, datasync, fi);
666 else
667 return -ENOSYS;
670 int fuse_fs_flush(struct fuse_fs *fs, const char *path,
671 struct fuse_file_info *fi)
673 fuse_get_context()->private_data = fs->user_data;
674 if (fs->op.flush)
675 return fs->op.flush(path, fi);
676 else
677 return -ENOSYS;
680 int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
682 fuse_get_context()->private_data = fs->user_data;
683 if (fs->op.statfs)
684 return fs->op.statfs(path, buf);
685 else {
686 buf->f_namemax = 255;
687 buf->f_bsize = 512;
688 return 0;
692 int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
693 struct fuse_file_info *fi)
695 fuse_get_context()->private_data = fs->user_data;
696 if (fs->op.releasedir)
697 return fs->op.releasedir(path, fi);
698 else
699 return 0;
702 int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
703 fuse_fill_dir_t filler, off_t off,
704 struct fuse_file_info *fi)
706 fuse_get_context()->private_data = fs->user_data;
707 if (fs->op.readdir)
708 return fs->op.readdir(path, buf, filler, off, fi);
709 else
710 return -ENOSYS;
713 int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
714 struct fuse_file_info *fi)
716 fuse_get_context()->private_data = fs->user_data;
717 if (fs->op.create)
718 return fs->op.create(path, mode, fi);
719 else
720 return -ENOSYS;
723 int fuse_fs_lock(struct fuse_fs *fs, const char *path,
724 struct fuse_file_info *fi, int cmd, struct flock *lock)
726 fuse_get_context()->private_data = fs->user_data;
727 if (fs->op.lock)
728 return fs->op.lock(path, fi, cmd, lock);
729 else
730 return -ENOSYS;
733 int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
735 fuse_get_context()->private_data = fs->user_data;
736 if (fs->op.chown)
737 return fs->op.chown(path, uid, gid);
738 else
739 return -ENOSYS;
742 int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
744 fuse_get_context()->private_data = fs->user_data;
745 if (fs->op.truncate)
746 return fs->op.truncate(path, size);
747 else
748 return -ENOSYS;
751 int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
752 struct fuse_file_info *fi)
754 fuse_get_context()->private_data = fs->user_data;
755 if (fs->op.ftruncate)
756 return fs->op.ftruncate(path, size, fi);
757 else if (fs->op.truncate)
758 return fs->op.truncate(path, size);
759 else
760 return -ENOSYS;
763 int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
764 const struct timespec tv[2])
766 fuse_get_context()->private_data = fs->user_data;
767 if (fs->op.utimens)
768 return fs->op.utimens(path, tv);
769 else if(fs->op.utime) {
770 struct utimbuf buf;
771 buf.actime = tv[0].tv_sec;
772 buf.modtime = tv[1].tv_sec;
773 return fs->op.utime(path, &buf);
774 } else
775 return -ENOSYS;
778 int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
780 fuse_get_context()->private_data = fs->user_data;
781 if (fs->op.access)
782 return fs->op.access(path, mask);
783 else
784 return -ENOSYS;
787 int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
788 size_t len)
790 fuse_get_context()->private_data = fs->user_data;
791 if (fs->op.readlink)
792 return fs->op.readlink(path, buf, len);
793 else
794 return -ENOSYS;
797 int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
798 dev_t rdev)
800 fuse_get_context()->private_data = fs->user_data;
801 if (fs->op.mknod)
802 return fs->op.mknod(path, mode, rdev);
803 else
804 return -ENOSYS;
807 int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
809 fuse_get_context()->private_data = fs->user_data;
810 if (fs->op.mkdir)
811 return fs->op.mkdir(path, mode);
812 else
813 return -ENOSYS;
816 int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
817 const char *value, size_t size, int flags)
819 fuse_get_context()->private_data = fs->user_data;
820 if (fs->op.setxattr)
821 return fs->op.setxattr(path, name, value, size, flags);
822 else
823 return -ENOSYS;
826 int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
827 char *value, size_t size)
829 fuse_get_context()->private_data = fs->user_data;
830 if (fs->op.getxattr)
831 return fs->op.getxattr(path, name, value, size);
832 else
833 return -ENOSYS;
836 int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
837 size_t size)
839 fuse_get_context()->private_data = fs->user_data;
840 if (fs->op.listxattr)
841 return fs->op.listxattr(path, list, size);
842 else
843 return -ENOSYS;
846 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
847 uint64_t *idx)
849 fuse_get_context()->private_data = fs->user_data;
850 if (fs->op.bmap)
851 return fs->op.bmap(path, blocksize, idx);
852 else
853 return -ENOSYS;
856 int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
858 fuse_get_context()->private_data = fs->user_data;
859 if (fs->op.removexattr)
860 return fs->op.removexattr(path, name);
861 else
862 return -ENOSYS;
865 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
867 struct node *node;
868 int isopen = 0;
869 pthread_mutex_lock(&f->lock);
870 node = lookup_node(f, dir, name);
871 if (node && node->open_count > 0)
872 isopen = 1;
873 pthread_mutex_unlock(&f->lock);
874 return isopen;
877 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
878 char *newname, size_t bufsize)
880 struct stat buf;
881 struct node *node;
882 struct node *newnode;
883 char *newpath;
884 int res;
885 int failctr = 10;
887 do {
888 pthread_mutex_lock(&f->lock);
889 node = lookup_node(f, dir, oldname);
890 if (node == NULL) {
891 pthread_mutex_unlock(&f->lock);
892 return NULL;
894 do {
895 f->hidectr ++;
896 snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
897 (unsigned int) node->nodeid, f->hidectr);
898 newnode = lookup_node(f, dir, newname);
899 } while(newnode);
900 pthread_mutex_unlock(&f->lock);
902 newpath = get_path_name(f, dir, newname);
903 if (!newpath)
904 break;
906 res = fuse_fs_getattr(f->fs, newpath, &buf);
907 if (res == -ENOENT)
908 break;
909 free(newpath);
910 newpath = NULL;
911 } while(res == 0 && --failctr);
913 return newpath;
916 static int hide_node(struct fuse *f, const char *oldpath,
917 fuse_ino_t dir, const char *oldname)
919 char newname[64];
920 char *newpath;
921 int err = -EBUSY;
923 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
924 if (newpath) {
925 err = fuse_fs_rename(f->fs, oldpath, newpath);
926 if (!err)
927 err = rename_node(f, dir, oldname, dir, newname, 1);
928 free(newpath);
930 return err;
933 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
934 const char *name, const char *path,
935 struct fuse_entry_param *e, struct fuse_file_info *fi)
937 int res;
939 memset(e, 0, sizeof(struct fuse_entry_param));
940 if (fi)
941 res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
942 else
943 res = fuse_fs_getattr(f->fs, path, &e->attr);
944 if (res == 0) {
945 struct node *node;
947 node = find_node(f, nodeid, name);
948 if (node == NULL)
949 res = -ENOMEM;
950 else {
951 e->ino = node->nodeid;
952 e->generation = node->generation;
953 e->entry_timeout = f->conf.entry_timeout;
954 e->attr_timeout = f->conf.attr_timeout;
955 set_stat(f, e->ino, &e->attr);
956 if (f->conf.debug)
957 fprintf(stderr, " NODEID: %lu\n", (unsigned long) e->ino);
960 return res;
963 static struct fuse_context_i *fuse_get_context_internal(void)
965 struct fuse_context_i *c;
967 c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
968 if (c == NULL) {
969 c = (struct fuse_context_i *) malloc(sizeof(struct fuse_context_i));
970 if (c == NULL) {
971 /* This is hard to deal with properly, so just abort. If
972 memory is so low that the context cannot be allocated,
973 there's not much hope for the filesystem anyway */
974 fprintf(stderr, "fuse: failed to allocate thread specific data\n");
975 abort();
977 pthread_setspecific(fuse_context_key, c);
979 return c;
982 static void fuse_freecontext(void *data)
984 free(data);
987 static int fuse_create_context_key(void)
989 int err = 0;
990 pthread_mutex_lock(&fuse_context_lock);
991 if (!fuse_context_ref) {
992 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
993 if (err) {
994 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
995 strerror(err));
996 pthread_mutex_unlock(&fuse_context_lock);
997 return -1;
1000 fuse_context_ref++;
1001 pthread_mutex_unlock(&fuse_context_lock);
1002 return 0;
1005 static void fuse_delete_context_key(void)
1007 pthread_mutex_lock(&fuse_context_lock);
1008 fuse_context_ref--;
1009 if (!fuse_context_ref) {
1010 free(pthread_getspecific(fuse_context_key));
1011 pthread_key_delete(fuse_context_key);
1013 pthread_mutex_unlock(&fuse_context_lock);
1016 static struct fuse *req_fuse_prepare(fuse_req_t req)
1018 struct fuse_context_i *c = fuse_get_context_internal();
1019 const struct fuse_ctx *ctx = fuse_req_ctx(req);
1020 c->req = req;
1021 c->ctx.fuse = req_fuse(req);
1022 c->ctx.uid = ctx->uid;
1023 c->ctx.gid = ctx->gid;
1024 c->ctx.pid = ctx->pid;
1025 #ifdef POSIXACLS
1026 c->ctx.umask = ctx->umask;
1027 #endif
1028 return c->ctx.fuse;
1031 static void reply_err(fuse_req_t req, int err)
1033 /* fuse_reply_err() uses non-negated errno values */
1034 fuse_reply_err(req, -err);
1037 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
1038 int err)
1040 if (!err) {
1041 struct fuse *f = req_fuse(req);
1042 if (fuse_reply_entry(req, e) == -ENOENT)
1043 forget_node(f, e->ino, 1);
1044 } else
1045 reply_err(req, err);
1048 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
1050 fuse_get_context()->private_data = fs->user_data;
1051 if (fs->op.init)
1052 fs->user_data = fs->op.init(conn);
1055 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
1057 struct fuse *f = (struct fuse *) data;
1058 struct fuse_context_i *c = fuse_get_context_internal();
1060 memset(c, 0, sizeof(*c));
1061 c->ctx.fuse = f;
1062 fuse_fs_init(f->fs, conn);
1065 void fuse_fs_destroy(struct fuse_fs *fs)
1067 fuse_get_context()->private_data = fs->user_data;
1068 if (fs->op.destroy)
1069 fs->op.destroy(fs->user_data);
1070 free(fs);
1073 static void fuse_lib_destroy(void *data)
1075 struct fuse *f = (struct fuse *) data;
1076 struct fuse_context_i *c = fuse_get_context_internal();
1078 memset(c, 0, sizeof(*c));
1079 c->ctx.fuse = f;
1080 fuse_fs_destroy(f->fs);
1081 f->fs = NULL;
1084 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
1085 const char *name)
1087 struct fuse *f = req_fuse_prepare(req);
1088 struct fuse_entry_param e;
1089 char *path;
1090 int err;
1092 err = -ENOENT;
1093 pthread_rwlock_rdlock(&f->tree_lock);
1094 path = get_path_name(f, parent, name);
1095 if (path != NULL) {
1096 struct fuse_intr_data d;
1097 if (f->conf.debug)
1098 fprintf(stderr, "LOOKUP %s\n", path);
1099 fuse_prepare_interrupt(f, req, &d);
1100 err = lookup_path(f, parent, name, path, &e, NULL);
1101 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
1102 e.ino = 0;
1103 e.entry_timeout = f->conf.negative_timeout;
1104 err = 0;
1106 fuse_finish_interrupt(f, req, &d);
1107 free(path);
1109 pthread_rwlock_unlock(&f->tree_lock);
1110 reply_entry(req, &e, err);
1113 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
1114 unsigned long nlookup)
1116 struct fuse *f = req_fuse(req);
1117 if (f->conf.debug)
1118 fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino, nlookup);
1119 forget_node(f, ino, nlookup);
1120 fuse_reply_none(req);
1123 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
1124 struct fuse_file_info *fi)
1126 struct fuse *f = req_fuse_prepare(req);
1127 struct stat buf;
1128 char *path;
1129 int err;
1131 (void) fi;
1132 memset(&buf, 0, sizeof(buf));
1134 err = -ENOENT;
1135 pthread_rwlock_rdlock(&f->tree_lock);
1136 path = get_path(f, ino);
1137 if (path != NULL) {
1138 struct fuse_intr_data d;
1139 fuse_prepare_interrupt(f, req, &d);
1140 err = fuse_fs_getattr(f->fs, path, &buf);
1141 fuse_finish_interrupt(f, req, &d);
1142 free(path);
1144 pthread_rwlock_unlock(&f->tree_lock);
1145 if (!err) {
1146 set_stat(f, ino, &buf);
1147 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
1148 } else
1149 reply_err(req, err);
1152 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
1154 fuse_get_context()->private_data = fs->user_data;
1155 if (fs->op.chmod)
1156 return fs->op.chmod(path, mode);
1157 else
1158 return -ENOSYS;
1161 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
1162 int valid, struct fuse_file_info *fi)
1164 struct fuse *f = req_fuse_prepare(req);
1165 struct stat buf;
1166 char *path;
1167 int err;
1169 err = -ENOENT;
1170 pthread_rwlock_rdlock(&f->tree_lock);
1171 path = get_path(f, ino);
1172 if (path != NULL) {
1173 struct fuse_intr_data d;
1174 fuse_prepare_interrupt(f, req, &d);
1175 err = 0;
1176 if (!err && (valid & FUSE_SET_ATTR_MODE))
1177 err = fuse_fs_chmod(f->fs, path, attr->st_mode);
1178 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
1179 uid_t uid =
1180 (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1;
1181 gid_t gid =
1182 (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1;
1183 err = fuse_fs_chown(f->fs, path, uid, gid);
1185 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
1186 if (fi)
1187 err = fuse_fs_ftruncate(f->fs, path, attr->st_size, fi);
1188 else
1189 err = fuse_fs_truncate(f->fs, path, attr->st_size);
1191 #ifdef HAVE_UTIMENSAT
1192 if (!err && f->utime_omit_ok &&
1193 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
1194 struct timespec tv[2];
1196 tv[0].tv_sec = 0;
1197 tv[1].tv_sec = 0;
1198 tv[0].tv_nsec = UTIME_OMIT;
1199 tv[1].tv_nsec = UTIME_OMIT;
1201 if (valid & FUSE_SET_ATTR_ATIME_NOW)
1202 tv[0].tv_nsec = UTIME_NOW;
1203 else if (valid & FUSE_SET_ATTR_ATIME)
1204 tv[0] = attr->st_atim;
1206 if (valid & FUSE_SET_ATTR_MTIME_NOW)
1207 tv[1].tv_nsec = UTIME_NOW;
1208 else if (valid & FUSE_SET_ATTR_MTIME)
1209 tv[1] = attr->st_mtim;
1211 err = fuse_fs_utimens(f->fs, path, tv);
1212 } else
1213 #endif
1214 if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
1215 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
1216 struct timespec tv[2];
1217 tv[0].tv_sec = attr->st_atime;
1218 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
1219 tv[1].tv_sec = attr->st_mtime;
1220 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
1221 err = fuse_fs_utimens(f->fs, path, tv);
1223 if (!err)
1224 err = fuse_fs_getattr(f->fs, path, &buf);
1225 fuse_finish_interrupt(f, req, &d);
1226 free(path);
1228 pthread_rwlock_unlock(&f->tree_lock);
1229 if (!err) {
1230 set_stat(f, ino, &buf);
1231 fuse_reply_attr(req, &buf, f->conf.attr_timeout);
1232 } else
1233 reply_err(req, err);
1236 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
1238 struct fuse *f = req_fuse_prepare(req);
1239 char *path;
1240 int err;
1242 err = -ENOENT;
1243 pthread_rwlock_rdlock(&f->tree_lock);
1244 path = get_path(f, ino);
1245 if (path != NULL) {
1246 struct fuse_intr_data d;
1247 if (f->conf.debug)
1248 fprintf(stderr, "ACCESS %s 0%o\n", path, mask);
1249 fuse_prepare_interrupt(f, req, &d);
1250 err = fuse_fs_access(f->fs, path, mask);
1251 fuse_finish_interrupt(f, req, &d);
1252 free(path);
1254 pthread_rwlock_unlock(&f->tree_lock);
1255 reply_err(req, err);
1258 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
1260 struct fuse *f = req_fuse_prepare(req);
1261 char linkname[PATH_MAX + 1];
1262 char *path;
1263 int err;
1265 err = -ENOENT;
1266 pthread_rwlock_rdlock(&f->tree_lock);
1267 path = get_path(f, ino);
1268 if (path != NULL) {
1269 struct fuse_intr_data d;
1270 fuse_prepare_interrupt(f, req, &d);
1271 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
1272 fuse_finish_interrupt(f, req, &d);
1273 free(path);
1275 pthread_rwlock_unlock(&f->tree_lock);
1276 if (!err) {
1277 linkname[PATH_MAX] = '\0';
1278 fuse_reply_readlink(req, linkname);
1279 } else
1280 reply_err(req, err);
1283 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
1284 mode_t mode, dev_t rdev)
1286 struct fuse *f = req_fuse_prepare(req);
1287 struct fuse_entry_param e;
1288 char *path;
1289 int err;
1291 err = -ENOENT;
1292 pthread_rwlock_rdlock(&f->tree_lock);
1293 path = get_path_name(f, parent, name);
1294 if (path) {
1295 struct fuse_intr_data d;
1296 if (f->conf.debug)
1297 fprintf(stderr, "MKNOD %s\n", path);
1298 fuse_prepare_interrupt(f, req, &d);
1299 err = -ENOSYS;
1300 if (S_ISREG(mode)) {
1301 struct fuse_file_info fi;
1303 memset(&fi, 0, sizeof(fi));
1304 fi.flags = O_CREAT | O_EXCL | O_WRONLY;
1305 err = fuse_fs_create(f->fs, path, mode, &fi);
1306 if (!err) {
1307 err = lookup_path(f, parent, name, path, &e, &fi);
1308 fuse_fs_release(f->fs, path, &fi);
1311 if (err == -ENOSYS) {
1312 err = fuse_fs_mknod(f->fs, path, mode, rdev);
1313 if (!err)
1314 err = lookup_path(f, parent, name, path, &e, NULL);
1316 fuse_finish_interrupt(f, req, &d);
1317 free(path);
1319 pthread_rwlock_unlock(&f->tree_lock);
1320 reply_entry(req, &e, err);
1323 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
1324 mode_t mode)
1326 struct fuse *f = req_fuse_prepare(req);
1327 struct fuse_entry_param e;
1328 char *path;
1329 int err;
1331 err = -ENOENT;
1332 pthread_rwlock_rdlock(&f->tree_lock);
1333 path = get_path_name(f, parent, name);
1334 if (path != NULL) {
1335 struct fuse_intr_data d;
1336 if (f->conf.debug)
1337 fprintf(stderr, "MKDIR %s\n", path);
1338 fuse_prepare_interrupt(f, req, &d);
1339 err = fuse_fs_mkdir(f->fs, path, mode);
1340 if (!err)
1341 err = lookup_path(f, parent, name, path, &e, NULL);
1342 fuse_finish_interrupt(f, req, &d);
1343 free(path);
1345 pthread_rwlock_unlock(&f->tree_lock);
1346 reply_entry(req, &e, err);
1349 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
1350 const char *name)
1352 struct fuse *f = req_fuse_prepare(req);
1353 char *path;
1354 int err;
1356 err = -ENOENT;
1357 pthread_rwlock_wrlock(&f->tree_lock);
1358 path = get_path_name(f, parent, name);
1359 if (path != NULL) {
1360 struct fuse_intr_data d;
1361 if (f->conf.debug)
1362 fprintf(stderr, "UNLINK %s\n", path);
1363 fuse_prepare_interrupt(f, req, &d);
1364 if (!f->conf.hard_remove && is_open(f, parent, name))
1365 err = hide_node(f, path, parent, name);
1366 else {
1367 err = fuse_fs_unlink(f->fs, path);
1368 if (!err)
1369 remove_node(f, parent, name);
1371 fuse_finish_interrupt(f, req, &d);
1372 free(path);
1374 pthread_rwlock_unlock(&f->tree_lock);
1375 reply_err(req, err);
1378 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
1380 struct fuse *f = req_fuse_prepare(req);
1381 char *path;
1382 int err;
1384 err = -ENOENT;
1385 pthread_rwlock_wrlock(&f->tree_lock);
1386 path = get_path_name(f, parent, name);
1387 if (path != NULL) {
1388 struct fuse_intr_data d;
1389 if (f->conf.debug)
1390 fprintf(stderr, "RMDIR %s\n", path);
1391 fuse_prepare_interrupt(f, req, &d);
1392 err = fuse_fs_rmdir(f->fs, path);
1393 fuse_finish_interrupt(f, req, &d);
1394 if (!err)
1395 remove_node(f, parent, name);
1396 free(path);
1398 pthread_rwlock_unlock(&f->tree_lock);
1399 reply_err(req, err);
1402 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
1403 fuse_ino_t parent, const char *name)
1405 struct fuse *f = req_fuse_prepare(req);
1406 struct fuse_entry_param e;
1407 char *path;
1408 int err;
1410 err = -ENOENT;
1411 pthread_rwlock_rdlock(&f->tree_lock);
1412 path = get_path_name(f, parent, name);
1413 if (path != NULL) {
1414 struct fuse_intr_data d;
1415 if (f->conf.debug)
1416 fprintf(stderr, "SYMLINK %s\n", path);
1417 fuse_prepare_interrupt(f, req, &d);
1418 err = fuse_fs_symlink(f->fs, linkname, path);
1419 if (!err)
1420 err = lookup_path(f, parent, name, path, &e, NULL);
1421 fuse_finish_interrupt(f, req, &d);
1422 free(path);
1424 pthread_rwlock_unlock(&f->tree_lock);
1425 reply_entry(req, &e, err);
1428 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
1429 const char *oldname, fuse_ino_t newdir,
1430 const char *newname)
1432 struct fuse *f = req_fuse_prepare(req);
1433 char *oldpath;
1434 char *newpath;
1435 int err;
1437 err = -ENOENT;
1438 pthread_rwlock_wrlock(&f->tree_lock);
1439 oldpath = get_path_name(f, olddir, oldname);
1440 if (oldpath != NULL) {
1441 newpath = get_path_name(f, newdir, newname);
1442 if (newpath != NULL) {
1443 struct fuse_intr_data d;
1444 if (f->conf.debug)
1445 fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath);
1446 err = 0;
1447 fuse_prepare_interrupt(f, req, &d);
1448 if (!f->conf.hard_remove && is_open(f, newdir, newname))
1449 err = hide_node(f, newpath, newdir, newname);
1450 if (!err) {
1451 err = fuse_fs_rename(f->fs, oldpath, newpath);
1452 if (!err)
1453 err = rename_node(f, olddir, oldname, newdir, newname, 0);
1455 fuse_finish_interrupt(f, req, &d);
1456 free(newpath);
1458 free(oldpath);
1460 pthread_rwlock_unlock(&f->tree_lock);
1461 reply_err(req, err);
1464 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
1465 const char *newname)
1467 struct fuse *f = req_fuse_prepare(req);
1468 struct fuse_entry_param e;
1469 char *oldpath;
1470 char *newpath;
1471 int err;
1473 err = -ENOENT;
1474 pthread_rwlock_rdlock(&f->tree_lock);
1475 oldpath = get_path(f, ino);
1476 if (oldpath != NULL) {
1477 newpath = get_path_name(f, newparent, newname);
1478 if (newpath != NULL) {
1479 struct fuse_intr_data d;
1480 if (f->conf.debug)
1481 fprintf(stderr, "LINK %s\n", newpath);
1482 fuse_prepare_interrupt(f, req, &d);
1483 err = fuse_fs_link(f->fs, oldpath, newpath);
1484 if (!err)
1485 err = lookup_path(f, newparent, newname, newpath, &e, NULL);
1486 fuse_finish_interrupt(f, req, &d);
1487 free(newpath);
1489 free(oldpath);
1491 pthread_rwlock_unlock(&f->tree_lock);
1492 reply_entry(req, &e, err);
1495 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
1496 struct fuse_file_info *fi)
1498 struct node *node;
1499 int unlink_hidden = 0;
1501 fuse_fs_release(f->fs, path ? path : "-", fi);
1503 pthread_mutex_lock(&f->lock);
1504 node = get_node(f, ino);
1505 assert(node->open_count > 0);
1506 --node->open_count;
1507 if (node->is_hidden && !node->open_count) {
1508 unlink_hidden = 1;
1509 node->is_hidden = 0;
1511 pthread_mutex_unlock(&f->lock);
1513 if(unlink_hidden && path)
1514 fuse_fs_unlink(f->fs, path);
1517 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
1518 const char *name, mode_t mode,
1519 struct fuse_file_info *fi)
1521 struct fuse *f = req_fuse_prepare(req);
1522 struct fuse_intr_data d;
1523 struct fuse_entry_param e;
1524 char *path;
1525 int err;
1527 err = -ENOENT;
1528 pthread_rwlock_rdlock(&f->tree_lock);
1529 path = get_path_name(f, parent, name);
1530 if (path) {
1531 fuse_prepare_interrupt(f, req, &d);
1532 err = fuse_fs_create(f->fs, path, mode, fi);
1533 if (!err) {
1534 err = lookup_path(f, parent, name, path, &e, fi);
1535 if (err)
1536 fuse_fs_release(f->fs, path, fi);
1537 else if (!S_ISREG(e.attr.st_mode)) {
1538 err = -EIO;
1539 fuse_fs_release(f->fs, path, fi);
1540 forget_node(f, e.ino, 1);
1541 } else {
1542 if (f->conf.direct_io)
1543 fi->direct_io = 1;
1544 if (f->conf.kernel_cache)
1545 fi->keep_cache = 1;
1549 fuse_finish_interrupt(f, req, &d);
1551 if (!err) {
1552 pthread_mutex_lock(&f->lock);
1553 get_node(f, e.ino)->open_count++;
1554 pthread_mutex_unlock(&f->lock);
1555 if (fuse_reply_create(req, &e, fi) == -ENOENT) {
1556 /* The open syscall was interrupted, so it must be cancelled */
1557 fuse_prepare_interrupt(f, req, &d);
1558 fuse_do_release(f, e.ino, path, fi);
1559 fuse_finish_interrupt(f, req, &d);
1560 forget_node(f, e.ino, 1);
1561 } else if (f->conf.debug) {
1562 fprintf(stderr, " CREATE[%llu] flags: 0x%x %s\n",
1563 (unsigned long long) fi->fh, fi->flags, path);
1565 } else
1566 reply_err(req, err);
1568 if (path)
1569 free(path);
1571 pthread_rwlock_unlock(&f->tree_lock);
1574 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
1575 struct fuse_file_info *fi)
1577 struct fuse *f = req_fuse_prepare(req);
1578 struct fuse_intr_data d;
1579 char *path = NULL;
1580 int err = 0;
1582 err = -ENOENT;
1583 pthread_rwlock_rdlock(&f->tree_lock);
1584 path = get_path(f, ino);
1585 if (path) {
1586 fuse_prepare_interrupt(f, req, &d);
1587 err = fuse_fs_open(f->fs, path, fi);
1588 if (!err) {
1589 if (f->conf.direct_io)
1590 fi->direct_io = 1;
1591 if (f->conf.kernel_cache)
1592 fi->keep_cache = 1;
1594 fuse_finish_interrupt(f, req, &d);
1596 if (!err) {
1597 pthread_mutex_lock(&f->lock);
1598 get_node(f, ino)->open_count++;
1599 pthread_mutex_unlock(&f->lock);
1600 if (fuse_reply_open(req, fi) == -ENOENT) {
1601 /* The open syscall was interrupted, so it must be cancelled */
1602 fuse_prepare_interrupt(f, req, &d);
1603 fuse_do_release(f, ino, path, fi);
1604 fuse_finish_interrupt(f, req, &d);
1605 } else if (f->conf.debug) {
1606 fprintf(stderr, "OPEN[%llu] flags: 0x%x %s\n",
1607 (unsigned long long) fi->fh, fi->flags, path);
1609 } else
1610 reply_err(req, err);
1612 if (path)
1613 free(path);
1614 pthread_rwlock_unlock(&f->tree_lock);
1617 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
1618 off_t off, struct fuse_file_info *fi)
1620 struct fuse *f = req_fuse_prepare(req);
1621 char *path;
1622 char *buf;
1623 int res;
1625 buf = (char *) malloc(size);
1626 if (buf == NULL) {
1627 reply_err(req, -ENOMEM);
1628 return;
1631 res = -ENOENT;
1632 pthread_rwlock_rdlock(&f->tree_lock);
1633 path = get_path(f, ino);
1634 if (path != NULL) {
1635 struct fuse_intr_data d;
1636 if (f->conf.debug)
1637 fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",
1638 (unsigned long long) fi->fh, (unsigned long) size,
1639 (unsigned long long) off);
1641 fuse_prepare_interrupt(f, req, &d);
1642 res = fuse_fs_read(f->fs, path, buf, size, off, fi);
1643 fuse_finish_interrupt(f, req, &d);
1644 free(path);
1646 pthread_rwlock_unlock(&f->tree_lock);
1648 if (res >= 0) {
1649 if (f->conf.debug)
1650 fprintf(stderr, " READ[%llu] %u bytes\n",
1651 (unsigned long long)fi->fh, res);
1652 if ((size_t) res > size)
1653 fprintf(stderr, "fuse: read too many bytes");
1654 fuse_reply_buf(req, buf, res);
1655 } else
1656 reply_err(req, res);
1658 free(buf);
1661 static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
1662 size_t size, off_t off, struct fuse_file_info *fi)
1664 struct fuse *f = req_fuse_prepare(req);
1665 char *path;
1666 int res;
1668 res = -ENOENT;
1669 pthread_rwlock_rdlock(&f->tree_lock);
1670 path = get_path(f, ino);
1671 if (path != NULL) {
1672 struct fuse_intr_data d;
1673 if (f->conf.debug)
1674 fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n",
1675 fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
1676 (unsigned long) size, (unsigned long long) off);
1678 fuse_prepare_interrupt(f, req, &d);
1679 res = fuse_fs_write(f->fs, path, buf, size, off, fi);
1680 fuse_finish_interrupt(f, req, &d);
1681 free(path);
1683 pthread_rwlock_unlock(&f->tree_lock);
1685 if (res >= 0) {
1686 if (f->conf.debug)
1687 fprintf(stderr, " WRITE%s[%llu] %u bytes\n",
1688 fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
1689 res);
1690 if ((size_t) res > size)
1691 fprintf(stderr, "fuse: wrote too many bytes");
1692 fuse_reply_write(req, res);
1693 } else
1694 reply_err(req, res);
1697 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
1698 struct fuse_file_info *fi)
1700 struct fuse *f = req_fuse_prepare(req);
1701 char *path;
1702 int err;
1704 err = -ENOENT;
1705 pthread_rwlock_rdlock(&f->tree_lock);
1706 path = get_path(f, ino);
1707 if (path != NULL) {
1708 struct fuse_intr_data d;
1709 if (f->conf.debug)
1710 fprintf(stderr, "FSYNC[%llu]\n", (unsigned long long) fi->fh);
1711 fuse_prepare_interrupt(f, req, &d);
1712 err = fuse_fs_fsync(f->fs, path, datasync, fi);
1713 fuse_finish_interrupt(f, req, &d);
1714 free(path);
1716 pthread_rwlock_unlock(&f->tree_lock);
1717 reply_err(req, err);
1720 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
1721 struct fuse_file_info *fi)
1723 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
1724 memset(fi, 0, sizeof(struct fuse_file_info));
1725 fi->fh = dh->fh;
1726 fi->fh_old = dh->fh;
1727 return dh;
1730 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
1731 struct fuse_file_info *llfi)
1733 struct fuse *f = req_fuse_prepare(req);
1734 struct fuse_intr_data d;
1735 struct fuse_dh *dh;
1736 struct fuse_file_info fi;
1737 char *path;
1738 int err;
1740 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
1741 if (dh == NULL) {
1742 reply_err(req, -ENOMEM);
1743 return;
1745 memset(dh, 0, sizeof(struct fuse_dh));
1746 dh->fuse = f;
1747 dh->contents = NULL;
1748 dh->len = 0;
1749 dh->filled = 0;
1750 dh->nodeid = ino;
1751 fuse_mutex_init(&dh->lock);
1753 llfi->fh = (uintptr_t) dh;
1755 memset(&fi, 0, sizeof(fi));
1756 fi.flags = llfi->flags;
1758 err = -ENOENT;
1759 pthread_rwlock_rdlock(&f->tree_lock);
1760 path = get_path(f, ino);
1761 if (path != NULL) {
1762 fuse_prepare_interrupt(f, req, &d);
1763 err = fuse_fs_opendir(f->fs, path, &fi);
1764 fuse_finish_interrupt(f, req, &d);
1765 dh->fh = fi.fh;
1767 if (!err) {
1768 if (fuse_reply_open(req, llfi) == -ENOENT) {
1769 /* The opendir syscall was interrupted, so it must be cancelled */
1770 fuse_prepare_interrupt(f, req, &d);
1771 fuse_fs_releasedir(f->fs, path, &fi);
1772 fuse_finish_interrupt(f, req, &d);
1773 pthread_mutex_destroy(&dh->lock);
1774 free(dh);
1776 } else {
1777 reply_err(req, err);
1778 pthread_mutex_destroy(&dh->lock);
1779 free(dh);
1781 free(path);
1782 pthread_rwlock_unlock(&f->tree_lock);
1785 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
1787 if (minsize > dh->size) {
1788 char *newptr;
1789 unsigned newsize = dh->size;
1790 if (!newsize)
1791 newsize = 1024;
1792 while (newsize < minsize) {
1793 if (newsize >= 0x80000000)
1794 newsize = 0xffffffff;
1795 else
1796 newsize *= 2;
1799 newptr = (char *) realloc(dh->contents, newsize);
1800 if (!newptr) {
1801 dh->error = -ENOMEM;
1802 return -1;
1804 dh->contents = newptr;
1805 dh->size = newsize;
1807 return 0;
1810 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
1811 off_t off)
1813 struct fuse_dh *dh = (struct fuse_dh *) dh_;
1814 struct stat stbuf;
1815 size_t newlen;
1817 if (statp)
1818 stbuf = *statp;
1819 else {
1820 memset(&stbuf, 0, sizeof(stbuf));
1821 stbuf.st_ino = FUSE_UNKNOWN_INO;
1824 if (!dh->fuse->conf.use_ino) {
1825 stbuf.st_ino = FUSE_UNKNOWN_INO;
1826 if (dh->fuse->conf.readdir_ino) {
1827 struct node *node;
1828 pthread_mutex_lock(&dh->fuse->lock);
1829 node = lookup_node(dh->fuse, dh->nodeid, name);
1830 if (node)
1831 stbuf.st_ino = (ino_t) node->nodeid;
1832 pthread_mutex_unlock(&dh->fuse->lock);
1836 if (off) {
1837 if (extend_contents(dh, dh->needlen) == -1)
1838 return 1;
1840 dh->filled = 0;
1841 newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len,
1842 dh->needlen - dh->len, name,
1843 &stbuf, off);
1844 if (newlen > dh->needlen)
1845 return 1;
1846 } else {
1847 newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
1848 if (extend_contents(dh, newlen) == -1)
1849 return 1;
1851 fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len,
1852 name, &stbuf, newlen);
1854 dh->len = newlen;
1855 return 0;
1858 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
1859 size_t size, off_t off, struct fuse_dh *dh,
1860 struct fuse_file_info *fi)
1862 int err = -ENOENT;
1863 char *path;
1864 pthread_rwlock_rdlock(&f->tree_lock);
1865 path = get_path(f, ino);
1866 if (path != NULL) {
1867 struct fuse_intr_data d;
1869 dh->len = 0;
1870 dh->error = 0;
1871 dh->needlen = size;
1872 dh->filled = 1;
1873 dh->req = req;
1874 fuse_prepare_interrupt(f, req, &d);
1875 err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
1876 fuse_finish_interrupt(f, req, &d);
1877 dh->req = NULL;
1878 if (!err)
1879 err = dh->error;
1880 if (err)
1881 dh->filled = 0;
1882 free(path);
1884 pthread_rwlock_unlock(&f->tree_lock);
1885 return err;
1888 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
1889 off_t off, struct fuse_file_info *llfi)
1891 struct fuse *f = req_fuse_prepare(req);
1892 struct fuse_file_info fi;
1893 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
1895 pthread_mutex_lock(&dh->lock);
1896 /* According to SUS, directory contents need to be refreshed on
1897 rewinddir() */
1898 if (!off)
1899 dh->filled = 0;
1901 if (!dh->filled) {
1902 int err = readdir_fill(f, req, ino, size, off, dh, &fi);
1903 if (err) {
1904 reply_err(req, err);
1905 goto out;
1908 if (dh->filled) {
1909 if (off < dh->len) {
1910 if (off + size > dh->len)
1911 size = dh->len - off;
1912 } else
1913 size = 0;
1914 } else {
1915 size = dh->len;
1916 off = 0;
1918 fuse_reply_buf(req, dh->contents + off, size);
1919 out:
1920 pthread_mutex_unlock(&dh->lock);
1923 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
1924 struct fuse_file_info *llfi)
1926 struct fuse *f = req_fuse_prepare(req);
1927 struct fuse_intr_data d;
1928 struct fuse_file_info fi;
1929 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
1930 char *path;
1932 pthread_rwlock_rdlock(&f->tree_lock);
1933 path = get_path(f, ino);
1934 fuse_prepare_interrupt(f, req, &d);
1935 fuse_fs_releasedir(f->fs, path ? path : "-", &fi);
1936 fuse_finish_interrupt(f, req, &d);
1937 if (path)
1938 free(path);
1939 pthread_rwlock_unlock(&f->tree_lock);
1940 pthread_mutex_lock(&dh->lock);
1941 pthread_mutex_unlock(&dh->lock);
1942 pthread_mutex_destroy(&dh->lock);
1943 free(dh->contents);
1944 free(dh);
1945 reply_err(req, 0);
1948 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
1949 struct fuse_file_info *llfi)
1951 struct fuse *f = req_fuse_prepare(req);
1952 struct fuse_file_info fi;
1953 char *path;
1954 int err;
1956 get_dirhandle(llfi, &fi);
1958 err = -ENOENT;
1959 pthread_rwlock_rdlock(&f->tree_lock);
1960 path = get_path(f, ino);
1961 if (path != NULL) {
1962 struct fuse_intr_data d;
1963 fuse_prepare_interrupt(f, req, &d);
1964 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
1965 fuse_finish_interrupt(f, req, &d);
1966 free(path);
1968 pthread_rwlock_unlock(&f->tree_lock);
1969 reply_err(req, err);
1972 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
1974 struct fuse *f = req_fuse_prepare(req);
1975 struct statvfs buf;
1976 char *path;
1977 int err;
1979 memset(&buf, 0, sizeof(buf));
1980 pthread_rwlock_rdlock(&f->tree_lock);
1981 if (!ino) {
1982 err = -ENOMEM;
1983 path = strdup("/");
1984 } else {
1985 err = -ENOENT;
1986 path = get_path(f, ino);
1988 if (path) {
1989 struct fuse_intr_data d;
1990 fuse_prepare_interrupt(f, req, &d);
1991 err = fuse_fs_statfs(f->fs, path, &buf);
1992 fuse_finish_interrupt(f, req, &d);
1993 free(path);
1995 pthread_rwlock_unlock(&f->tree_lock);
1997 if (!err)
1998 fuse_reply_statfs(req, &buf);
1999 else
2000 reply_err(req, err);
2003 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
2004 const char *value, size_t size, int flags)
2006 struct fuse *f = req_fuse_prepare(req);
2007 char *path;
2008 int err;
2010 err = -ENOENT;
2011 pthread_rwlock_rdlock(&f->tree_lock);
2012 path = get_path(f, ino);
2013 if (path != NULL) {
2014 struct fuse_intr_data d;
2015 fuse_prepare_interrupt(f, req, &d);
2016 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
2017 fuse_finish_interrupt(f, req, &d);
2018 free(path);
2020 pthread_rwlock_unlock(&f->tree_lock);
2021 reply_err(req, err);
2024 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2025 const char *name, char *value, size_t size)
2027 int err;
2028 char *path;
2030 err = -ENOENT;
2031 pthread_rwlock_rdlock(&f->tree_lock);
2032 path = get_path(f, ino);
2033 if (path != NULL) {
2034 struct fuse_intr_data d;
2035 fuse_prepare_interrupt(f, req, &d);
2036 err = fuse_fs_getxattr(f->fs, path, name, value, size);
2037 fuse_finish_interrupt(f, req, &d);
2038 free(path);
2040 pthread_rwlock_unlock(&f->tree_lock);
2041 return err;
2044 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
2045 size_t size)
2047 struct fuse *f = req_fuse_prepare(req);
2048 int res;
2050 if (size) {
2051 char *value = (char *) malloc(size);
2052 if (value == NULL) {
2053 reply_err(req, -ENOMEM);
2054 return;
2056 res = common_getxattr(f, req, ino, name, value, size);
2057 if (res > 0)
2058 fuse_reply_buf(req, value, res);
2059 else
2060 reply_err(req, res);
2061 free(value);
2062 } else {
2063 res = common_getxattr(f, req, ino, name, NULL, 0);
2064 if (res >= 0)
2065 fuse_reply_xattr(req, res);
2066 else
2067 reply_err(req, res);
2071 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2072 char *list, size_t size)
2074 char *path;
2075 int err;
2077 err = -ENOENT;
2078 pthread_rwlock_rdlock(&f->tree_lock);
2079 path = get_path(f, ino);
2080 if (path != NULL) {
2081 struct fuse_intr_data d;
2082 fuse_prepare_interrupt(f, req, &d);
2083 err = fuse_fs_listxattr(f->fs, path, list, size);
2084 fuse_finish_interrupt(f, req, &d);
2085 free(path);
2087 pthread_rwlock_unlock(&f->tree_lock);
2088 return err;
2091 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
2093 struct fuse *f = req_fuse_prepare(req);
2094 int res;
2096 if (size) {
2097 char *list = (char *) malloc(size);
2098 if (list == NULL) {
2099 reply_err(req, -ENOMEM);
2100 return;
2102 res = common_listxattr(f, req, ino, list, size);
2103 if (res > 0)
2104 fuse_reply_buf(req, list, res);
2105 else
2106 reply_err(req, res);
2107 free(list);
2108 } else {
2109 res = common_listxattr(f, req, ino, NULL, 0);
2110 if (res >= 0)
2111 fuse_reply_xattr(req, res);
2112 else
2113 reply_err(req, res);
2117 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
2118 const char *name)
2120 struct fuse *f = req_fuse_prepare(req);
2121 char *path;
2122 int err;
2124 err = -ENOENT;
2125 pthread_rwlock_rdlock(&f->tree_lock);
2126 path = get_path(f, ino);
2127 if (path != NULL) {
2128 struct fuse_intr_data d;
2129 fuse_prepare_interrupt(f, req, &d);
2130 err = fuse_fs_removexattr(f->fs, path, name);
2131 fuse_finish_interrupt(f, req, &d);
2132 free(path);
2134 pthread_rwlock_unlock(&f->tree_lock);
2135 reply_err(req, err);
2138 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
2140 struct lock *l;
2142 for (l = node->locks; l; l = l->next)
2143 if (l->owner != lock->owner &&
2144 lock->start <= l->end && l->start <= lock->end &&
2145 (l->type == F_WRLCK || lock->type == F_WRLCK))
2146 break;
2148 return l;
2151 static void delete_lock(struct lock **lockp)
2153 struct lock *l = *lockp;
2154 *lockp = l->next;
2155 free(l);
2158 static void insert_lock(struct lock **pos, struct lock *lock)
2160 lock->next = *pos;
2161 *pos = lock;
2164 static int locks_insert(struct node *node, struct lock *lock)
2166 struct lock **lp;
2167 struct lock *newl1 = NULL;
2168 struct lock *newl2 = NULL;
2170 if (lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX) {
2171 newl1 = malloc(sizeof(struct lock));
2172 newl2 = malloc(sizeof(struct lock));
2174 if (!newl1 || !newl2) {
2175 free(newl1);
2176 free(newl2);
2177 return -ENOLCK;
2181 for (lp = &node->locks; *lp;) {
2182 struct lock *l = *lp;
2183 if (l->owner != lock->owner)
2184 goto skip;
2186 if (lock->type == l->type) {
2187 if (l->end < lock->start - 1)
2188 goto skip;
2189 if (lock->end < l->start - 1)
2190 break;
2191 if (l->start <= lock->start && lock->end <= l->end)
2192 goto out;
2193 if (l->start < lock->start)
2194 lock->start = l->start;
2195 if (lock->end < l->end)
2196 lock->end = l->end;
2197 goto delete;
2198 } else {
2199 if (l->end < lock->start)
2200 goto skip;
2201 if (lock->end < l->start)
2202 break;
2203 if (lock->start <= l->start && l->end <= lock->end)
2204 goto delete;
2205 if (l->end <= lock->end) {
2206 l->end = lock->start - 1;
2207 goto skip;
2209 if (lock->start <= l->start) {
2210 l->start = lock->end + 1;
2211 break;
2213 *newl2 = *l;
2214 newl2->start = lock->end + 1;
2215 l->end = lock->start - 1;
2216 insert_lock(&l->next, newl2);
2217 newl2 = NULL;
2219 skip:
2220 lp = &l->next;
2221 continue;
2223 delete:
2224 delete_lock(lp);
2226 if (lock->type != F_UNLCK) {
2227 *newl1 = *lock;
2228 insert_lock(lp, newl1);
2229 newl1 = NULL;
2231 out:
2232 free(newl1);
2233 free(newl2);
2234 return 0;
2237 static void flock_to_lock(struct flock *flock, struct lock *lock)
2239 memset(lock, 0, sizeof(struct lock));
2240 lock->type = flock->l_type;
2241 lock->start = flock->l_start;
2242 lock->end = flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
2243 lock->pid = flock->l_pid;
2246 static void lock_to_flock(struct lock *lock, struct flock *flock)
2248 flock->l_type = lock->type;
2249 flock->l_start = lock->start;
2250 flock->l_len = (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
2251 flock->l_pid = lock->pid;
2254 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
2255 const char *path, struct fuse_file_info *fi)
2257 struct fuse_intr_data d;
2258 struct flock lock;
2259 struct lock l;
2260 int err;
2261 int errlock;
2263 fuse_prepare_interrupt(f, req, &d);
2264 memset(&lock, 0, sizeof(lock));
2265 lock.l_type = F_UNLCK;
2266 lock.l_whence = SEEK_SET;
2267 err = fuse_fs_flush(f->fs, path, fi);
2268 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
2269 fuse_finish_interrupt(f, req, &d);
2271 if (errlock != -ENOSYS) {
2272 flock_to_lock(&lock, &l);
2273 l.owner = fi->lock_owner;
2274 pthread_mutex_lock(&f->lock);
2275 locks_insert(get_node(f, ino), &l);
2276 pthread_mutex_unlock(&f->lock);
2278 /* if op.lock() is defined FLUSH is needed regardless of op.flush() */
2279 if (err == -ENOSYS)
2280 err = 0;
2282 return err;
2285 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
2286 struct fuse_file_info *fi)
2288 struct fuse *f = req_fuse_prepare(req);
2289 struct fuse_intr_data d;
2290 char *path;
2291 int err = 0;
2293 pthread_rwlock_rdlock(&f->tree_lock);
2294 path = get_path(f, ino);
2295 if (f->conf.debug)
2296 fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n",
2297 fi->flush ? "+FLUSH" : "",
2298 (unsigned long long) fi->fh, fi->flags);
2300 if (fi->flush) {
2301 err = fuse_flush_common(f, req, ino, path, fi);
2302 if (err == -ENOSYS)
2303 err = 0;
2306 fuse_prepare_interrupt(f, req, &d);
2307 fuse_do_release(f, ino, path, fi);
2308 fuse_finish_interrupt(f, req, &d);
2309 free(path);
2310 pthread_rwlock_unlock(&f->tree_lock);
2312 reply_err(req, err);
2315 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
2316 struct fuse_file_info *fi)
2318 struct fuse *f = req_fuse_prepare(req);
2319 char *path;
2320 int err;
2322 pthread_rwlock_rdlock(&f->tree_lock);
2323 path = get_path(f, ino);
2324 if (path && f->conf.debug)
2325 fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh);
2326 err = fuse_flush_common(f, req, ino, path, fi);
2327 free(path);
2328 pthread_rwlock_unlock(&f->tree_lock);
2329 reply_err(req, err);
2332 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
2333 struct fuse_file_info *fi, struct flock *lock,
2334 int cmd)
2336 struct fuse *f = req_fuse_prepare(req);
2337 char *path;
2338 int err;
2340 err = -ENOENT;
2341 pthread_rwlock_rdlock(&f->tree_lock);
2342 path = get_path(f, ino);
2343 if (path != NULL) {
2344 struct fuse_intr_data d;
2345 fuse_prepare_interrupt(f, req, &d);
2346 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
2347 fuse_finish_interrupt(f, req, &d);
2348 free(path);
2350 pthread_rwlock_unlock(&f->tree_lock);
2351 return err;
2354 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
2355 struct fuse_file_info *fi, struct flock *lock)
2357 int err;
2358 struct lock l;
2359 struct lock *conflict;
2360 struct fuse *f = req_fuse(req);
2362 flock_to_lock(lock, &l);
2363 l.owner = fi->lock_owner;
2364 pthread_mutex_lock(&f->lock);
2365 conflict = locks_conflict(get_node(f, ino), &l);
2366 if (conflict)
2367 lock_to_flock(conflict, lock);
2368 pthread_mutex_unlock(&f->lock);
2369 if (!conflict)
2370 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
2371 else
2372 err = 0;
2374 if (!err)
2375 fuse_reply_lock(req, lock);
2376 else
2377 reply_err(req, err);
2380 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
2381 struct fuse_file_info *fi, struct flock *lock,
2382 int should_sleep)
2384 int err = fuse_lock_common(req, ino, fi, lock, should_sleep ? F_SETLKW : F_SETLK);
2385 if (!err) {
2386 struct fuse *f = req_fuse(req);
2387 struct lock l;
2388 flock_to_lock(lock, &l);
2389 l.owner = fi->lock_owner;
2390 pthread_mutex_lock(&f->lock);
2391 locks_insert(get_node(f, ino), &l);
2392 pthread_mutex_unlock(&f->lock);
2394 reply_err(req, err);
2397 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
2398 uint64_t idx)
2400 struct fuse *f = req_fuse_prepare(req);
2401 struct fuse_intr_data d;
2402 char *path;
2403 int err;
2405 err = -ENOENT;
2406 pthread_rwlock_rdlock(&f->tree_lock);
2407 path = get_path(f, ino);
2408 if (path != NULL) {
2409 fuse_prepare_interrupt(f, req, &d);
2410 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
2411 fuse_finish_interrupt(f, req, &d);
2412 free(path);
2414 pthread_rwlock_unlock(&f->tree_lock);
2415 if (!err)
2416 fuse_reply_bmap(req, idx);
2417 else
2418 reply_err(req, err);
2421 static struct fuse_lowlevel_ops fuse_path_ops = {
2422 .init = fuse_lib_init,
2423 .destroy = fuse_lib_destroy,
2424 .lookup = fuse_lib_lookup,
2425 .forget = fuse_lib_forget,
2426 .getattr = fuse_lib_getattr,
2427 .setattr = fuse_lib_setattr,
2428 .access = fuse_lib_access,
2429 .readlink = fuse_lib_readlink,
2430 .mknod = fuse_lib_mknod,
2431 .mkdir = fuse_lib_mkdir,
2432 .unlink = fuse_lib_unlink,
2433 .rmdir = fuse_lib_rmdir,
2434 .symlink = fuse_lib_symlink,
2435 .rename = fuse_lib_rename,
2436 .link = fuse_lib_link,
2437 .create = fuse_lib_create,
2438 .open = fuse_lib_open,
2439 .read = fuse_lib_read,
2440 .write = fuse_lib_write,
2441 .flush = fuse_lib_flush,
2442 .release = fuse_lib_release,
2443 .fsync = fuse_lib_fsync,
2444 .opendir = fuse_lib_opendir,
2445 .readdir = fuse_lib_readdir,
2446 .releasedir = fuse_lib_releasedir,
2447 .fsyncdir = fuse_lib_fsyncdir,
2448 .statfs = fuse_lib_statfs,
2449 .setxattr = fuse_lib_setxattr,
2450 .getxattr = fuse_lib_getxattr,
2451 .listxattr = fuse_lib_listxattr,
2452 .removexattr = fuse_lib_removexattr,
2453 .getlk = fuse_lib_getlk,
2454 .setlk = fuse_lib_setlk,
2455 .bmap = fuse_lib_bmap,
2458 struct fuse_session *fuse_get_session(struct fuse *f)
2460 return f->se;
2463 int fuse_loop(struct fuse *f)
2465 if (f)
2466 return fuse_session_loop(f->se);
2467 else
2468 return -1;
2471 void fuse_exit(struct fuse *f)
2473 fuse_session_exit(f->se);
2476 struct fuse_context *fuse_get_context(void)
2478 return &fuse_get_context_internal()->ctx;
2481 int fuse_interrupted(void)
2483 return fuse_req_interrupted(fuse_get_context_internal()->req);
2486 enum {
2487 KEY_HELP,
2490 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
2492 static const struct fuse_opt fuse_lib_opts[] = {
2493 FUSE_OPT_KEY("-h", KEY_HELP),
2494 FUSE_OPT_KEY("--help", KEY_HELP),
2495 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
2496 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
2497 FUSE_LIB_OPT("debug", debug, 1),
2498 FUSE_LIB_OPT("-d", debug, 1),
2499 FUSE_LIB_OPT("hard_remove", hard_remove, 1),
2500 FUSE_LIB_OPT("use_ino", use_ino, 1),
2501 FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
2502 FUSE_LIB_OPT("direct_io", direct_io, 1),
2503 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
2504 FUSE_LIB_OPT("umask=", set_mode, 1),
2505 FUSE_LIB_OPT("umask=%o", umask, 0),
2506 FUSE_LIB_OPT("uid=", set_uid, 1),
2507 FUSE_LIB_OPT("uid=%d", uid, 0),
2508 FUSE_LIB_OPT("gid=", set_gid, 1),
2509 FUSE_LIB_OPT("gid=%d", gid, 0),
2510 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0),
2511 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0),
2512 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0),
2513 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1),
2514 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
2515 FUSE_LIB_OPT("intr", intr, 1),
2516 FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
2517 FUSE_OPT_END
2520 static void fuse_lib_help(void)
2522 fprintf(stderr,
2523 " -o hard_remove immediate removal (don't hide files)\n"
2524 " -o use_ino let filesystem set inode numbers\n"
2525 " -o readdir_ino try to fill in d_ino in readdir\n"
2526 " -o direct_io use direct I/O\n"
2527 " -o kernel_cache cache files in kernel\n"
2528 " -o umask=M set file permissions (octal)\n"
2529 " -o uid=N set file owner\n"
2530 " -o gid=N set file group\n"
2531 " -o entry_timeout=T cache timeout for names (1.0s)\n"
2532 " -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
2533 " -o attr_timeout=T cache timeout for attributes (1.0s)\n"
2534 " -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
2535 " -o intr allow requests to be interrupted\n"
2536 " -o intr_signal=NUM signal to send on interrupt (%i)\n"
2537 "\n", FUSE_DEFAULT_INTR_SIGNAL);
2540 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
2541 struct fuse_args *outargs)
2543 (void) arg; (void) outargs;
2545 if (key == KEY_HELP) {
2546 struct fuse_config *conf = (struct fuse_config *) data;
2547 fuse_lib_help();
2548 conf->help = 1;
2551 return 1;
2554 static int fuse_init_intr_signal(int signum, int *installed)
2556 struct sigaction old_sa;
2558 if (sigaction(signum, NULL, &old_sa) == -1) {
2559 perror("fuse: cannot get old signal handler");
2560 return -1;
2563 if (old_sa.sa_handler == SIG_DFL) {
2564 struct sigaction sa;
2566 memset(&sa, 0, sizeof(struct sigaction));
2567 sa.sa_handler = fuse_intr_sighandler;
2568 sigemptyset(&sa.sa_mask);
2570 if (sigaction(signum, &sa, NULL) == -1) {
2571 perror("fuse: cannot set interrupt signal handler");
2572 return -1;
2574 *installed = 1;
2576 return 0;
2579 static void fuse_restore_intr_signal(int signum)
2581 struct sigaction sa;
2583 memset(&sa, 0, sizeof(struct sigaction));
2584 sa.sa_handler = SIG_DFL;
2585 sigaction(signum, &sa, NULL);
2588 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
2589 void *user_data)
2591 struct fuse_fs *fs;
2593 if (sizeof(struct fuse_operations) < op_size) {
2594 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
2595 op_size = sizeof(struct fuse_operations);
2598 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
2599 if (!fs) {
2600 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
2601 return NULL;
2604 fs->user_data = user_data;
2605 if (op)
2606 memcpy(&fs->op, op, op_size);
2607 return fs;
2610 struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
2611 const struct fuse_operations *op, size_t op_size,
2612 void *user_data)
2614 struct fuse *f;
2615 struct node *root;
2616 struct fuse_fs *fs;
2617 struct fuse_lowlevel_ops llop = fuse_path_ops;
2619 if (fuse_create_context_key() == -1)
2620 goto out;
2622 f = (struct fuse *) calloc(1, sizeof(struct fuse));
2623 if (f == NULL) {
2624 fprintf(stderr, "fuse: failed to allocate fuse object\n");
2625 goto out_delete_context_key;
2628 fs = fuse_fs_new(op, op_size, user_data);
2629 if (!fs)
2630 goto out_free;
2632 f->fs = fs;
2633 f->utime_omit_ok = fs->op.flag_utime_omit_ok;
2635 /* Oh f**k, this is ugly! */
2636 if (!fs->op.lock) {
2637 llop.getlk = NULL;
2638 llop.setlk = NULL;
2641 f->conf.entry_timeout = 1.0;
2642 f->conf.attr_timeout = 1.0;
2643 f->conf.negative_timeout = 0.0;
2644 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
2646 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1)
2647 goto out_free_fs;
2649 if (!f->conf.ac_attr_timeout_set)
2650 f->conf.ac_attr_timeout = f->conf.attr_timeout;
2652 #ifdef __FreeBSD__
2654 * In FreeBSD, we always use these settings as inode numbers are needed to
2655 * make getcwd(3) work.
2657 f->conf.readdir_ino = 1;
2658 #endif
2660 f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
2661 if (f->se == NULL) {
2662 goto out_free_fs;
2665 fuse_session_add_chan(f->se, ch);
2667 if (f->conf.debug)
2668 fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
2669 f->ctr = 0;
2670 f->generation = 0;
2671 /* FIXME: Dynamic hash table */
2672 f->name_table_size = 14057;
2673 f->name_table = (struct node **)
2674 calloc(1, sizeof(struct node *) * f->name_table_size);
2675 if (f->name_table == NULL) {
2676 fprintf(stderr, "fuse: memory allocation failed\n");
2677 goto out_free_session;
2680 f->id_table_size = 14057;
2681 f->id_table = (struct node **)
2682 calloc(1, sizeof(struct node *) * f->id_table_size);
2683 if (f->id_table == NULL) {
2684 fprintf(stderr, "fuse: memory allocation failed\n");
2685 goto out_free_name_table;
2688 fuse_mutex_init(&f->lock);
2689 pthread_rwlock_init(&f->tree_lock, NULL);
2691 root = (struct node *) calloc(1, sizeof(struct node));
2692 if (root == NULL) {
2693 fprintf(stderr, "fuse: memory allocation failed\n");
2694 goto out_free_id_table;
2697 root->name = strdup("/");
2698 if (root->name == NULL) {
2699 fprintf(stderr, "fuse: memory allocation failed\n");
2700 goto out_free_root;
2703 if (f->conf.intr &&
2704 fuse_init_intr_signal(f->conf.intr_signal, &f->intr_installed) == -1)
2705 goto out_free_root_name;
2707 root->parent = NULL;
2708 root->nodeid = FUSE_ROOT_ID;
2709 root->generation = 0;
2710 root->refctr = 1;
2711 root->nlookup = 1;
2712 hash_id(f, root);
2714 return f;
2716 out_free_root_name:
2717 free(root->name);
2718 out_free_root:
2719 free(root);
2720 out_free_id_table:
2721 free(f->id_table);
2722 out_free_name_table:
2723 free(f->name_table);
2724 out_free_session:
2725 fuse_session_destroy(f->se);
2726 out_free_fs:
2727 /* Horrible compatibility hack to stop the destructor from being
2728 called on the filesystem without init being called first */
2729 fs->op.destroy = NULL;
2730 fuse_fs_destroy(f->fs);
2731 out_free:
2732 free(f);
2733 out_delete_context_key:
2734 fuse_delete_context_key();
2735 out:
2736 return NULL;
2739 void fuse_destroy(struct fuse *f)
2741 size_t i;
2743 if (f->conf.intr && f->intr_installed)
2744 fuse_restore_intr_signal(f->conf.intr_signal);
2746 if (f->fs) {
2747 struct fuse_context_i *c = fuse_get_context_internal();
2749 memset(c, 0, sizeof(*c));
2750 c->ctx.fuse = f;
2752 for (i = 0; i < f->id_table_size; i++) {
2753 struct node *node;
2755 for (node = f->id_table[i]; node != NULL; node = node->id_next) {
2756 if (node->is_hidden) {
2757 char *path = get_path(f, node->nodeid);
2758 if (path) {
2759 fuse_fs_unlink(f->fs, path);
2760 free(path);
2766 for (i = 0; i < f->id_table_size; i++) {
2767 struct node *node;
2768 struct node *next;
2770 for (node = f->id_table[i]; node != NULL; node = next) {
2771 next = node->id_next;
2772 free_node(node);
2775 free(f->id_table);
2776 free(f->name_table);
2777 pthread_mutex_destroy(&f->lock);
2778 pthread_rwlock_destroy(&f->tree_lock);
2779 fuse_session_destroy(f->se);
2780 free(f);
2781 fuse_delete_context_key();