/[fuse_dbi]/fuse/cvs/lib/fuse.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /fuse/cvs/lib/fuse.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations)
Wed Aug 4 11:36:44 2004 UTC (19 years, 9 months ago) by dpavlin
File MIME type: text/plain
File size: 45280 byte(s)
import current CVS of fuse

1 dpavlin 4 /*
2     FUSE: Filesystem in Userspace
3     Copyright (C) 2001-2004 Miklos Szeredi <miklos@szeredi.hu>
4    
5     This program can be distributed under the terms of the GNU LGPL.
6     See the file COPYING.LIB
7     */
8    
9     #include <config.h>
10     #include "fuse_i.h"
11     #include <linux/fuse.h>
12    
13     #include <string.h>
14     #include <stdlib.h>
15     #include <unistd.h>
16     #include <limits.h>
17     #include <errno.h>
18     #include <sys/param.h>
19    
20     #define FUSE_MAX_PATH 4096
21     #define PARAM(inarg) (((char *)(inarg)) + sizeof(*inarg))
22    
23     #define ENTRY_REVALIDATE_TIME 1 /* sec */
24     #define ATTR_REVALIDATE_TIME 1 /* sec */
25    
26     static const char *opname(enum fuse_opcode opcode)
27     {
28     switch (opcode) {
29     case FUSE_LOOKUP: return "LOOKUP";
30     case FUSE_FORGET: return "FORGET";
31     case FUSE_GETATTR: return "GETATTR";
32     case FUSE_SETATTR: return "SETATTR";
33     case FUSE_READLINK: return "READLINK";
34     case FUSE_SYMLINK: return "SYMLINK";
35     case FUSE_GETDIR: return "GETDIR";
36     case FUSE_MKNOD: return "MKNOD";
37     case FUSE_MKDIR: return "MKDIR";
38     case FUSE_UNLINK: return "UNLINK";
39     case FUSE_RMDIR: return "RMDIR";
40     case FUSE_RENAME: return "RENAME";
41     case FUSE_LINK: return "LINK";
42     case FUSE_OPEN: return "OPEN";
43     case FUSE_READ: return "READ";
44     case FUSE_WRITE: return "WRITE";
45     case FUSE_STATFS: return "STATFS";
46     case FUSE_FLUSH: return "FLUSH";
47     case FUSE_RELEASE: return "RELEASE";
48     case FUSE_FSYNC: return "FSYNC";
49     case FUSE_SETXATTR: return "SETXATTR";
50     case FUSE_GETXATTR: return "GETXATTR";
51     case FUSE_LISTXATTR: return "LISTXATTR";
52     case FUSE_REMOVEXATTR: return "REMOVEXATTR";
53     default: return "???";
54     }
55     }
56    
57    
58     static inline void dec_avail(struct fuse *f)
59     {
60     pthread_mutex_lock(&f->lock);
61     f->numavail --;
62     pthread_mutex_unlock(&f->lock);
63     }
64    
65     static struct node *__get_node(struct fuse *f, fino_t ino)
66     {
67     size_t hash = ino % f->ino_table_size;
68     struct node *node;
69    
70     for (node = f->ino_table[hash]; node != NULL; node = node->ino_next)
71     if (node->ino == ino)
72     return node;
73    
74     return NULL;
75     }
76    
77     static struct node *get_node(struct fuse *f, fino_t ino)
78     {
79     struct node *node = __get_node(f, ino);
80     if (node != NULL)
81     return node;
82    
83     fprintf(stderr, "fuse internal error: inode %lu not found\n", ino);
84     abort();
85     }
86    
87     static void hash_ino(struct fuse *f, struct node *node)
88     {
89     size_t hash = node->ino % f->ino_table_size;
90     node->ino_next = f->ino_table[hash];
91     f->ino_table[hash] = node;
92     }
93    
94     static void unhash_ino(struct fuse *f, struct node *node)
95     {
96     size_t hash = node->ino % f->ino_table_size;
97     struct node **nodep = &f->ino_table[hash];
98    
99     for (; *nodep != NULL; nodep = &(*nodep)->ino_next)
100     if (*nodep == node) {
101     *nodep = node->ino_next;
102     return;
103     }
104     }
105    
106     static fino_t next_ino(struct fuse *f)
107     {
108     do {
109     f->ctr++;
110     if (!f->ctr)
111     f->generation ++;
112     } while (f->ctr == 0 || __get_node(f, f->ctr) != NULL);
113     return f->ctr;
114     }
115    
116     static void free_node(struct node *node)
117     {
118     free(node->name);
119     free(node);
120     }
121    
122     static unsigned int name_hash(struct fuse *f, fino_t parent, const char *name)
123     {
124     unsigned int hash = *name;
125    
126     if (hash)
127     for (name += 1; *name != '\0'; name++)
128     hash = (hash << 5) - hash + *name;
129    
130     return (hash + parent) % f->name_table_size;
131     }
132    
133     static struct node *__lookup_node(struct fuse *f, fino_t parent,
134     const char *name)
135     {
136     size_t hash = name_hash(f, parent, name);
137     struct node *node;
138    
139     for (node = f->name_table[hash]; node != NULL; node = node->name_next)
140     if (node->parent == parent && strcmp(node->name, name) == 0)
141     return node;
142    
143     return NULL;
144     }
145    
146     static struct node *lookup_node(struct fuse *f, fino_t parent,
147     const char *name)
148     {
149     struct node *node;
150    
151     pthread_mutex_lock(&f->lock);
152     node = __lookup_node(f, parent, name);
153     pthread_mutex_unlock(&f->lock);
154     if (node != NULL)
155     return node;
156    
157     fprintf(stderr, "fuse internal error: node %lu/%s not found\n", parent,
158     name);
159     abort();
160     }
161    
162     static void hash_name(struct fuse *f, struct node *node, fino_t parent,
163     const char *name)
164     {
165     size_t hash = name_hash(f, parent, name);
166     node->parent = parent;
167     node->name = strdup(name);
168     node->name_next = f->name_table[hash];
169     f->name_table[hash] = node;
170     }
171    
172     static void unhash_name(struct fuse *f, struct node *node)
173     {
174     if (node->name != NULL) {
175     size_t hash = name_hash(f, node->parent, node->name);
176     struct node **nodep = &f->name_table[hash];
177    
178     for (; *nodep != NULL; nodep = &(*nodep)->name_next)
179     if (*nodep == node) {
180     *nodep = node->name_next;
181     node->name_next = NULL;
182     free(node->name);
183     node->name = NULL;
184     node->parent = 0;
185     return;
186     }
187     fprintf(stderr, "fuse internal error: unable to unhash node: %lu\n",
188     node->ino);
189     abort();
190     }
191     }
192    
193     static struct node *find_node(struct fuse *f, fino_t parent, char *name,
194     struct fuse_attr *attr, int version)
195     {
196     struct node *node;
197     int mode = attr->mode & S_IFMT;
198     int rdev = 0;
199    
200     if (S_ISCHR(mode) || S_ISBLK(mode))
201     rdev = attr->rdev;
202    
203     pthread_mutex_lock(&f->lock);
204     node = __lookup_node(f, parent, name);
205     if (node != NULL) {
206     if (node->mode == mode && node->rdev == rdev)
207     goto out;
208    
209     unhash_name(f, node);
210     }
211    
212     node = (struct node *) calloc(1, sizeof(struct node));
213     node->mode = mode;
214     node->rdev = rdev;
215     node->open_count = 0;
216     node->is_hidden = 0;
217     node->ino = next_ino(f);
218     node->generation = f->generation;
219     hash_ino(f, node);
220     hash_name(f, node, parent, name);
221    
222     out:
223     node->version = version;
224     pthread_mutex_unlock(&f->lock);
225     return node;
226     }
227    
228     static int path_lookup(struct fuse *f, const char *path, fino_t *inop)
229     {
230     fino_t ino;
231     int err;
232     char *s;
233     char *name;
234     char *tmp = strdup(path);
235     if (!tmp)
236     return -ENOMEM;
237    
238     pthread_mutex_lock(&f->lock);
239     ino = FUSE_ROOT_INO;
240     err = 0;
241     for (s = tmp; (name = strsep(&s, "/")) != NULL; ) {
242     if (name[0]) {
243     struct node *node = __lookup_node(f, ino, name);
244     if (node == NULL) {
245     err = -ENOENT;
246     break;
247     }
248     ino = node->ino;
249     }
250     }
251     pthread_mutex_unlock(&f->lock);
252     free(tmp);
253     if (!err)
254     *inop = ino;
255    
256     return err;
257     }
258    
259     static char *add_name(char *buf, char *s, const char *name)
260     {
261     size_t len = strlen(name);
262     s -= len;
263     if (s <= buf) {
264     fprintf(stderr, "fuse: path too long: ...%s\n", s + len);
265     return NULL;
266     }
267     strncpy(s, name, len);
268     s--;
269     *s = '/';
270    
271     return s;
272     }
273    
274     static char *get_path_name(struct fuse *f, fino_t ino, const char *name)
275     {
276     char buf[FUSE_MAX_PATH];
277     char *s = buf + FUSE_MAX_PATH - 1;
278     struct node *node;
279    
280     *s = '\0';
281    
282     if (name != NULL) {
283     s = add_name(buf, s, name);
284     if (s == NULL)
285     return NULL;
286     }
287    
288     pthread_mutex_lock(&f->lock);
289     for (node = get_node(f, ino); node->ino != FUSE_ROOT_INO;
290     node = get_node(f, node->parent)) {
291     if (node->name == NULL) {
292     s = NULL;
293     break;
294     }
295    
296     s = add_name(buf, s, node->name);
297     if (s == NULL)
298     break;
299     }
300     pthread_mutex_unlock(&f->lock);
301    
302     if (s == NULL)
303     return NULL;
304     else if (*s == '\0')
305     return strdup("/");
306     else
307     return strdup(s);
308     }
309    
310     static char *get_path(struct fuse *f, fino_t ino)
311     {
312     return get_path_name(f, ino, NULL);
313     }
314    
315     static void destroy_node(struct fuse *f, fino_t ino, int version)
316     {
317     struct node *node;
318    
319     pthread_mutex_lock(&f->lock);
320     node = get_node(f, ino);
321     if (node->version == version && ino != FUSE_ROOT_INO) {
322     unhash_name(f, node);
323     unhash_ino(f, node);
324     free_node(node);
325     }
326     pthread_mutex_unlock(&f->lock);
327    
328     }
329    
330     static void remove_node(struct fuse *f, fino_t dir, const char *name)
331     {
332     struct node *node;
333    
334     pthread_mutex_lock(&f->lock);
335     node = __lookup_node(f, dir, name);
336     if (node == NULL) {
337     fprintf(stderr, "fuse internal error: unable to remove node %lu/%s\n",
338     dir, name);
339     abort();
340     }
341     unhash_name(f, node);
342     pthread_mutex_unlock(&f->lock);
343     }
344    
345     static int rename_node(struct fuse *f, fino_t olddir, const char *oldname,
346     fino_t newdir, const char *newname, int hide)
347     {
348     struct node *node;
349     struct node *newnode;
350     int err = 0;
351    
352     pthread_mutex_lock(&f->lock);
353     node = __lookup_node(f, olddir, oldname);
354     newnode = __lookup_node(f, newdir, newname);
355     if (node == NULL) {
356     fprintf(stderr, "fuse internal error: unable to rename node %lu/%s\n",
357     olddir, oldname);
358     abort();
359     }
360    
361     if (newnode != NULL) {
362     if (hide) {
363     fprintf(stderr, "fuse: hidden file got created during hiding\n");
364     err = -1;
365     goto out;
366     }
367     unhash_name(f, newnode);
368     }
369    
370     unhash_name(f, node);
371     hash_name(f, node, newdir, newname);
372     if (hide)
373     node->is_hidden = 1;
374    
375     out:
376     pthread_mutex_unlock(&f->lock);
377     return err;
378     }
379    
380     static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
381     {
382     attr->mode = stbuf->st_mode;
383     attr->nlink = stbuf->st_nlink;
384     attr->uid = stbuf->st_uid;
385     attr->gid = stbuf->st_gid;
386     attr->rdev = stbuf->st_rdev;
387     attr->size = stbuf->st_size;
388     attr->blocks = stbuf->st_blocks;
389     attr->atime = stbuf->st_atime;
390     attr->mtime = stbuf->st_mtime;
391     attr->ctime = stbuf->st_ctime;
392     #ifdef HAVE_STRUCT_STAT_ST_ATIM
393     attr->atimensec = stbuf->st_atim.tv_nsec;
394     attr->mtimensec = stbuf->st_mtim.tv_nsec;
395     attr->ctimensec = stbuf->st_ctim.tv_nsec;
396     #endif
397     }
398    
399     static int fill_dir(struct fuse_dirhandle *dh, char *name, int type)
400     {
401     struct fuse_dirent dirent;
402     size_t reclen;
403     size_t res;
404    
405     dirent.ino = (unsigned long) -1;
406     dirent.namelen = strlen(name);
407     strncpy(dirent.name, name, sizeof(dirent.name));
408     dirent.type = type;
409     reclen = FUSE_DIRENT_SIZE(&dirent);
410     res = fwrite(&dirent, reclen, 1, dh->fp);
411     if (res == 0) {
412     perror("fuse: writing directory file");
413     return -EIO;
414     }
415     return 0;
416     }
417    
418     static int send_reply_raw(struct fuse *f, char *outbuf, size_t outsize,
419     int locked)
420     {
421     int res;
422    
423     if ((f->flags & FUSE_DEBUG)) {
424     struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
425     printf(" unique: %i, error: %i (%s), outsize: %i\n", out->unique,
426     out->error, strerror(-out->error), outsize);
427     fflush(stdout);
428     }
429    
430     /* This needs to be done before the reply, otherwise the scheduler
431     could play tricks with us, and only let the counter be increased
432     long after the operation is done */
433     if (!locked)
434     pthread_mutex_lock(&f->lock);
435     f->numavail ++;
436     if (!locked)
437     pthread_mutex_unlock(&f->lock);
438    
439     res = write(f->fd, outbuf, outsize);
440     if (res == -1) {
441     /* ENOENT means the operation was interrupted */
442     if (!f->exited && errno != ENOENT)
443     perror("fuse: writing device");
444     return -errno;
445     }
446     return 0;
447     }
448    
449     static int __send_reply(struct fuse *f, struct fuse_in_header *in, int error,
450     void *arg, size_t argsize, int locked)
451     {
452     int res;
453     char *outbuf;
454     size_t outsize;
455     struct fuse_out_header *out;
456    
457     if (error <= -1000 || error > 0) {
458     fprintf(stderr, "fuse: bad error value: %i\n", error);
459     error = -ERANGE;
460     }
461    
462     if (error)
463     argsize = 0;
464    
465     outsize = sizeof(struct fuse_out_header) + argsize;
466     outbuf = (char *) malloc(outsize);
467     out = (struct fuse_out_header *) outbuf;
468     memset(out, 0, sizeof(struct fuse_out_header));
469     out->unique = in->unique;
470     out->error = error;
471     if (argsize != 0)
472     memcpy(outbuf + sizeof(struct fuse_out_header), arg, argsize);
473    
474     res = send_reply_raw(f, outbuf, outsize, locked);
475     free(outbuf);
476    
477     return res;
478     }
479    
480     static int send_reply(struct fuse *f, struct fuse_in_header *in, int error,
481     void *arg, size_t argsize)
482     {
483     return __send_reply(f, in, error, arg, argsize, 0);
484     }
485    
486     static int is_open(struct fuse *f, fino_t dir, const char *name)
487     {
488     struct node *node;
489     int isopen = 0;
490     pthread_mutex_lock(&f->lock);
491     node = __lookup_node(f, dir, name);
492     if (node && node->open_count > 0)
493     isopen = 1;
494     pthread_mutex_unlock(&f->lock);
495     return isopen;
496     }
497    
498     static char *hidden_name(struct fuse *f, fino_t dir, const char *oldname,
499     char *newname, size_t bufsize)
500     {
501     struct stat buf;
502     struct node *node;
503     struct node *newnode;
504     char *newpath;
505     int res;
506     int failctr = 10;
507    
508     if (!f->op.getattr)
509     return NULL;
510    
511     do {
512     node = lookup_node(f, dir, oldname);
513     pthread_mutex_lock(&f->lock);
514     do {
515     f->hidectr ++;
516     snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
517     (unsigned int) node->ino, f->hidectr);
518     newnode = __lookup_node(f, dir, newname);
519     } while(newnode);
520     pthread_mutex_unlock(&f->lock);
521    
522     newpath = get_path_name(f, dir, newname);
523     if (!newpath)
524     break;
525    
526     res = f->op.getattr(newpath, &buf);
527     if (res != 0)
528     break;
529     free(newpath);
530     newpath = NULL;
531     } while(--failctr);
532    
533     return newpath;
534     }
535    
536     static int hide_node(struct fuse *f, const char *oldpath, fino_t dir,
537     const char *oldname)
538     {
539     char newname[64];
540     char *newpath;
541     int err = -1;
542    
543     if (!f->op.rename || !f->op.unlink)
544     return -EBUSY;
545    
546     newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
547     if (newpath) {
548     err = f->op.rename(oldpath, newpath);
549     if (!err)
550     err = rename_node(f, dir, oldname, dir, newname, 1);
551     free(newpath);
552     }
553     if (err)
554     return -EBUSY;
555    
556     return 0;
557     }
558    
559     static int lookup_path(struct fuse *f, fino_t ino, int version, char *name,
560     const char *path, struct fuse_entry_out *arg)
561     {
562     int res;
563     struct stat buf;
564    
565     res = f->op.getattr(path, &buf);
566     if (res == 0) {
567     struct node *node;
568    
569     memset(arg, 0, sizeof(struct fuse_entry_out));
570     convert_stat(&buf, &arg->attr);
571     node = find_node(f, ino, name, &arg->attr, version);
572     arg->ino = node->ino;
573     arg->generation = node->generation;
574     arg->entry_valid = ENTRY_REVALIDATE_TIME;
575     arg->entry_valid_nsec = 0;
576     arg->attr_valid = ATTR_REVALIDATE_TIME;
577     arg->attr_valid_nsec = 0;
578     if (f->flags & FUSE_DEBUG) {
579     printf(" INO: %li\n", arg->ino);
580     fflush(stdout);
581     }
582     }
583     return res;
584     }
585    
586     static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name)
587     {
588     int res;
589     int res2;
590     char *path;
591     struct fuse_entry_out arg;
592    
593     res = -ENOENT;
594     path = get_path_name(f, in->ino, name);
595     if (path != NULL) {
596     if (f->flags & FUSE_DEBUG) {
597     printf("LOOKUP %s\n", path);
598     fflush(stdout);
599     }
600     res = -ENOSYS;
601     if (f->op.getattr)
602     res = lookup_path(f, in->ino, in->unique, name, path, &arg);
603     free(path);
604     }
605     res2 = send_reply(f, in, res, &arg, sizeof(arg));
606     if (res == 0 && res2 == -ENOENT)
607     destroy_node(f, arg.ino, in->unique);
608     }
609    
610     static void do_forget(struct fuse *f, struct fuse_in_header *in,
611     struct fuse_forget_in *arg)
612     {
613     if (f->flags & FUSE_DEBUG) {
614     printf("FORGET %li/%i\n", in->ino, arg->version);
615     fflush(stdout);
616     }
617     destroy_node(f, in->ino, arg->version);
618     }
619    
620     static void do_getattr(struct fuse *f, struct fuse_in_header *in)
621     {
622     int res;
623     char *path;
624     struct stat buf;
625     struct fuse_attr_out arg;
626    
627     res = -ENOENT;
628     path = get_path(f, in->ino);
629     if (path != NULL) {
630     res = -ENOSYS;
631     if (f->op.getattr)
632     res = f->op.getattr(path, &buf);
633     free(path);
634     }
635    
636     if (res == 0) {
637     memset(&arg, 0, sizeof(struct fuse_attr_out));
638     arg.attr_valid = ATTR_REVALIDATE_TIME;
639     arg.attr_valid_nsec = 0;
640     convert_stat(&buf, &arg.attr);
641     }
642    
643     send_reply(f, in, res, &arg, sizeof(arg));
644     }
645    
646     static int do_chmod(struct fuse *f, const char *path, struct fuse_attr *attr)
647     {
648     int res;
649    
650     res = -ENOSYS;
651     if (f->op.chmod)
652     res = f->op.chmod(path, attr->mode);
653    
654     return res;
655     }
656    
657     static int do_chown(struct fuse *f, const char *path, struct fuse_attr *attr,
658     int valid)
659     {
660     int res;
661     uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1;
662     gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1;
663    
664     res = -ENOSYS;
665     if (f->op.chown)
666     res = f->op.chown(path, uid, gid);
667    
668     return res;
669     }
670    
671     static int do_truncate(struct fuse *f, const char *path,
672     struct fuse_attr *attr)
673     {
674     int res;
675    
676     res = -ENOSYS;
677     if (f->op.truncate)
678     res = f->op.truncate(path, attr->size);
679    
680     return res;
681     }
682    
683     static int do_utime(struct fuse *f, const char *path, struct fuse_attr *attr)
684     {
685     int res;
686     struct utimbuf buf;
687     buf.actime = attr->atime;
688     buf.modtime = attr->mtime;
689     res = -ENOSYS;
690     if (f->op.utime)
691     res = f->op.utime(path, &buf);
692    
693     return res;
694     }
695    
696     static void do_setattr(struct fuse *f, struct fuse_in_header *in,
697     struct fuse_setattr_in *arg)
698     {
699     int res;
700     char *path;
701     int valid = arg->valid;
702     struct fuse_attr *attr = &arg->attr;
703     struct fuse_attr_out outarg;
704    
705     res = -ENOENT;
706     path = get_path(f, in->ino);
707     if (path != NULL) {
708     res = -ENOSYS;
709     if (f->op.getattr) {
710     res = 0;
711     if (!res && (valid & FATTR_MODE))
712     res = do_chmod(f, path, attr);
713     if (!res && (valid & (FATTR_UID | FATTR_GID)))
714     res = do_chown(f, path, attr, valid);
715     if (!res && (valid & FATTR_SIZE))
716     res = do_truncate(f, path, attr);
717     if (!res && (valid & (FATTR_ATIME | FATTR_MTIME)) ==
718     (FATTR_ATIME | FATTR_MTIME))
719     res = do_utime(f, path, attr);
720     if (!res) {
721     struct stat buf;
722     res = f->op.getattr(path, &buf);
723     if (!res) {
724     memset(&outarg, 0, sizeof(struct fuse_attr_out));
725     outarg.attr_valid = ATTR_REVALIDATE_TIME;
726     outarg.attr_valid_nsec = 0;
727     convert_stat(&buf, &outarg.attr);
728     }
729     }
730     }
731     free(path);
732     }
733     send_reply(f, in, res, &outarg, sizeof(outarg));
734     }
735    
736     static void do_readlink(struct fuse *f, struct fuse_in_header *in)
737     {
738     int res;
739     char link[PATH_MAX + 1];
740     char *path;
741    
742     res = -ENOENT;
743     path = get_path(f, in->ino);
744     if (path != NULL) {
745     res = -ENOSYS;
746     if (f->op.readlink)
747     res = f->op.readlink(path, link, sizeof(link));
748     free(path);
749     }
750     link[PATH_MAX] = '\0';
751     send_reply(f, in, res, link, res == 0 ? strlen(link) : 0);
752     }
753    
754     static void do_getdir(struct fuse *f, struct fuse_in_header *in)
755     {
756     int res;
757     struct fuse_getdir_out arg;
758     struct fuse_dirhandle dh;
759     char *path;
760    
761     dh.fuse = f;
762     dh.fp = tmpfile();
763     dh.dir = in->ino;
764     res = -ENOENT;
765     path = get_path(f, in->ino);
766     if (path != NULL) {
767     res = -ENOSYS;
768     if (f->op.getdir)
769     res = f->op.getdir(path, &dh, (fuse_dirfil_t) fill_dir);
770     free(path);
771     }
772     fflush(dh.fp);
773    
774     memset(&arg, 0, sizeof(struct fuse_getdir_out));
775     arg.fd = fileno(dh.fp);
776     send_reply(f, in, res, &arg, sizeof(arg));
777     fclose(dh.fp);
778     }
779    
780     static void do_mknod(struct fuse *f, struct fuse_in_header *in,
781     struct fuse_mknod_in *inarg)
782     {
783     int res;
784     int res2;
785     char *path;
786     char *name = PARAM(inarg);
787     struct fuse_entry_out outarg;
788    
789     res = -ENOENT;
790     path = get_path_name(f, in->ino, name);
791     if (path != NULL) {
792     if (f->flags & FUSE_DEBUG) {
793     printf("MKNOD %s\n", path);
794     fflush(stdout);
795     }
796     res = -ENOSYS;
797     if (f->op.mknod && f->op.getattr) {
798     res = f->op.mknod(path, inarg->mode, inarg->rdev);
799     if (res == 0)
800     res = lookup_path(f, in->ino, in->unique, name, path, &outarg);
801     }
802     free(path);
803     }
804     res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
805     if (res == 0 && res2 == -ENOENT)
806     destroy_node(f, outarg.ino, in->unique);
807     }
808    
809     static void do_mkdir(struct fuse *f, struct fuse_in_header *in,
810     struct fuse_mkdir_in *inarg)
811     {
812     int res;
813     int res2;
814     char *path;
815     char *name = PARAM(inarg);
816     struct fuse_entry_out outarg;
817    
818     res = -ENOENT;
819     path = get_path_name(f, in->ino, name);
820     if (path != NULL) {
821     if (f->flags & FUSE_DEBUG) {
822     printf("MKDIR %s\n", path);
823     fflush(stdout);
824     }
825     res = -ENOSYS;
826     if (f->op.mkdir && f->op.getattr) {
827     res = f->op.mkdir(path, inarg->mode);
828     if (res == 0)
829     res = lookup_path(f, in->ino, in->unique, name, path, &outarg);
830     }
831     free(path);
832     }
833     res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
834     if (res == 0 && res2 == -ENOENT)
835     destroy_node(f, outarg.ino, in->unique);
836     }
837    
838     static void do_unlink(struct fuse *f, struct fuse_in_header *in, char *name)
839     {
840     int res;
841     char *path;
842    
843     res = -ENOENT;
844     path = get_path_name(f, in->ino, name);
845     if (path != NULL) {
846     if (f->flags & FUSE_DEBUG) {
847     printf("UNLINK %s\n", path);
848     fflush(stdout);
849     }
850     res = -ENOSYS;
851     if (f->op.unlink) {
852     if (!(f->flags & FUSE_HARD_REMOVE) && is_open(f, in->ino, name))
853     res = hide_node(f, path, in->ino, name);
854     else {
855     res = f->op.unlink(path);
856     if (res == 0)
857     remove_node(f, in->ino, name);
858     }
859     }
860     free(path);
861     }
862     send_reply(f, in, res, NULL, 0);
863     }
864    
865     static void do_rmdir(struct fuse *f, struct fuse_in_header *in, char *name)
866     {
867     int res;
868     char *path;
869    
870     res = -ENOENT;
871     path = get_path_name(f, in->ino, name);
872     if (path != NULL) {
873     if (f->flags & FUSE_DEBUG) {
874     printf("RMDIR %s\n", path);
875     fflush(stdout);
876     }
877     res = -ENOSYS;
878     if (f->op.rmdir) {
879     res = f->op.rmdir(path);
880     if (res == 0)
881     remove_node(f, in->ino, name);
882     }
883     free(path);
884     }
885     send_reply(f, in, res, NULL, 0);
886     }
887    
888     static void do_symlink(struct fuse *f, struct fuse_in_header *in, char *name,
889     char *link)
890     {
891     int res;
892     int res2;
893     char *path;
894     struct fuse_entry_out outarg;
895    
896     res = -ENOENT;
897     path = get_path_name(f, in->ino, name);
898     if (path != NULL) {
899     if (f->flags & FUSE_DEBUG) {
900     printf("SYMLINK %s\n", path);
901     fflush(stdout);
902     }
903     res = -ENOSYS;
904     if (f->op.symlink && f->op.getattr) {
905     res = f->op.symlink(link, path);
906     if (res == 0)
907     res = lookup_path(f, in->ino, in->unique, name, path, &outarg);
908     }
909     free(path);
910     }
911     res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
912     if (res == 0 && res2 == -ENOENT)
913     destroy_node(f, outarg.ino, in->unique);
914    
915     }
916    
917     static void do_rename(struct fuse *f, struct fuse_in_header *in,
918     struct fuse_rename_in *inarg)
919     {
920     int res;
921     fino_t olddir = in->ino;
922     fino_t newdir = inarg->newdir;
923     char *oldname = PARAM(inarg);
924     char *newname = oldname + strlen(oldname) + 1;
925     char *oldpath;
926     char *newpath;
927    
928     res = -ENOENT;
929     oldpath = get_path_name(f, olddir, oldname);
930     if (oldpath != NULL) {
931     newpath = get_path_name(f, newdir, newname);
932     if (newpath != NULL) {
933     if (f->flags & FUSE_DEBUG) {
934     printf("RENAME %s -> %s\n", oldpath, newpath);
935     fflush(stdout);
936     }
937     res = -ENOSYS;
938     if (f->op.rename) {
939     res = 0;
940     if (!(f->flags & FUSE_HARD_REMOVE) &&
941     is_open(f, newdir, newname))
942     res = hide_node(f, newpath, newdir, newname);
943     if (res == 0) {
944     res = f->op.rename(oldpath, newpath);
945     if (res == 0)
946     rename_node(f, olddir, oldname, newdir, newname, 0);
947     }
948     }
949     free(newpath);
950     }
951     free(oldpath);
952     }
953     send_reply(f, in, res, NULL, 0);
954     }
955    
956     static void do_link(struct fuse *f, struct fuse_in_header *in,
957     struct fuse_link_in *arg)
958     {
959     int res;
960     int res2;
961     char *oldpath;
962     char *newpath;
963     char *name = PARAM(arg);
964     struct fuse_entry_out outarg;
965    
966     res = -ENOENT;
967     oldpath = get_path(f, in->ino);
968     if (oldpath != NULL) {
969     newpath = get_path_name(f, arg->newdir, name);
970     if (newpath != NULL) {
971     if (f->flags & FUSE_DEBUG) {
972     printf("LINK %s\n", newpath);
973     fflush(stdout);
974     }
975     res = -ENOSYS;
976     if (f->op.link && f->op.getattr) {
977     res = f->op.link(oldpath, newpath);
978     if (res == 0)
979     res = lookup_path(f, arg->newdir, in->unique, name,
980     newpath, &outarg);
981     }
982     free(newpath);
983     }
984     free(oldpath);
985     }
986     res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
987     if (res == 0 && res2 == -ENOENT)
988     destroy_node(f, outarg.ino, in->unique);
989     }
990    
991     static void do_open(struct fuse *f, struct fuse_in_header *in,
992     struct fuse_open_in *arg)
993     {
994     int res;
995     char *path;
996     struct fuse_open_out outarg;
997    
998     res = -ENOENT;
999     path = get_path(f, in->ino);
1000     if (path != NULL) {
1001     res = -ENOSYS;
1002     if (f->op.open)
1003     res = f->op.open(path, arg->flags);
1004     }
1005     if (res == 0) {
1006     int res2;
1007    
1008     /* If the request is interrupted the lock must be held until
1009     the cancellation is finished. Otherwise there could be
1010     races with rename/unlink, against which the kernel can't
1011     protect */
1012     pthread_mutex_lock(&f->lock);
1013     f->fh_ctr ++;
1014     outarg.fh = f->fh_ctr;
1015     if (f->flags & FUSE_DEBUG) {
1016     printf("OPEN[%u] flags: 0x%x\n", outarg.fh, arg->flags);
1017     fflush(stdout);
1018     }
1019    
1020     res2 = __send_reply(f, in, res, &outarg, sizeof(outarg), 1);
1021     if(res2 == -ENOENT) {
1022     /* The open syscall was interrupted, so it must be cancelled */
1023     if(f->op.release)
1024     f->op.release(path, arg->flags);
1025     } else
1026     get_node(f, in->ino)->open_count ++;
1027     pthread_mutex_unlock(&f->lock);
1028    
1029     } else
1030     send_reply(f, in, res, NULL, 0);
1031    
1032     if (path)
1033     free(path);
1034     }
1035    
1036     static void do_flush(struct fuse *f, struct fuse_in_header *in,
1037     struct fuse_flush_in *arg)
1038     {
1039     char *path;
1040     int res;
1041    
1042     res = -ENOENT;
1043     path = get_path(f, in->ino);
1044     if (path != NULL) {
1045     if (f->flags & FUSE_DEBUG) {
1046     printf("FLUSH[%u]\n", arg->fh);
1047     fflush(stdout);
1048     }
1049     res = -ENOSYS;
1050     if (f->op.flush)
1051     res = f->op.flush(path);
1052     free(path);
1053     }
1054     send_reply(f, in, res, NULL, 0);
1055     }
1056    
1057     static void do_release(struct fuse *f, struct fuse_in_header *in,
1058     struct fuse_release_in *arg)
1059     {
1060     struct node *node;
1061     char *path;
1062    
1063     pthread_mutex_lock(&f->lock);
1064     node = get_node(f, in->ino);
1065     --node->open_count;
1066     pthread_mutex_unlock(&f->lock);
1067    
1068     path = get_path(f, in->ino);
1069     if (path != NULL) {
1070     if (f->flags & FUSE_DEBUG) {
1071     printf("RELEASE[%u]\n", arg->fh);
1072     fflush(stdout);
1073     }
1074     if (f->op.release)
1075     f->op.release(path, arg->flags);
1076    
1077     if(node->is_hidden && node->open_count == 0)
1078     /* can now clean up this hidden file */
1079     f->op.unlink(path);
1080    
1081     free(path);
1082     }
1083     send_reply(f, in, 0, NULL, 0);
1084     }
1085    
1086     static void do_read(struct fuse *f, struct fuse_in_header *in,
1087     struct fuse_read_in *arg)
1088     {
1089     int res;
1090     char *path;
1091     char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + arg->size);
1092     struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
1093     char *buf = outbuf + sizeof(struct fuse_out_header);
1094     size_t size;
1095     size_t outsize;
1096    
1097     res = -ENOENT;
1098     path = get_path(f, in->ino);
1099     if (path != NULL) {
1100     if (f->flags & FUSE_DEBUG) {
1101     printf("READ[%u] %u bytes from %llu\n", arg->fh, arg->size,
1102     arg->offset);
1103     fflush(stdout);
1104     }
1105    
1106     res = -ENOSYS;
1107     if (f->op.read)
1108     res = f->op.read(path, buf, arg->size, arg->offset);
1109     free(path);
1110     }
1111    
1112     size = 0;
1113     if (res >= 0) {
1114     size = res;
1115     res = 0;
1116     if (f->flags & FUSE_DEBUG) {
1117     printf(" READ[%u] %u bytes\n", arg->fh, size);
1118     fflush(stdout);
1119     }
1120     }
1121     memset(out, 0, sizeof(struct fuse_out_header));
1122     out->unique = in->unique;
1123     out->error = res;
1124     outsize = sizeof(struct fuse_out_header) + size;
1125    
1126     send_reply_raw(f, outbuf, outsize, 0);
1127     free(outbuf);
1128     }
1129    
1130     static void do_write(struct fuse *f, struct fuse_in_header *in,
1131     struct fuse_write_in *arg)
1132     {
1133     int res;
1134     char *path;
1135     struct fuse_write_out outarg;
1136    
1137     res = -ENOENT;
1138     path = get_path(f, in->ino);
1139     if (path != NULL) {
1140     if (f->flags & FUSE_DEBUG) {
1141     printf("WRITE%s[%u] %u bytes to %llu\n",
1142     arg->writepage ? "PAGE" : "", arg->fh, arg->size,
1143     arg->offset);
1144     fflush(stdout);
1145     }
1146    
1147     res = -ENOSYS;
1148     if (f->op.write)
1149     res = f->op.write(path, PARAM(arg), arg->size, arg->offset);
1150     free(path);
1151     }
1152    
1153     if (res >= 0) {
1154     outarg.size = res;
1155     res = 0;
1156     }
1157    
1158     send_reply(f, in, res, &outarg, sizeof(outarg));
1159     }
1160    
1161     static int default_statfs(struct statfs *buf)
1162     {
1163     buf->f_namelen = 255;
1164     buf->f_bsize = 512;
1165     return 0;
1166     }
1167    
1168     static void convert_statfs(struct statfs *statfs, struct fuse_kstatfs *kstatfs)
1169     {
1170     kstatfs->bsize = statfs->f_bsize;
1171     kstatfs->blocks = statfs->f_blocks;
1172     kstatfs->bfree = statfs->f_bfree;
1173     kstatfs->bavail = statfs->f_bavail;
1174     kstatfs->files = statfs->f_files;
1175     kstatfs->ffree = statfs->f_ffree;
1176     kstatfs->namelen = statfs->f_namelen;
1177     }
1178    
1179     static void do_statfs(struct fuse *f, struct fuse_in_header *in)
1180     {
1181     int res;
1182     struct fuse_statfs_out arg;
1183     struct statfs buf;
1184    
1185     memset(&buf, 0, sizeof(struct statfs));
1186     if (f->op.statfs)
1187     res = f->op.statfs("/", &buf);
1188     else
1189     res = default_statfs(&buf);
1190    
1191     if (res == 0)
1192     convert_statfs(&buf, &arg.st);
1193    
1194     send_reply(f, in, res, &arg, sizeof(arg));
1195     }
1196    
1197     static void do_fsync(struct fuse *f, struct fuse_in_header *in,
1198     struct fuse_fsync_in *inarg)
1199     {
1200     int res;
1201     char *path;
1202    
1203     res = -ENOENT;
1204     path = get_path(f, in->ino);
1205     if (path != NULL) {
1206     if (f->flags & FUSE_DEBUG) {
1207     printf("FSYNC[%u]\n", inarg->fh);
1208     fflush(stdout);
1209     }
1210     res = -ENOSYS;
1211     if (f->op.fsync)
1212     res = f->op.fsync(path, inarg->datasync);
1213     free(path);
1214     }
1215     send_reply(f, in, res, NULL, 0);
1216     }
1217    
1218     static void do_setxattr(struct fuse *f, struct fuse_in_header *in,
1219     struct fuse_setxattr_in *arg)
1220     {
1221     int res;
1222     char *path;
1223     char *name = PARAM(arg);
1224     unsigned char *value = name + strlen(name) + 1;
1225    
1226     res = -ENOENT;
1227     path = get_path(f, in->ino);
1228     if (path != NULL) {
1229     res = -ENOSYS;
1230     if (f->op.setxattr)
1231     res = f->op.setxattr(path, name, value, arg->size, arg->flags);
1232     free(path);
1233     }
1234     send_reply(f, in, res, NULL, 0);
1235     }
1236    
1237     static int common_getxattr(struct fuse *f, struct fuse_in_header *in,
1238     const char *name, char *value, size_t size)
1239     {
1240     int res;
1241     char *path;
1242    
1243     res = -ENOENT;
1244     path = get_path(f, in->ino);
1245     if (path != NULL) {
1246     res = -ENOSYS;
1247     if (f->op.getxattr)
1248     res = f->op.getxattr(path, name, value, size);
1249     free(path);
1250     }
1251     return res;
1252     }
1253    
1254     static void do_getxattr_read(struct fuse *f, struct fuse_in_header *in,
1255     const char *name, size_t size)
1256     {
1257     int res;
1258     char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + size);
1259     struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
1260     char *value = outbuf + sizeof(struct fuse_out_header);
1261    
1262     res = common_getxattr(f, in, name, value, size);
1263     size = 0;
1264     if (res > 0) {
1265     size = res;
1266     res = 0;
1267     }
1268     memset(out, 0, sizeof(struct fuse_out_header));
1269     out->unique = in->unique;
1270     out->error = res;
1271    
1272     send_reply_raw(f, outbuf, sizeof(struct fuse_out_header) + size, 0);
1273     free(outbuf);
1274     }
1275    
1276     static void do_getxattr_size(struct fuse *f, struct fuse_in_header *in,
1277     const char *name)
1278     {
1279     int res;
1280     struct fuse_getxattr_out arg;
1281    
1282     res = common_getxattr(f, in, name, NULL, 0);
1283     if (res >= 0) {
1284     arg.size = res;
1285     res = 0;
1286     }
1287     send_reply(f, in, res, &arg, sizeof(arg));
1288     }
1289    
1290     static void do_getxattr(struct fuse *f, struct fuse_in_header *in,
1291     struct fuse_getxattr_in *arg)
1292     {
1293     char *name = PARAM(arg);
1294    
1295     if (arg->size)
1296     do_getxattr_read(f, in, name, arg->size);
1297     else
1298     do_getxattr_size(f, in, name);
1299     }
1300    
1301     static int common_listxattr(struct fuse *f, struct fuse_in_header *in,
1302     char *list, size_t size)
1303     {
1304     int res;
1305     char *path;
1306    
1307     res = -ENOENT;
1308     path = get_path(f, in->ino);
1309     if (path != NULL) {
1310     res = -ENOSYS;
1311     if (f->op.listxattr)
1312     res = f->op.listxattr(path, list, size);
1313     free(path);
1314     }
1315     return res;
1316     }
1317    
1318     static void do_listxattr_read(struct fuse *f, struct fuse_in_header *in,
1319     size_t size)
1320     {
1321     int res;
1322     char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + size);
1323     struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
1324     char *list = outbuf + sizeof(struct fuse_out_header);
1325    
1326     res = common_listxattr(f, in, list, size);
1327     size = 0;
1328     if (res > 0) {
1329     size = res;
1330     res = 0;
1331     }
1332     memset(out, 0, sizeof(struct fuse_out_header));
1333     out->unique = in->unique;
1334     out->error = res;
1335    
1336     send_reply_raw(f, outbuf, sizeof(struct fuse_out_header) + size, 0);
1337     free(outbuf);
1338     }
1339    
1340     static void do_listxattr_size(struct fuse *f, struct fuse_in_header *in)
1341     {
1342     int res;
1343     struct fuse_getxattr_out arg;
1344    
1345     res = common_listxattr(f, in, NULL, 0);
1346     if (res >= 0) {
1347     arg.size = res;
1348     res = 0;
1349     }
1350     send_reply(f, in, res, &arg, sizeof(arg));
1351     }
1352    
1353     static void do_listxattr(struct fuse *f, struct fuse_in_header *in,
1354     struct fuse_getxattr_in *arg)
1355     {
1356     if (arg->size)
1357     do_listxattr_read(f, in, arg->size);
1358     else
1359     do_listxattr_size(f, in);
1360     }
1361    
1362     static void do_removexattr(struct fuse *f, struct fuse_in_header *in,
1363     char *name)
1364     {
1365     int res;
1366     char *path;
1367    
1368     res = -ENOENT;
1369     path = get_path(f, in->ino);
1370     if (path != NULL) {
1371     res = -ENOSYS;
1372     if (f->op.removexattr)
1373     res = f->op.removexattr(path, name);
1374     free(path);
1375     }
1376     send_reply(f, in, res, NULL, 0);
1377     }
1378    
1379    
1380     static void free_cmd(struct fuse_cmd *cmd)
1381     {
1382     free(cmd->buf);
1383     free(cmd);
1384     }
1385    
1386     void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
1387     {
1388     struct fuse_in_header *in = (struct fuse_in_header *) cmd->buf;
1389     void *inarg = cmd->buf + sizeof(struct fuse_in_header);
1390     size_t argsize;
1391     struct fuse_context *ctx = fuse_get_context(f);
1392    
1393     dec_avail(f);
1394    
1395     if ((f->flags & FUSE_DEBUG)) {
1396     printf("unique: %i, opcode: %s (%i), ino: %li, insize: %i\n",
1397     in->unique, opname(in->opcode), in->opcode, in->ino,
1398     cmd->buflen);
1399     fflush(stdout);
1400     }
1401    
1402     ctx->uid = in->uid;
1403     ctx->gid = in->gid;
1404    
1405     argsize = cmd->buflen - sizeof(struct fuse_in_header);
1406    
1407     switch (in->opcode) {
1408     case FUSE_LOOKUP:
1409     do_lookup(f, in, (char *) inarg);
1410     break;
1411    
1412     case FUSE_GETATTR:
1413     do_getattr(f, in);
1414     break;
1415    
1416     case FUSE_SETATTR:
1417     do_setattr(f, in, (struct fuse_setattr_in *) inarg);
1418     break;
1419    
1420     case FUSE_READLINK:
1421     do_readlink(f, in);
1422     break;
1423    
1424     case FUSE_GETDIR:
1425     do_getdir(f, in);
1426     break;
1427    
1428     case FUSE_MKNOD:
1429     do_mknod(f, in, (struct fuse_mknod_in *) inarg);
1430     break;
1431    
1432     case FUSE_MKDIR:
1433     do_mkdir(f, in, (struct fuse_mkdir_in *) inarg);
1434     break;
1435    
1436     case FUSE_UNLINK:
1437     do_unlink(f, in, (char *) inarg);
1438     break;
1439    
1440     case FUSE_RMDIR:
1441     do_rmdir(f, in, (char *) inarg);
1442     break;
1443    
1444     case FUSE_SYMLINK:
1445     do_symlink(f, in, (char *) inarg,
1446     ((char *) inarg) + strlen((char *) inarg) + 1);
1447     break;
1448    
1449     case FUSE_RENAME:
1450     do_rename(f, in, (struct fuse_rename_in *) inarg);
1451     break;
1452    
1453     case FUSE_LINK:
1454     do_link(f, in, (struct fuse_link_in *) inarg);
1455     break;
1456    
1457     case FUSE_OPEN:
1458     do_open(f, in, (struct fuse_open_in *) inarg);
1459     break;
1460    
1461     case FUSE_FLUSH:
1462     do_flush(f, in, (struct fuse_flush_in *) inarg);
1463     break;
1464    
1465     case FUSE_RELEASE:
1466     do_release(f, in, (struct fuse_release_in *) inarg);
1467     break;
1468    
1469     case FUSE_READ:
1470     do_read(f, in, (struct fuse_read_in *) inarg);
1471     break;
1472    
1473     case FUSE_WRITE:
1474     do_write(f, in, (struct fuse_write_in *) inarg);
1475     break;
1476    
1477     case FUSE_STATFS:
1478     do_statfs(f, in);
1479     break;
1480    
1481     case FUSE_FSYNC:
1482     do_fsync(f, in, (struct fuse_fsync_in *) inarg);
1483     break;
1484    
1485     case FUSE_SETXATTR:
1486     do_setxattr(f, in, (struct fuse_setxattr_in *) inarg);
1487     break;
1488    
1489     case FUSE_GETXATTR:
1490     do_getxattr(f, in, (struct fuse_getxattr_in *) inarg);
1491     break;
1492    
1493     case FUSE_LISTXATTR:
1494     do_listxattr(f, in, (struct fuse_getxattr_in *) inarg);
1495     break;
1496    
1497     case FUSE_REMOVEXATTR:
1498     do_removexattr(f, in, (char *) inarg);
1499     break;
1500    
1501     default:
1502     send_reply(f, in, -ENOSYS, NULL, 0);
1503     }
1504    
1505     free_cmd(cmd);
1506     }
1507    
1508     int __fuse_exited(struct fuse* f)
1509     {
1510     return f->exited;
1511     }
1512    
1513     struct fuse_cmd *__fuse_read_cmd(struct fuse *f)
1514     {
1515     ssize_t res;
1516     struct fuse_cmd *cmd;
1517     struct fuse_in_header *in;
1518     void *inarg;
1519    
1520     cmd = (struct fuse_cmd *) malloc(sizeof(struct fuse_cmd));
1521     cmd->buf = (char *) malloc(FUSE_MAX_IN);
1522     in = (struct fuse_in_header *) cmd->buf;
1523     inarg = cmd->buf + sizeof(struct fuse_in_header);
1524    
1525     res = read(f->fd, cmd->buf, FUSE_MAX_IN);
1526     if (res == -1) {
1527     free_cmd(cmd);
1528     if (__fuse_exited(f) || errno == EINTR)
1529     return NULL;
1530    
1531     /* ENODEV means we got unmounted, so we silenty return failure */
1532     if (errno != ENODEV) {
1533     /* BAD... This will happen again */
1534     perror("fuse: reading device");
1535     }
1536    
1537     fuse_exit(f);
1538     return NULL;
1539     }
1540     if ((size_t) res < sizeof(struct fuse_in_header)) {
1541     free_cmd(cmd);
1542     /* Cannot happen */
1543     fprintf(stderr, "short read on fuse device\n");
1544     fuse_exit(f);
1545     return NULL;
1546     }
1547     cmd->buflen = res;
1548    
1549     /* Forget is special, it can be done without messing with threads. */
1550     if (in->opcode == FUSE_FORGET) {
1551     do_forget(f, in, (struct fuse_forget_in *) inarg);
1552     free_cmd(cmd);
1553     return NULL;
1554     }
1555    
1556     return cmd;
1557     }
1558    
1559     void fuse_loop(struct fuse *f)
1560     {
1561     if (f == NULL)
1562     return;
1563    
1564     while (1) {
1565     struct fuse_cmd *cmd;
1566    
1567     if (__fuse_exited(f))
1568     return;
1569    
1570     cmd = __fuse_read_cmd(f);
1571     if (cmd == NULL)
1572     continue;
1573    
1574     __fuse_process_cmd(f, cmd);
1575     }
1576     }
1577    
1578     int fuse_invalidate(struct fuse *f, const char *path)
1579     {
1580     int res;
1581     int err;
1582     fino_t ino;
1583     struct fuse_user_header h;
1584    
1585     err = path_lookup(f, path, &ino);
1586     if (err) {
1587     if (err == -ENOENT)
1588     return 0;
1589     else
1590     return err;
1591     }
1592    
1593     memset(&h, 0, sizeof(struct fuse_user_header));
1594     h.opcode = FUSE_INVALIDATE;
1595     h.ino = ino;
1596    
1597     if ((f->flags & FUSE_DEBUG)) {
1598     printf("INVALIDATE ino: %li\n", ino);
1599     fflush(stdout);
1600     }
1601    
1602     res = write(f->fd, &h, sizeof(struct fuse_user_header));
1603     if (res == -1) {
1604     if (errno != ENOENT) {
1605     perror("fuse: writing device");
1606     return -errno;
1607     }
1608     }
1609     return 0;
1610     }
1611    
1612     void fuse_exit(struct fuse *f)
1613     {
1614     f->exited = 1;
1615     }
1616    
1617     struct fuse_context *fuse_get_context(struct fuse *f)
1618     {
1619     if (f->getcontext)
1620     return f->getcontext(f);
1621     else
1622     return &f->context;
1623     }
1624    
1625     static int check_version(struct fuse *f)
1626     {
1627     int res;
1628     FILE *vf = fopen(FUSE_VERSION_FILE, "r");
1629     if (vf == NULL) {
1630     fprintf(stderr, "fuse: kernel interface too old, need >= %i.%i\n",
1631     FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
1632     return -1;
1633     }
1634     res = fscanf(vf, "%i.%i", &f->majorver, &f->minorver);
1635     fclose(vf);
1636     if (res != 2) {
1637     fprintf(stderr, "fuse: error reading %s\n", FUSE_VERSION_FILE);
1638     return -1;
1639     }
1640     if (f->majorver != FUSE_KERNEL_VERSION) {
1641     fprintf(stderr, "fuse: bad kernel interface major version: needs %i\n",
1642     FUSE_KERNEL_VERSION);
1643     return -1;
1644     }
1645     if (f->minorver < FUSE_KERNEL_MINOR_VERSION) {
1646     fprintf(stderr, "fuse: kernel interface too old: need >= %i.%i",
1647     FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
1648     return -1;
1649     }
1650    
1651     return 0;
1652     }
1653    
1654    
1655     int fuse_is_lib_option(const char *opt)
1656     {
1657     if (strcmp(opt, "debug") == 0 ||
1658     strcmp(opt, "hard_remove") == 0)
1659     return 1;
1660     else
1661     return 0;
1662     }
1663    
1664     static void parse_lib_opts(struct fuse *f, const char *opts)
1665     {
1666     if (opts) {
1667     char *xopts = strdup(opts);
1668     char *s = xopts;
1669     char *opt;
1670    
1671     while((opt = strsep(&s, ","))) {
1672     if (strcmp(opt, "debug") == 0)
1673     f->flags |= FUSE_DEBUG;
1674     else if (strcmp(opt, "hard_remove") == 0)
1675     f->flags |= FUSE_HARD_REMOVE;
1676     else
1677     fprintf(stderr, "fuse: warning: unknown option `%s'\n", opt);
1678     }
1679     free(xopts);
1680     }
1681     }
1682    
1683     struct fuse *fuse_new(int fd, const char *opts, const struct fuse_operations *op)
1684     {
1685     struct fuse *f;
1686     struct node *root;
1687    
1688     f = (struct fuse *) calloc(1, sizeof(struct fuse));
1689    
1690     if (check_version(f) == -1) {
1691     free(f);
1692     return NULL;
1693     }
1694    
1695     parse_lib_opts(f, opts);
1696     f->fd = fd;
1697     f->ctr = 0;
1698     f->generation = 0;
1699     /* FIXME: Dynamic hash table */
1700     f->name_table_size = 14057;
1701     f->name_table = (struct node **)
1702     calloc(1, sizeof(struct node *) * f->name_table_size);
1703     f->ino_table_size = 14057;
1704     f->ino_table = (struct node **)
1705     calloc(1, sizeof(struct node *) * f->ino_table_size);
1706     pthread_mutex_init(&f->lock, NULL);
1707     f->numworker = 0;
1708     f->numavail = 0;
1709     f->op = *op;
1710     f->getcontext = NULL;
1711     f->context.uid = 0;
1712     f->context.gid = 0;
1713     f->exited = 0;
1714    
1715     root = (struct node *) calloc(1, sizeof(struct node));
1716     root->mode = 0;
1717     root->rdev = 0;
1718     root->name = strdup("/");
1719     root->parent = 0;
1720     root->ino = FUSE_ROOT_INO;
1721     root->generation = 0;
1722     hash_ino(f, root);
1723    
1724     return f;
1725     }
1726    
1727     void fuse_destroy(struct fuse *f)
1728     {
1729     size_t i;
1730     for (i = 0; i < f->ino_table_size; i++) {
1731     struct node *node;
1732    
1733     for (node = f->ino_table[i]; node != NULL; node = node->ino_next) {
1734     if (node->is_hidden) {
1735     char *path = get_path(f, node->ino);
1736     if (path)
1737     f->op.unlink(path);
1738     }
1739     }
1740     }
1741     for (i = 0; i < f->ino_table_size; i++) {
1742     struct node *node;
1743     struct node *next;
1744    
1745     for (node = f->ino_table[i]; node != NULL; node = next) {
1746     next = node->ino_next;
1747     free_node(node);
1748     }
1749     }
1750     free(f->ino_table);
1751     free(f->name_table);
1752     pthread_mutex_destroy(&f->lock);
1753     free(f);
1754     }

  ViewVC Help
Powered by ViewVC 1.1.26