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
10 /* For pthread_rwlock_t */
12 #endif /* __SOLARIS__ */
16 #include "fuse_lowlevel.h"
18 #include "fuse_misc.h"
32 #include <sys/param.h>
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
50 double negative_timeout
;
52 double ac_attr_timeout
;
53 int ac_attr_timeout_set
;
69 #endif /* __SOLARIS__ */
73 struct fuse_operations op
;
76 struct fuse_module
*m
;
77 #endif /* __SOLARIS__ */
85 #endif /* __SOLARIS__ */
88 struct fuse_session
*se
;
89 struct node
**name_table
;
90 size_t name_table_size
;
91 struct node
**id_table
;
94 unsigned int generation
;
97 pthread_rwlock_t tree_lock
;
98 struct fuse_config conf
;
114 struct node
*name_next
;
115 struct node
*id_next
;
117 unsigned int generation
;
125 struct timespec stat_updated
;
126 struct timespec mtime
;
129 #endif /* __SOLARIS__ */
134 pthread_mutex_t lock
;
148 struct fuse_context_i
{
149 struct fuse_context ctx
;
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
;
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
));
168 fprintf(stderr
, "fuse: memory allocation failed\n");
172 fuse_current_so
= so
;
173 so
->handle
= dlopen(soname
, RTLD_NOW
);
174 fuse_current_so
= NULL
;
176 fprintf(stderr
, "fuse: %s\n", dlerror());
180 fprintf(stderr
, "fuse: %s did not register any modules", soname
);
192 static int fuse_load_so_module(const char *module
)
195 char *soname
= malloc(strlen(module
) + 64);
197 fprintf(stderr
, "fuse: memory allocation failed\n");
200 sprintf(soname
, "libfusemod_%s.so", module
);
201 res
= fuse_load_so_name(soname
);
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) {
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
);
225 int err
= fuse_load_so_module(module
);
227 m
= fuse_find_module(module
);
229 pthread_mutex_unlock(&fuse_context_lock
);
233 static void fuse_put_module(struct fuse_module
*m
)
235 pthread_mutex_lock(&fuse_context_lock
);
238 if (!m
->ctr
&& m
->so
) {
239 struct fusemod_so
*so
= m
->so
;
243 struct fuse_module
**mp
;
244 for (mp
= &fuse_modules
; *mp
;) {
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
;
263 for (node
= f
->id_table
[hash
]; node
!= NULL
; node
= node
->id_next
)
264 if (node
->nodeid
== nodeid
)
270 static struct node
*get_node(struct fuse
*f
, fuse_ino_t nodeid
)
272 struct node
*node
= get_node_nocheck(f
, nodeid
);
274 fprintf(stderr
, "fuse internal error: node %llu not found\n",
275 (unsigned long long) nodeid
);
281 static void free_node(struct node
*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
;
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
,
309 unsigned int hash
= *name
;
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
)
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
);
336 fprintf(stderr
, "fuse internal error: unable to unhash node: %llu\n",
337 (unsigned long long) node
->nodeid
);
342 static int hash_name(struct fuse
*f
, struct node
*node
, fuse_ino_t parentid
,
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
)
352 node
->parent
= parent
;
353 node
->name_next
= f
->name_table
[hash
];
354 f
->name_table
[hash
] = node
;
358 static void delete_node(struct fuse
*f
, struct node
*node
)
361 fprintf(stderr
, "delete: %llu\n", (unsigned long long) node
->nodeid
);
368 static void unref_node(struct fuse
*f
, struct node
*node
)
370 assert(node
->refctr
> 0);
373 delete_node(f
, node
);
376 static fuse_ino_t
next_id(struct fuse
*f
)
379 f
->ctr
= (f
->ctr
+ 1) & 0xffffffff;
382 } while (f
->ctr
== 0 || f
->ctr
== FUSE_UNKNOWN_INO
||
383 get_node_nocheck(f
, f
->ctr
) != NULL
);
387 static struct node
*lookup_node(struct fuse
*f
, fuse_ino_t parent
,
390 size_t hash
= name_hash(f
, parent
, name
);
393 for (node
= f
->name_table
[hash
]; node
!= NULL
; node
= node
->name_next
)
394 if (node
->parent
->nodeid
== parent
&& strcmp(node
->name
, name
) == 0)
400 static struct node
*find_node(struct fuse
*f
, fuse_ino_t parent
,
405 pthread_mutex_lock(&f
->lock
);
406 node
= lookup_node(f
, parent
, name
);
408 node
= (struct node
*) calloc(1, sizeof(struct node
));
413 node
->nodeid
= next_id(f
);
414 node
->open_count
= 0;
416 node
->generation
= f
->generation
;
417 if (hash_name(f
, node
, parent
, name
) == -1) {
426 pthread_mutex_unlock(&f
->lock
);
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
);
439 if (s
- len
<= *buf
) {
440 unsigned pathlen
= *bufsize
- (s
- *buf
);
441 unsigned newbufsize
= *bufsize
;
444 while (newbufsize
< pathlen
+ len
+ 1) {
445 if (newbufsize
>= 0x80000000)
446 newbufsize
= 0xffffffff;
451 newbuf
= realloc(*buf
, newbufsize
);
456 s
= newbuf
+ newbufsize
- pathlen
;
457 memmove(s
, newbuf
+ *bufsize
- pathlen
, pathlen
);
458 *bufsize
= newbufsize
;
461 #else /* ! __SOLARIS__ */
464 fprintf(stderr
, "fuse: path too long: ...%s\n", s
+ len
);
467 #endif /* __SOLARIS__ */
468 strncpy(s
, name
, len
);
475 static char *get_path_name(struct fuse
*f
, fuse_ino_t nodeid
, const char *name
)
478 char buf
[FUSE_MAX_PATH
];
479 char *s
= buf
+ FUSE_MAX_PATH
- 1;
485 s
= add_name(buf
, s
, name
);
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
) {
498 s
= add_name(buf
, s
, node
->name
);
502 pthread_mutex_unlock(&f
->lock
);
504 if (node
== NULL
|| s
== NULL
)
511 #else /* __SOLARIS__ */
513 unsigned bufsize
= 256;
518 buf
= malloc(bufsize
);
522 s
= buf
+ bufsize
- 1;
526 s
= add_name(&buf
, &bufsize
, s
, name
);
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
) {
539 s
= add_name(&buf
, &bufsize
, s
, node
->name
);
543 pthread_mutex_unlock(&f
->lock
);
545 if (node
== NULL
|| s
== NULL
)
549 memmove(buf
, s
, bufsize
- (s
- buf
));
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
)
568 if (nodeid
== FUSE_ROOT_ID
)
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
);
578 pthread_mutex_unlock(&f
->lock
);
581 static void remove_node(struct fuse
*f
, fuse_ino_t dir
, const char *name
)
585 pthread_mutex_lock(&f
->lock
);
586 node
= lookup_node(f
, dir
, name
);
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
)
596 struct node
*newnode
;
599 pthread_mutex_lock(&f
->lock
);
600 node
= lookup_node(f
, olddir
, oldname
);
601 newnode
= lookup_node(f
, newdir
, newname
);
605 if (newnode
!= NULL
) {
607 fprintf(stderr
, "fuse: hidden file got created during hiding\n");
611 unhash_name(f
, newnode
);
614 unhash_name(f
, node
);
615 if (hash_name(f
, node
, newdir
, newname
) == -1) {
624 pthread_mutex_unlock(&f
->lock
);
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
);
635 stbuf
->st_uid
= f
->conf
.uid
;
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
)
651 struct fuse_intr_data
{
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())
665 pthread_mutex_lock(&f
->lock
);
666 while (!d
->finished
) {
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
);
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
);
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
)
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
)
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
;
716 return fs
->op
.getattr(path
, buf
);
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
;
726 return fs
->op
.fgetattr(path
, buf
, fi
);
727 else if (fs
->op
.getattr
)
728 return fs
->op
.getattr(path
, buf
);
733 int fuse_fs_rename(struct fuse_fs
*fs
, const char *oldpath
,
736 fuse_get_context()->private_data
= fs
->user_data
;
738 return fs
->op
.rename(oldpath
, newpath
);
743 int fuse_fs_unlink(struct fuse_fs
*fs
, const char *path
)
745 fuse_get_context()->private_data
= fs
->user_data
;
747 return fs
->op
.unlink(path
);
752 int fuse_fs_rmdir(struct fuse_fs
*fs
, const char *path
)
754 fuse_get_context()->private_data
= fs
->user_data
;
756 return fs
->op
.rmdir(path
);
761 int fuse_fs_symlink(struct fuse_fs
*fs
, const char *linkname
, const char *path
)
763 fuse_get_context()->private_data
= fs
->user_data
;
765 return fs
->op
.symlink(linkname
, path
);
770 int fuse_fs_link(struct fuse_fs
*fs
, const char *oldpath
, const char *newpath
)
772 fuse_get_context()->private_data
= fs
->user_data
;
774 return fs
->op
.link(oldpath
, newpath
);
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
;
784 return fs
->op
.release(path
, fi
);
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
;
794 return fs
->op
.opendir(path
, fi
);
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
;
804 return fs
->op
.open(path
, fi
);
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
;
814 return fs
->op
.read(path
, buf
, size
, off
, fi
);
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
;
824 return fs
->op
.write(path
, buf
, size
, off
, fi
);
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
;
834 return fs
->op
.fsync(path
, datasync
, fi
);
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
;
844 return fs
->op
.fsyncdir(path
, datasync
, fi
);
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
;
854 return fs
->op
.flush(path
, fi
);
859 int fuse_fs_statfs(struct fuse_fs
*fs
, const char *path
, struct statvfs
*buf
)
861 fuse_get_context()->private_data
= fs
->user_data
;
863 return fs
->op
.statfs(path
, buf
);
865 buf
->f_namemax
= 255;
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
);
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
;
887 return fs
->op
.readdir(path
, buf
, filler
, off
, fi
);
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
;
897 return fs
->op
.create(path
, mode
, fi
);
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
;
907 return fs
->op
.lock(path
, fi
, cmd
, lock
);
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
;
916 return fs
->op
.chown(path
, uid
, gid
);
921 int fuse_fs_truncate(struct fuse_fs
*fs
, const char *path
, off_t size
)
923 fuse_get_context()->private_data
= fs
->user_data
;
925 return fs
->op
.truncate(path
, size
);
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
);
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
;
947 return fs
->op
.utimens(path
, tv
);
948 else if(fs
->op
.utime
) {
950 buf
.actime
= tv
[0].tv_sec
;
951 buf
.modtime
= tv
[1].tv_sec
;
952 return fs
->op
.utime(path
, &buf
);
957 int fuse_fs_access(struct fuse_fs
*fs
, const char *path
, int mask
)
959 fuse_get_context()->private_data
= fs
->user_data
;
961 return fs
->op
.access(path
, mask
);
966 int fuse_fs_readlink(struct fuse_fs
*fs
, const char *path
, char *buf
,
969 fuse_get_context()->private_data
= fs
->user_data
;
971 return fs
->op
.readlink(path
, buf
, len
);
976 int fuse_fs_mknod(struct fuse_fs
*fs
, const char *path
, mode_t mode
,
979 fuse_get_context()->private_data
= fs
->user_data
;
981 return fs
->op
.mknod(path
, mode
, rdev
);
986 int fuse_fs_mkdir(struct fuse_fs
*fs
, const char *path
, mode_t mode
)
988 fuse_get_context()->private_data
= fs
->user_data
;
990 return fs
->op
.mkdir(path
, mode
);
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
;
1000 return fs
->op
.setxattr(path
, name
, value
, size
, flags
);
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
);
1015 int fuse_fs_listxattr(struct fuse_fs
*fs
, const char *path
, char *list
,
1018 fuse_get_context()->private_data
= fs
->user_data
;
1019 if (fs
->op
.listxattr
)
1020 return fs
->op
.listxattr(path
, list
, size
);
1025 int fuse_fs_bmap(struct fuse_fs
*fs
, const char *path
, size_t blocksize
,
1028 fuse_get_context()->private_data
= fs
->user_data
;
1030 return fs
->op
.bmap(path
, blocksize
, idx
);
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
);
1044 static int is_open(struct fuse
*f
, fuse_ino_t dir
, const char *name
)
1048 pthread_mutex_lock(&f
->lock
);
1049 node
= lookup_node(f
, dir
, name
);
1050 if (node
&& node
->open_count
> 0)
1052 pthread_mutex_unlock(&f
->lock
);
1056 static char *hidden_name(struct fuse
*f
, fuse_ino_t dir
, const char *oldname
,
1057 char *newname
, size_t bufsize
)
1061 struct node
*newnode
;
1067 pthread_mutex_lock(&f
->lock
);
1068 node
= lookup_node(f
, dir
, oldname
);
1070 pthread_mutex_unlock(&f
->lock
);
1075 snprintf(newname
, bufsize
, ".fuse_hidden%08x%08x",
1076 (unsigned int) node
->nodeid
, f
->hidectr
);
1077 newnode
= lookup_node(f
, dir
, newname
);
1079 pthread_mutex_unlock(&f
->lock
);
1081 newpath
= get_path_name(f
, dir
, newname
);
1085 res
= fuse_fs_getattr(f
->fs
, newpath
, &buf
);
1090 } while(res
== 0 && --failctr
);
1095 static int hide_node(struct fuse
*f
, const char *oldpath
,
1096 fuse_ino_t dir
, const char *oldname
)
1102 newpath
= hidden_name(f
, dir
, oldname
, newname
, sizeof(newname
));
1104 err
= fuse_fs_rename(f
->fs
, oldpath
, newpath
);
1106 err
= rename_node(f
, dir
, oldname
, dir
, newname
, 1);
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
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
);
1132 perror("fuse: clock_gettime");
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
)
1156 memset(e
, 0, sizeof(struct fuse_entry_param
));
1158 res
= fuse_fs_fgetattr(f
->fs
, path
, &e
->attr
, fi
);
1160 res
= fuse_fs_getattr(f
->fs
, path
, &e
->attr
);
1164 node
= find_node(f
, nodeid
, name
);
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
;
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
);
1181 fprintf(stderr
, " NODEID: %lu\n", (unsigned long) e
->ino
);
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
);
1193 c
= (struct fuse_context_i
*) malloc(sizeof(struct fuse_context_i
));
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");
1201 pthread_setspecific(fuse_context_key
, c
);
1206 static void fuse_freecontext(void *data
)
1211 static int fuse_create_context_key(void)
1214 pthread_mutex_lock(&fuse_context_lock
);
1215 if (!fuse_context_ref
) {
1216 err
= pthread_key_create(&fuse_context_key
, fuse_freecontext
);
1218 fprintf(stderr
, "fuse: failed to create thread specific key: %s\n",
1220 pthread_mutex_unlock(&fuse_context_lock
);
1225 pthread_mutex_unlock(&fuse_context_lock
);
1229 static void fuse_delete_context_key(void)
1231 pthread_mutex_lock(&fuse_context_lock
);
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
);
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
;
1250 c
->ctx
.umask
= ctx
->umask
;
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
,
1269 struct fuse
*f
= req_fuse(req
);
1270 if (fuse_reply_entry(req
, e
) == -ENOENT
)
1271 forget_node(f
, e
->ino
, 1);
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
;
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
));
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
;
1297 fs
->op
.destroy(fs
->user_data
);
1300 fuse_put_module(fs
->m
);
1301 #endif /* __SOLARIS__ */
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
));
1312 fuse_fs_destroy(f
->fs
);
1316 static void fuse_lib_lookup(fuse_req_t req
, fuse_ino_t parent
,
1319 struct fuse
*f
= req_fuse_prepare(req
);
1320 struct fuse_entry_param e
;
1325 pthread_rwlock_rdlock(&f
->tree_lock
);
1326 path
= get_path_name(f
, parent
, name
);
1328 struct fuse_intr_data d
;
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) {
1335 e
.entry_timeout
= f
->conf
.negative_timeout
;
1338 fuse_finish_interrupt(f
, req
, &d
);
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
);
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
);
1364 memset(&buf
, 0, sizeof(buf
));
1367 pthread_rwlock_rdlock(&f
->tree_lock
);
1368 path
= get_path(f
, ino
);
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
);
1376 pthread_rwlock_unlock(&f
->tree_lock
);
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
);
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
;
1395 return fs
->op
.chmod(path
, mode
);
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
);
1409 pthread_rwlock_rdlock(&f
->tree_lock
);
1410 path
= get_path(f
, ino
);
1412 struct fuse_intr_data d
;
1413 fuse_prepare_interrupt(f
, req
, &d
);
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
))) {
1419 (valid
& FUSE_SET_ATTR_UID
) ? attr
->st_uid
: (uid_t
) -1;
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
)) {
1426 err
= fuse_fs_ftruncate(f
->fs
, path
, attr
->st_size
, fi
);
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];
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
);
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
);
1463 err
= fuse_fs_getattr(f
->fs
, path
, &buf
);
1464 fuse_finish_interrupt(f
, req
, &d
);
1467 pthread_rwlock_unlock(&f
->tree_lock
);
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
);
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
);
1489 pthread_rwlock_rdlock(&f
->tree_lock
);
1490 path
= get_path(f
, ino
);
1492 struct fuse_intr_data d
;
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
);
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];
1512 pthread_rwlock_rdlock(&f
->tree_lock
);
1513 path
= get_path(f
, ino
);
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
);
1521 pthread_rwlock_unlock(&f
->tree_lock
);
1523 linkname
[PATH_MAX
] = '\0';
1524 fuse_reply_readlink(req
, linkname
);
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
;
1538 pthread_rwlock_rdlock(&f
->tree_lock
);
1539 path
= get_path_name(f
, parent
, name
);
1541 struct fuse_intr_data d
;
1543 fprintf(stderr
, "MKNOD %s\n", path
);
1544 fuse_prepare_interrupt(f
, req
, &d
);
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
);
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
);
1560 err
= lookup_path(f
, parent
, name
, path
, &e
, NULL
);
1562 fuse_finish_interrupt(f
, req
, &d
);
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
,
1572 struct fuse
*f
= req_fuse_prepare(req
);
1573 struct fuse_entry_param e
;
1578 pthread_rwlock_rdlock(&f
->tree_lock
);
1579 path
= get_path_name(f
, parent
, name
);
1581 struct fuse_intr_data d
;
1583 fprintf(stderr
, "MKDIR %s\n", path
);
1584 fuse_prepare_interrupt(f
, req
, &d
);
1585 err
= fuse_fs_mkdir(f
->fs
, path
, mode
);
1587 err
= lookup_path(f
, parent
, name
, path
, &e
, NULL
);
1588 fuse_finish_interrupt(f
, req
, &d
);
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
,
1598 struct fuse
*f
= req_fuse_prepare(req
);
1603 pthread_rwlock_wrlock(&f
->tree_lock
);
1604 path
= get_path_name(f
, parent
, name
);
1606 struct fuse_intr_data d
;
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
);
1613 err
= fuse_fs_unlink(f
->fs
, path
);
1615 remove_node(f
, parent
, name
);
1617 fuse_finish_interrupt(f
, req
, &d
);
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
);
1631 pthread_rwlock_wrlock(&f
->tree_lock
);
1632 path
= get_path_name(f
, parent
, name
);
1634 struct fuse_intr_data d
;
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
);
1641 remove_node(f
, parent
, name
);
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
;
1657 pthread_rwlock_rdlock(&f
->tree_lock
);
1658 path
= get_path_name(f
, parent
, name
);
1660 struct fuse_intr_data d
;
1662 fprintf(stderr
, "SYMLINK %s\n", path
);
1663 fuse_prepare_interrupt(f
, req
, &d
);
1664 err
= fuse_fs_symlink(f
->fs
, linkname
, path
);
1666 err
= lookup_path(f
, parent
, name
, path
, &e
, NULL
);
1667 fuse_finish_interrupt(f
, req
, &d
);
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
);
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
;
1691 fprintf(stderr
, "RENAME %s -> %s\n", oldpath
, newpath
);
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
);
1697 err
= fuse_fs_rename(f
->fs
, oldpath
, newpath
);
1699 err
= rename_node(f
, olddir
, oldname
, newdir
, newname
, 0);
1701 fuse_finish_interrupt(f
, req
, &d
);
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
;
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
;
1727 fprintf(stderr
, "LINK %s\n", newpath
);
1728 fuse_prepare_interrupt(f
, req
, &d
);
1729 err
= fuse_fs_link(f
->fs
, oldpath
, newpath
);
1731 err
= lookup_path(f
, newparent
, newname
, newpath
, &e
, NULL
);
1732 fuse_finish_interrupt(f
, req
, &d
);
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
)
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);
1753 if (node
->is_hidden
&& !node
->open_count
) {
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
;
1774 pthread_rwlock_rdlock(&f
->tree_lock
);
1775 path
= get_path_name(f
, parent
, name
);
1777 fuse_prepare_interrupt(f
, req
, &d
);
1778 err
= fuse_fs_create(f
->fs
, path
, mode
, fi
);
1780 err
= lookup_path(f
, parent
, name
, path
, &e
, fi
);
1782 fuse_fs_release(f
->fs
, path
, fi
);
1783 else if (!S_ISREG(e
.attr
.st_mode
)) {
1785 fuse_fs_release(f
->fs
, path
, fi
);
1786 forget_node(f
, e
.ino
, 1);
1788 if (f
->conf
.direct_io
)
1790 if (f
->conf
.kernel_cache
)
1795 fuse_finish_interrupt(f
, req
, &d
);
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
);
1812 reply_err(req
, err
);
1817 pthread_rwlock_unlock(&f
->tree_lock
);
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
)
1834 pthread_mutex_lock(&f
->lock
);
1835 node
= get_node(f
, ino
);
1836 if (node
->cache_valid
) {
1837 struct timespec now
;
1840 if (diff_timespec(&now
, &node
->stat_updated
) > f
->conf
.ac_attr_timeout
) {
1843 pthread_mutex_unlock(&f
->lock
);
1844 err
= fuse_fs_fgetattr(f
->fs
, path
, &stbuf
, fi
);
1845 pthread_mutex_lock(&f
->lock
);
1847 update_stat(node
, &stbuf
);
1849 node
->cache_valid
= 0;
1852 if (node
->cache_valid
)
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
;
1870 pthread_rwlock_rdlock(&f
->tree_lock
);
1871 path
= get_path(f
, ino
);
1873 fuse_prepare_interrupt(f
, req
, &d
);
1874 err
= fuse_fs_open(f
->fs
, path
, fi
);
1876 if (f
->conf
.direct_io
)
1878 if (f
->conf
.kernel_cache
)
1882 if (f
->conf
.auto_cache
)
1883 open_auto_cache(f
, ino
, path
, fi
);
1884 #endif /* __SOLARIS__ */
1886 fuse_finish_interrupt(f
, req
, &d
);
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
);
1902 reply_err(req
, err
);
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
);
1917 buf
= (char *) malloc(size
);
1919 reply_err(req
, -ENOMEM
);
1924 pthread_rwlock_rdlock(&f
->tree_lock
);
1925 path
= get_path(f
, ino
);
1927 struct fuse_intr_data d
;
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
);
1938 pthread_rwlock_unlock(&f
->tree_lock
);
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
);
1948 reply_err(req
, res
);
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
);
1961 pthread_rwlock_rdlock(&f
->tree_lock
);
1962 path
= get_path(f
, ino
);
1964 struct fuse_intr_data d
;
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
);
1975 pthread_rwlock_unlock(&f
->tree_lock
);
1979 fprintf(stderr
, " WRITE%s[%llu] %u bytes\n",
1980 fi
->writepage
? "PAGE" : "", (unsigned long long) fi
->fh
,
1982 if ((size_t) res
> size
)
1983 fprintf(stderr
, "fuse: wrote too many bytes");
1984 fuse_reply_write(req
, res
);
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
);
1997 pthread_rwlock_rdlock(&f
->tree_lock
);
1998 path
= get_path(f
, ino
);
2000 struct fuse_intr_data d
;
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
);
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
));
2018 fi
->fh_old
= dh
->fh
;
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
;
2028 struct fuse_file_info fi
;
2032 dh
= (struct fuse_dh
*) malloc(sizeof(struct fuse_dh
));
2034 reply_err(req
, -ENOMEM
);
2037 memset(dh
, 0, sizeof(struct fuse_dh
));
2039 dh
->contents
= NULL
;
2043 fuse_mutex_init(&dh
->lock
);
2045 llfi
->fh
= (uintptr_t) dh
;
2047 memset(&fi
, 0, sizeof(fi
));
2048 fi
.flags
= llfi
->flags
;
2051 pthread_rwlock_rdlock(&f
->tree_lock
);
2052 path
= get_path(f
, ino
);
2054 fuse_prepare_interrupt(f
, req
, &d
);
2055 err
= fuse_fs_opendir(f
->fs
, path
, &fi
);
2056 fuse_finish_interrupt(f
, req
, &d
);
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
);
2069 reply_err(req
, err
);
2071 pthread_mutex_destroy(&dh
->lock
);
2072 #endif /* ! __SOLARIS__ */
2076 pthread_rwlock_unlock(&f
->tree_lock
);
2079 static int extend_contents(struct fuse_dh
*dh
, unsigned minsize
)
2081 if (minsize
> dh
->size
) {
2083 unsigned newsize
= dh
->size
;
2087 while (newsize
< minsize
) {
2088 if (newsize
>= 0x80000000)
2089 newsize
= 0xffffffff;
2093 #else /* __SOLARIS__ */
2094 while (newsize
< minsize
)
2096 #endif /* __SOLARIS__ */
2098 newptr
= (char *) realloc(dh
->contents
, newsize
);
2100 dh
->error
= -ENOMEM
;
2103 dh
->contents
= newptr
;
2109 static int fill_dir(void *dh_
, const char *name
, const struct stat
*statp
,
2112 struct fuse_dh
*dh
= (struct fuse_dh
*) dh_
;
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
) {
2127 pthread_mutex_lock(&dh
->fuse
->lock
);
2128 node
= lookup_node(dh
->fuse
, dh
->nodeid
, name
);
2130 stbuf
.st_ino
= (ino_t
) node
->nodeid
;
2131 pthread_mutex_unlock(&dh
->fuse
->lock
);
2136 if (extend_contents(dh
, dh
->needlen
) == -1)
2140 newlen
= dh
->len
+ fuse_add_direntry(dh
->req
, dh
->contents
+ dh
->len
,
2141 dh
->needlen
- dh
->len
, name
,
2143 if (newlen
> dh
->needlen
)
2146 newlen
= dh
->len
+ fuse_add_direntry(dh
->req
, NULL
, 0, name
, NULL
, 0);
2147 if (extend_contents(dh
, newlen
) == -1)
2150 fuse_add_direntry(dh
->req
, dh
->contents
+ dh
->len
, dh
->size
- dh
->len
,
2151 name
, &stbuf
, newlen
);
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
)
2163 pthread_rwlock_rdlock(&f
->tree_lock
);
2164 path
= get_path(f
, ino
);
2166 struct fuse_intr_data d
;
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
);
2183 pthread_rwlock_unlock(&f
->tree_lock
);
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
2201 int err
= readdir_fill(f
, req
, ino
, size
, off
, dh
, &fi
);
2203 reply_err(req
, err
);
2208 if (off
< dh
->len
) {
2209 if (off
+ size
> dh
->len
)
2210 size
= dh
->len
- off
;
2217 fuse_reply_buf(req
, dh
->contents
+ off
, size
);
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
);
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
);
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
);
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
;
2255 get_dirhandle(llfi
, &fi
);
2258 pthread_rwlock_rdlock(&f
->tree_lock
);
2259 path
= get_path(f
, ino
);
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
);
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
);
2278 memset(&buf
, 0, sizeof(buf
));
2279 pthread_rwlock_rdlock(&f
->tree_lock
);
2285 path
= get_path(f
, ino
);
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
);
2294 pthread_rwlock_unlock(&f
->tree_lock
);
2297 fuse_reply_statfs(req
, &buf
);
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
);
2310 pthread_rwlock_rdlock(&f
->tree_lock
);
2311 path
= get_path(f
, ino
);
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
);
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
)
2330 pthread_rwlock_rdlock(&f
->tree_lock
);
2331 path
= get_path(f
, ino
);
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
);
2339 pthread_rwlock_unlock(&f
->tree_lock
);
2343 static void fuse_lib_getxattr(fuse_req_t req
, fuse_ino_t ino
, const char *name
,
2346 struct fuse
*f
= req_fuse_prepare(req
);
2350 char *value
= (char *) malloc(size
);
2351 if (value
== NULL
) {
2352 reply_err(req
, -ENOMEM
);
2355 res
= common_getxattr(f
, req
, ino
, name
, value
, size
);
2357 fuse_reply_buf(req
, value
, res
);
2359 reply_err(req
, res
);
2362 res
= common_getxattr(f
, req
, ino
, name
, NULL
, 0);
2364 fuse_reply_xattr(req
, res
);
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
)
2377 pthread_rwlock_rdlock(&f
->tree_lock
);
2378 path
= get_path(f
, ino
);
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
);
2386 pthread_rwlock_unlock(&f
->tree_lock
);
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
);
2396 char *list
= (char *) malloc(size
);
2398 reply_err(req
, -ENOMEM
);
2401 res
= common_listxattr(f
, req
, ino
, list
, size
);
2403 fuse_reply_buf(req
, list
, res
);
2405 reply_err(req
, res
);
2408 res
= common_listxattr(f
, req
, ino
, NULL
, 0);
2410 fuse_reply_xattr(req
, res
);
2412 reply_err(req
, res
);
2416 static void fuse_lib_removexattr(fuse_req_t req
, fuse_ino_t ino
,
2419 struct fuse
*f
= req_fuse_prepare(req
);
2424 pthread_rwlock_rdlock(&f
->tree_lock
);
2425 path
= get_path(f
, ino
);
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
);
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
)
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
))
2450 static void delete_lock(struct lock
**lockp
)
2452 struct lock
*l
= *lockp
;
2457 static void insert_lock(struct lock
**pos
, struct lock
*lock
)
2463 static int locks_insert(struct node
*node
, struct lock
*lock
)
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
) {
2480 for (lp
= &node
->locks
; *lp
;) {
2481 struct lock
*l
= *lp
;
2482 if (l
->owner
!= lock
->owner
)
2485 if (lock
->type
== l
->type
) {
2486 if (l
->end
< lock
->start
- 1)
2488 if (lock
->end
< l
->start
- 1)
2490 if (l
->start
<= lock
->start
&& lock
->end
<= l
->end
)
2492 if (l
->start
< lock
->start
)
2493 lock
->start
= l
->start
;
2494 if (lock
->end
< l
->end
)
2498 if (l
->end
< lock
->start
)
2500 if (lock
->end
< l
->start
)
2502 if (lock
->start
<= l
->start
&& l
->end
<= lock
->end
)
2504 if (l
->end
<= lock
->end
) {
2505 l
->end
= lock
->start
- 1;
2508 if (lock
->start
<= l
->start
) {
2509 l
->start
= lock
->end
+ 1;
2513 newl2
->start
= lock
->end
+ 1;
2514 l
->end
= lock
->start
- 1;
2515 insert_lock(&l
->next
, newl2
);
2525 if (lock
->type
!= F_UNLCK
) {
2527 insert_lock(lp
, newl1
);
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
;
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() */
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
;
2592 pthread_rwlock_rdlock(&f
->tree_lock
);
2593 path
= get_path(f
, ino
);
2595 fprintf(stderr
, "RELEASE%s[%llu] flags: 0x%x\n",
2596 fi
->flush
? "+FLUSH" : "",
2597 (unsigned long long) fi
->fh
, fi
->flags
);
2600 err
= fuse_flush_common(f
, req
, ino
, path
, fi
);
2605 fuse_prepare_interrupt(f
, req
, &d
);
2606 fuse_do_release(f
, ino
, path
, fi
);
2607 fuse_finish_interrupt(f
, req
, &d
);
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
);
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
);
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
,
2635 struct fuse
*f
= req_fuse_prepare(req
);
2640 pthread_rwlock_rdlock(&f
->tree_lock
);
2641 path
= get_path(f
, ino
);
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
);
2649 pthread_rwlock_unlock(&f
->tree_lock
);
2653 static void fuse_lib_getlk(fuse_req_t req
, fuse_ino_t ino
,
2654 struct fuse_file_info
*fi
, struct flock
*lock
)
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
);
2666 lock_to_flock(conflict
, lock
);
2667 pthread_mutex_unlock(&f
->lock
);
2669 err
= fuse_lock_common(req
, ino
, fi
, lock
, F_GETLK
);
2674 fuse_reply_lock(req
, lock
);
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
,
2683 int err
= fuse_lock_common(req
, ino
, fi
, lock
, should_sleep
? F_SETLKW
: F_SETLK
);
2685 struct fuse
*f
= req_fuse(req
);
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
,
2699 struct fuse
*f
= req_fuse_prepare(req
);
2700 struct fuse_intr_data d
;
2705 pthread_rwlock_rdlock(&f
->tree_lock
);
2706 path
= get_path(f
, ino
);
2708 fuse_prepare_interrupt(f
, req
, &d
);
2709 err
= fuse_fs_bmap(f
->fs
, path
, blocksize
, &idx
);
2710 fuse_finish_interrupt(f
, req
, &d
);
2713 pthread_rwlock_unlock(&f
->tree_lock
);
2715 fuse_reply_bmap(req
, idx
);
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
)
2762 int fuse_loop(struct fuse
*f
)
2765 return fuse_session_loop(f
->se
);
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
);
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),
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),
2821 FUSE_LIB_OPT("modules=%s", modules
, 0),
2822 #endif /* __SOLARIS__ */
2826 static void fuse_lib_help(void)
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"
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"
2847 " -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
2848 #endif /* __SOLARIS__ */
2849 "\n", FUSE_DEFAULT_INTR_SIGNAL
);
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
;
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");
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");
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
);
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];
2944 newfs
= m
->factory(args
, fs
);
2954 #endif /* __SOLARIS__ */
2956 struct fuse_fs
*fuse_fs_new(const struct fuse_operations
*op
, size_t op_size
,
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
));
2968 fprintf(stderr
, "fuse: failed to allocate fuse_fs object\n");
2972 fs
->user_data
= user_data
;
2974 memcpy(&fs
->op
, op
, op_size
);
2978 struct fuse
*fuse_new(struct fuse_chan
*ch
, struct fuse_args
*args
,
2979 const struct fuse_operations
*op
, size_t op_size
,
2985 struct fuse_lowlevel_ops llop
= fuse_path_ops
;
2987 if (fuse_create_context_key() == -1)
2990 f
= (struct fuse
*) calloc(1, sizeof(struct fuse
));
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
);
3001 f
->utime_omit_ok
= fs
->op
.flag_utime_omit_ok
;
3003 /* Oh f**k, this is ugly! */
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)
3018 if (f
->conf
.modules
) {
3022 for (module
= f
->conf
.modules
; module
; module
= next
) {
3024 for (p
= module
; *p
&& *p
!= ':'; p
++);
3025 next
= *p
? p
+ 1 : NULL
;
3027 if (module
[0] && fuse_push_module(f
, module
, args
) == -1)
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;
3044 f
->se
= fuse_lowlevel_new(args
, &llop
, sizeof(llop
), f
);
3046 if (f
->se
== NULL
) {
3049 fuse_lib_help_modules();
3050 #endif /* __SOLARIS__ */
3054 fuse_session_add_chan(f
->se
, ch
);
3058 fprintf(stderr
, "utime_omit_ok: %i\n", f
->utime_omit_ok
);
3059 #endif /* ! __SOLARIS__ */
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
));
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");
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;
3113 out_free_name_table
:
3114 free(f
->name_table
);
3116 fuse_session_destroy(f
->se
);
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
);
3123 free(f
->conf
.modules
);
3124 #endif /* __SOLARIS__ */
3127 out_delete_context_key
:
3128 fuse_delete_context_key();
3133 void fuse_destroy(struct fuse
*f
)
3137 if (f
->conf
.intr
&& f
->intr_installed
)
3138 fuse_restore_intr_signal(f
->conf
.intr_signal
);
3141 struct fuse_context_i
*c
= fuse_get_context_internal();
3143 memset(c
, 0, sizeof(*c
));
3146 for (i
= 0; i
< f
->id_table_size
; i
++) {
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
);
3153 fuse_fs_unlink(f
->fs
, path
);
3160 for (i
= 0; i
< f
->id_table_size
; i
++) {
3164 for (node
= f
->id_table
[i
]; node
!= NULL
; node
= next
) {
3165 next
= node
->id_next
;
3170 free(f
->name_table
);
3171 pthread_mutex_destroy(&f
->lock
);
3172 pthread_rwlock_destroy(&f
->tree_lock
);
3173 fuse_session_destroy(f
->se
);
3175 free(f
->conf
.modules
);
3176 #endif /* __SOLARIS__ */
3178 fuse_delete_context_key();