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