Blob


1 /*
2 * 9P to FUSE translator. Acts as FUSE server, 9P client.
3 * Mounts 9P servers via FUSE kernel module.
4 *
5 * There are four procs in this threaded program
6 * (ignoring the one that runs main and then exits).
7 * The first proc reads FUSE requests from /dev/fuse.
8 * It sends the requests over a channel to a second proc,
9 * which serves the requests. Each request runs in a
10 * thread in that second proc. Those threads do write
11 * FUSE replies, which in theory might block, but in practice don't.
12 * The 9P interactions are handled by lib9pclient, which
13 * allocates two more procs, one for reading and one for
14 * writing the 9P connection. Thus the many threads in the
15 * request proc can do 9P interactions without blocking.
16 */
18 #define _GNU_SOURCE 1 /* for O_DIRECTORY on Linux */
19 #include "a.h"
21 /* GNUisms */
22 #ifndef O_DIRECTORY
23 #define O_DIRECTORY 0
24 #endif
25 #ifndef O_LARGEFILE
26 #if defined(__linux__)
27 #define O_LARGEFILE 0100000 /* Sigh */
28 #else
29 #define O_LARGEFILE 0
30 #endif
31 #endif
34 int debug;
35 char *argv0;
36 char *aname = "";
37 void fusedispatch(void*);
38 Channel *fusechan;
40 enum
41 {
42 STACK = 8192
43 };
45 /*
46 * The number of seconds that the kernel can cache
47 * returned file attributes. FUSE's default is 1.0.
48 * I haven't experimented with using 0.
49 */
50 double attrtimeout = 1.0;
52 /*
53 * The number of seconds that the kernel can cache
54 * the returned entry nodeids returned by lookup.
55 * I haven't experimented with other values.
56 */
57 double entrytimeout = 1.0;
59 CFsys *fsys;
60 CFid *fsysroot;
61 void init9p(char*, char*);
63 void
64 usage(void)
65 {
66 fprint(2, "usage: 9pfuse [-D] [-A attrtimeout] [-a aname] address mtpt\n");
67 exit(1);
68 }
70 void fusereader(void*);
72 void
73 threadmain(int argc, char **argv)
74 {
75 ARGBEGIN{
76 case 'D':
77 chatty9pclient++;
78 debug++;
79 break;
80 case 'A':
81 attrtimeout = atof(EARGF(usage()));
82 break;
83 case 'a':
84 aname = EARGF(usage());
85 break;
86 default:
87 usage();
88 }ARGEND
90 if(argc != 2)
91 usage();
93 quotefmtinstall();
94 fmtinstall('F', fcallfmt);
95 fmtinstall('M', dirmodefmt);
96 fmtinstall('G', fusefmt);
98 setsid(); /* won't be able to use console, but can't be interrupted */
100 init9p(argv[0], aname);
101 initfuse(argv[1]);
103 fusechan = chancreate(sizeof(void*), 0);
104 proccreate(fusedispatch, nil, STACK);
105 sendp(fusechan, nil); /* sync */
107 proccreate(fusereader, nil, STACK);
108 /*
109 * Now that we're serving FUSE, we can wait
110 * for the mount to finish and exit back to the user.
111 */
112 waitfuse();
113 threadexits(0);
116 void
117 fusereader(void *v)
119 FuseMsg *m;
121 while((m = readfusemsg()) != nil)
122 sendp(fusechan, m);
124 fusemtpt = nil; /* no need to unmount */
125 threadexitsall(0);
128 void
129 init9p(char *addr, char *spec)
131 int fd;
133 if((fd = dial(netmkaddr(addr, "tcp", "564"), nil, nil, nil)) < 0)
134 sysfatal("dial %s: %r", addr);
135 if((fsys = fsmount(fd, spec)) == nil)
136 sysfatal("fsmount: %r");
137 fsysroot = fsroot(fsys);
140 /*
141 * FUSE uses nodeids to refer to active "struct inodes"
142 * (9P's unopened fids). FUSE uses fhs to refer to active
143 * "struct fuse_files" (9P's opened fids). The choice of
144 * numbers is up to us except that nodeid 1 is the root directory.
145 * We use the same number space for both and call the
146 * bookkeeping structure a FuseFid.
148 * FUSE requires nodeids to have associated generation
149 * numbers. If we reuse a nodeid, we have to bump the
150 * generation number to guarantee that the nodeid,gen
151 * combination is never reused.
153 * There are also inode numbers returned in directory reads
154 * and file attributes, but these do NOT need to match the nodeids.
155 * We use a combination of qid.path and qid.type as the inode
156 * number.
157 */
158 /*
159 * TO DO: reference count the fids.
160 */
161 typedef struct Fusefid Fusefid;
162 struct Fusefid
164 Fusefid *next;
165 CFid *fid;
166 int ref;
167 int id;
168 int gen;
169 int isnodeid;
171 /* directory read state */
172 Dir *d0;
173 Dir *d;
174 int nd;
175 int off;
176 };
178 Fusefid **fusefid;
179 int nfusefid;
180 Fusefid *freefusefidlist;
182 Fusefid*
183 allocfusefid(void)
185 Fusefid *f;
187 if((f = freefusefidlist) == nil){
188 f = emalloc(sizeof *f);
189 fusefid = erealloc(fusefid, (nfusefid+1)*sizeof *fusefid);
190 f->id = nfusefid;
191 fusefid[f->id] = f;
192 nfusefid++;
193 }else
194 freefusefidlist = f->next;
195 f->next = nil;
196 f->ref = 1;
197 f->isnodeid = -1;
198 return f;
201 void
202 freefusefid(Fusefid *f)
204 if(--f->ref > 0)
205 return;
206 assert(f->ref == 0);
207 if(f->fid)
208 fsclose(f->fid);
209 if(f->d0)
210 free(f->d0);
211 f->off = 0;
212 f->d0 = nil;
213 f->fid = nil;
214 f->d = nil;
215 f->nd = 0;
216 f->next = freefusefidlist;
217 f->isnodeid = -1;
218 freefusefidlist = f;
221 uvlong
222 _alloc(CFid *fid, int isnodeid)
224 Fusefid *ff;
226 ff = allocfusefid();
227 ff->fid = fid;
228 ff->isnodeid = isnodeid;
229 ff->gen++;
230 return ff->id+2; /* skip 0 and 1 */
233 uvlong
234 allocfh(CFid *fid)
236 return _alloc(fid, 0);
238 uvlong
239 allocnodeid(CFid *fid)
241 return _alloc(fid, 1);
244 Fusefid*
245 lookupfusefid(uvlong id, int isnodeid)
247 Fusefid *ff;
248 if(id < 2 || id >= nfusefid+2)
249 return nil;
250 ff = fusefid[(int)id-2];
251 if(ff->isnodeid != isnodeid)
252 return nil;
253 return ff;
256 CFid*
257 _lookupcfid(uvlong id, int isnodeid)
259 Fusefid *ff;
261 if((ff = lookupfusefid(id, isnodeid)) == nil)
262 return nil;
263 return ff->fid;
266 CFid*
267 fh2fid(uvlong fh)
269 return _lookupcfid(fh, 0);
272 CFid*
273 nodeid2fid(uvlong nodeid)
275 if(nodeid == 1)
276 return fsysroot;
277 return _lookupcfid(nodeid, 1);
280 uvlong
281 qid2inode(Qid q)
283 return q.path | ((uvlong)q.type<<56);
286 void
287 dir2attr(Dir *d, struct fuse_attr *attr)
289 attr->ino = qid2inode(d->qid);
290 attr->size = d->length;
291 attr->blocks = (d->length+8191)/8192;
292 attr->atime = d->atime;
293 attr->mtime = d->mtime;
294 attr->ctime = d->mtime; /* not right */
295 attr->atimensec = 0;
296 attr->mtimensec = 0;
297 attr->ctimensec = 0;
298 attr->mode = d->mode&0777;
299 if(d->mode&DMDIR)
300 attr->mode |= S_IFDIR;
301 else
302 attr->mode |= S_IFREG;
303 attr->nlink = 1; /* works for directories! - see FUSE FAQ */
304 attr->uid = getuid();
305 attr->gid = getgid();
306 attr->rdev = 0;
309 void
310 f2timeout(double f, __u64 *s, __u32 *ns)
312 *s = f;
313 *ns = (f - (int)f)*1e9;
316 void
317 dir2attrout(Dir *d, struct fuse_attr_out *out)
319 f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
320 dir2attr(d, &out->attr);
323 /*
324 * Lookup. Walk to the name given as the argument.
325 * The response is a fuse_entry_out giving full stat info.
326 */
327 void
328 fuselookup(FuseMsg *m)
330 char *name;
331 Fusefid *ff;
332 CFid *fid, *newfid;
333 Dir *d;
334 struct fuse_entry_out out;
336 name = m->tx;
337 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
338 replyfuseerrno(m, ESTALE);
339 return;
341 if(strchr(name, '/')){
342 replyfuseerrno(m, ENOENT);
343 return;
345 if((newfid = fswalk(fid, name)) == nil){
346 replyfuseerrstr(m);
347 return;
349 if((d = fsdirfstat(newfid)) == nil){
350 fsclose(newfid);
351 replyfuseerrstr(m);
352 return;
354 out.nodeid = allocnodeid(newfid);
355 ff = lookupfusefid(out.nodeid, 1);
356 out.generation = ff->gen;
357 f2timeout(attrtimeout, &out.attr_valid, &out.attr_valid_nsec);
358 f2timeout(entrytimeout, &out.entry_valid, &out.entry_valid_nsec);
359 dir2attr(d, &out.attr);
360 free(d);
361 replyfuse(m, &out, sizeof out);
364 /*
365 * Forget. Reference-counted clunk for nodeids.
366 * Does not send a reply.
367 * Each lookup response gives the kernel an additional reference
368 * to the returned nodeid. Forget says "drop this many references
369 * to this nodeid". Our fuselookup, when presented with the same query,
370 * does not return the same results (it allocates a new nodeid for each
371 * call), but if that ever changes, fuseforget already handles the ref
372 * counts properly.
373 */
374 void
375 fuseforget(FuseMsg *m)
377 struct fuse_forget_in *in;
378 Fusefid *ff;
380 in = m->tx;
381 if((ff = lookupfusefid(m->hdr->nodeid, 1)) == nil)
382 return;
383 if(ff->ref > in->nlookup){
384 ff->ref -= in->nlookup;
385 return;
387 if(ff->ref < in->nlookup)
388 fprint(2, "bad count in forget\n");
389 ff->ref = 1;
390 freefusefid(ff);
393 /*
394 * Getattr.
395 * Replies with a fuse_attr_out structure giving the
396 * attr for the requested nodeid in out.attr.
397 * Out.attr_valid and out.attr_valid_nsec give
398 * the amount of time that the attributes can
399 * be cached.
401 * Empirically, though, if I run ls -ld on the root
402 * twice back to back, I still get two getattrs,
403 * even with a one second attribute timeout!
404 */
405 void
406 fusegetattr(FuseMsg *m)
408 CFid *fid;
409 struct fuse_attr_out out;
410 Dir *d;
412 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
413 replyfuseerrno(m, ESTALE);
414 return;
416 if((d = fsdirfstat(fid)) == nil){
417 replyfuseerrstr(m);
418 return;
420 memset(&out, 0, sizeof out);
421 dir2attrout(d, &out);
422 free(d);
423 replyfuse(m, &out, sizeof out);
426 /*
427 * Setattr.
428 * FUSE treats the many Unix attribute setting routines
429 * more or less like 9P does, with a single message.
430 */
431 void
432 fusesetattr(FuseMsg *m)
434 CFid *fid, *nfid;
435 Dir d, *dd;
436 struct fuse_setattr_in *in;
437 struct fuse_attr_out out;
439 in = m->tx;
440 if(in->valid&FATTR_FH){
441 if((fid = fh2fid(in->fh)) == nil){
442 replyfuseerrno(m, ESTALE);
443 return;
445 }else{
446 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
447 replyfuseerrno(m, ESTALE);
448 return;
450 /*
451 * Special case: Linux issues a size change to
452 * truncate a file before opening it OTRUNC.
453 * Synthetic file servers (e.g., plumber) honor
454 * open(OTRUNC) but not wstat.
455 */
456 if(in->valid == FATTR_SIZE && in->size == 0){
457 if((nfid = fswalk(fid, nil)) == nil){
458 replyfuseerrstr(m);
459 return;
461 if(fsfopen(nfid, OWRITE|OTRUNC) < 0){
462 replyfuseerrstr(m);
463 fsclose(nfid);
464 return;
466 fsclose(nfid);
467 goto stat;
471 nulldir(&d);
472 if(in->valid&FATTR_SIZE)
473 d.length = in->size;
474 if(in->valid&FATTR_ATIME)
475 d.atime = in->atime;
476 if(in->valid&FATTR_MTIME)
477 d.mtime = in->mtime;
478 if(in->valid&FATTR_MODE)
479 d.mode = in->mode;
480 if((in->valid&FATTR_UID) || (in->valid&FATTR_GID)){
481 /*
482 * I can't be bothered with these yet.
483 */
484 replyfuseerrno(m, EPERM);
485 return;
487 if(fsdirfwstat(fid, &d) < 0){
488 replyfuseerrstr(m);
489 return;
491 stat:
492 if((dd = fsdirfstat(fid)) == nil){
493 replyfuseerrstr(m);
494 return;
496 memset(&out, 0, sizeof out);
497 dir2attrout(dd, &out);
498 free(dd);
499 replyfuse(m, &out, sizeof out);
502 CFid*
503 _fuseopenfid(uvlong nodeid, int isdir, int openmode, int *err)
505 CFid *fid, *newfid;
507 if((fid = nodeid2fid(nodeid)) == nil){
508 *err = ESTALE;
509 return nil;
511 if(isdir && !(fsqid(fid).type&QTDIR)){
512 *err = ENOTDIR;
513 return nil;
515 if(openmode != OREAD && fsqid(fid).type&QTDIR){
516 *err = EISDIR;
517 return nil;
520 /* Clone fid to get one we can open. */
521 newfid = fswalk(fid, nil);
522 if(newfid == nil){
523 *err = errstr2errno();
524 return nil;
527 if(fsfopen(newfid, openmode) < 0){
528 *err = errstr2errno();
529 fsclose(newfid);
530 return nil;
533 return newfid;
536 /*
537 * Open & Opendir.
538 * Argument is a struct fuse_open_in.
539 * The mode field is ignored (presumably permission bits)
540 * and flags is the open mode.
541 * Replies with a struct fuse_open_out.
542 */
543 void
544 _fuseopen(FuseMsg *m, int isdir)
546 struct fuse_open_in *in;
547 struct fuse_open_out out;
548 CFid *fid;
549 int openmode, flags, err;
551 in = m->tx;
552 flags = in->flags;
553 openmode = flags&3;
554 flags &= ~3;
555 flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE);
556 if(flags & O_TRUNC){
557 openmode |= OTRUNC;
558 flags &= ~O_TRUNC;
560 /*
561 * Could translate but not standard 9P:
562 * O_DIRECT -> ODIRECT
563 * O_NONBLOCK -> ONONBLOCK
564 * O_APPEND -> OAPPEND
565 */
566 if(flags){
567 fprint(2, "unexpected open flags %#uo", (uint)in->flags);
568 replyfuseerrno(m, EACCES);
569 return;
571 if((fid = _fuseopenfid(m->hdr->nodeid, isdir, openmode, &err)) == nil){
572 replyfuseerrno(m, err);
573 return;
575 out.fh = allocfh(fid);
576 out.open_flags = FOPEN_DIRECT_IO; /* no page cache */
577 replyfuse(m, &out, sizeof out);
580 void
581 fuseopen(FuseMsg *m)
583 _fuseopen(m, 0);
586 void
587 fuseopendir(FuseMsg *m)
589 _fuseopen(m, 1);
592 /*
593 * Create & Mkdir.
594 */
595 CFid*
596 _fusecreate(uvlong nodeid, char *name, int perm, int ismkdir, int omode, struct fuse_entry_out *out, int *err)
598 CFid *fid, *newfid, *newfid2;
599 Dir *d;
600 Fusefid *ff;
602 if((fid = nodeid2fid(nodeid)) == nil){
603 *err = ESTALE;
604 return nil;
606 perm &= 0777;
607 if(ismkdir)
608 perm |= DMDIR;
609 if(ismkdir && omode != OREAD){
610 *err = EPERM;
611 return nil;
613 if((newfid = fswalk(fid, nil)) == nil){
614 *err = errstr2errno();
615 return nil;
617 if(fsfcreate(newfid, name, omode, perm) < 0){
618 *err = errstr2errno();
619 fsclose(newfid);
620 return nil;
622 if((d = fsdirfstat(newfid)) == nil){
623 *err = errstr2errno();
624 fsfremove(newfid);
625 return nil;
627 /*
628 * This fid is no good, because it's open.
629 * We need an unopened fid. Sigh.
630 */
631 if((newfid2 = fswalk(fid, name)) == nil){
632 *err = errstr2errno();
633 free(d);
634 fsfremove(newfid);
635 return nil;
637 out->nodeid = allocnodeid(newfid2);
638 ff = lookupfusefid(out->nodeid, 1);
639 out->generation = ff->gen;
640 f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
641 f2timeout(entrytimeout, &out->entry_valid, &out->entry_valid_nsec);
642 dir2attr(d, &out->attr);
643 free(d);
644 return newfid;
647 void
648 fusemkdir(FuseMsg *m)
650 struct fuse_mkdir_in *in;
651 struct fuse_entry_out out;
652 CFid *fid;
653 int err;
654 char *name;
656 in = m->tx;
657 name = (char*)(in+1);
658 if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 1, OREAD, &out, &err)) == nil){
659 replyfuseerrno(m, err);
660 return;
662 /* Toss the open fid. */
663 fsclose(fid);
664 replyfuse(m, &out, sizeof out);
667 void
668 fusecreate(FuseMsg *m)
670 struct fuse_open_in *in;
671 struct fuse_create_out out;
672 CFid *fid;
673 int err, openmode, flags;
674 char *name;
676 in = m->tx;
677 flags = in->flags;
678 openmode = in->flags&3;
679 flags &= ~3;
680 flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE);
681 flags &= ~(O_CREAT|O_TRUNC); /* huh? */
682 if(flags){
683 fprint(2, "bad mode %#uo\n", in->flags);
684 replyfuseerrno(m, EACCES);
685 return;
687 name = (char*)(in+1);
688 if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 0, openmode, &out.e, &err)) == nil){
689 replyfuseerrno(m, err);
690 return;
692 out.o.fh = allocfh(fid);
693 out.o.open_flags = FOPEN_DIRECT_IO; /* no page cache */
694 replyfuse(m, &out, sizeof out);
697 /*
698 * Access.
699 * Lib9pclient implements this just as Plan 9 does,
700 * by opening the file (or not) and then closing it.
701 */
702 void
703 fuseaccess(FuseMsg *m)
705 struct fuse_access_in *in;
706 CFid *fid;
707 int err, omode;
708 static int a2o[] = {
709 0,
710 OEXEC,
711 OWRITE,
712 ORDWR,
713 OREAD,
714 OEXEC,
715 ORDWR,
716 ORDWR
717 };
719 in = m->tx;
720 if(in->mask >= nelem(a2o)){
721 replyfuseerrno(m, EINVAL);
722 return;
724 omode = a2o[in->mask];
725 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
726 replyfuseerrno(m, ESTALE);
727 return;
729 if(fsqid(fid).type&QTDIR)
730 omode = OREAD;
731 if((fid = _fuseopenfid(m->hdr->nodeid, 0, omode, &err)) == nil){
732 replyfuseerrno(m, err);
733 return;
735 fsclose(fid);
736 replyfuse(m, nil, 0);
739 /*
740 * Release.
741 * Equivalent of clunk for file handles.
742 * in->flags is the open mode used in Open or Opendir.
743 */
744 void
745 fuserelease(FuseMsg *m)
747 struct fuse_release_in *in;
748 Fusefid *ff;
750 in = m->tx;
751 if((ff = lookupfusefid(in->fh, 0)) != nil)
752 freefusefid(ff);
753 else
754 fprint(2, "fuserelease: fh not found\n");
755 replyfuse(m, nil, 0);
758 void
759 fusereleasedir(FuseMsg *m)
761 fuserelease(m);
764 /*
765 * Read.
766 * Read from file handle in->fh at offset in->offset for size in->size.
767 * We truncate size to maxwrite just to keep the buffer reasonable.
768 */
769 void
770 fuseread(FuseMsg *m)
772 int n;
773 uchar *buf;
774 CFid *fid;
775 struct fuse_read_in *in;
777 in = m->tx;
778 if((fid = fh2fid(in->fh)) == nil){
779 replyfuseerrno(m, ESTALE);
780 return;
782 n = in->size;
783 if(n > fusemaxwrite)
784 n = fusemaxwrite;
785 buf = emalloc(n);
786 n = fspread(fid, buf, n, in->offset);
787 if(n < 0){
788 free(buf);
789 replyfuseerrstr(m);
791 replyfuse(m, buf, n);
792 free(buf);
795 /*
796 * Readdir.
797 * Read from file handle in->fh at offset in->offset for size in->size.
798 * We truncate size to maxwrite just to keep the buffer reasonable.
799 * We assume 9P directory read semantics: a read at offset 0 rewinds
800 * and a read at any other offset starts where we left off.
801 * If it became necessary, we could implement a crude seek
802 * or cache the entire list of directory entries.
803 * Directory entries read from 9P but not yet handed to FUSE
804 * are stored in m->d,nd,d0.
805 */
806 int canpack(Dir*, uvlong, uchar**, uchar*);
807 void
808 fusereaddir(FuseMsg *m)
810 struct fuse_read_in *in;
811 uchar *buf, *p, *ep;
812 int n;
813 Fusefid *ff;
815 in = m->tx;
816 if((ff = lookupfusefid(in->fh, 0)) == nil){
817 replyfuseerrno(m, ESTALE);
818 return;
820 if(in->offset == 0){
821 fsseek(ff->fid, 0, 0);
822 free(ff->d0);
823 ff->d0 = nil;
824 ff->d = nil;
825 ff->nd = 0;
827 n = in->size;
828 if(n > fusemaxwrite)
829 n = fusemaxwrite;
830 buf = emalloc(n);
831 p = buf;
832 ep = buf + n;
833 for(;;){
834 while(ff->nd > 0){
835 if(!canpack(ff->d, ff->off, &p, ep))
836 goto out;
837 ff->off++;
838 ff->d++;
839 ff->nd--;
841 free(ff->d0);
842 ff->d0 = nil;
843 ff->d = nil;
844 if((ff->nd = fsdirread(ff->fid, &ff->d0)) < 0){
845 replyfuseerrstr(m);
846 free(buf);
847 return;
849 if(ff->nd == 0)
850 break;
851 ff->d = ff->d0;
853 out:
854 replyfuse(m, buf, p - buf);
855 free(buf);
858 int
859 canpack(Dir *d, uvlong off, uchar **pp, uchar *ep)
861 uchar *p;
862 struct fuse_dirent *de;
863 int pad, size;
865 p = *pp;
866 size = FUSE_NAME_OFFSET + strlen(d->name);
867 pad = 0;
868 if(size%8)
869 pad = 8 - size%8;
870 if(size+pad > ep - p)
871 return 0;
872 de = (struct fuse_dirent*)p;
873 de->ino = qid2inode(d->qid);
874 de->off = off;
875 de->namelen = strlen(d->name);
876 memmove(de->name, d->name, de->namelen);
877 if(pad > 0)
878 memset(de->name+de->namelen, 0, pad);
879 *pp = p+size+pad;
880 return 1;
883 /*
884 * Write.
885 * Write from file handle in->fh at offset in->offset for size in->size.
886 * Don't know what in->write_flags means.
888 * Apparently implementations are allowed to buffer these writes
889 * and wait until Flush is sent, but FUSE docs say flush may be
890 * called zero, one, or even more times per close. So better do the
891 * actual writing here. Also, errors that happen during Flush just
892 * show up in the close() return status, which no one checks anyway.
893 */
894 void
895 fusewrite(FuseMsg *m)
897 struct fuse_write_in *in;
898 struct fuse_write_out out;
899 void *a;
900 CFid *fid;
901 int n;
903 in = m->tx;
904 a = in+1;
905 if((fid = fh2fid(in->fh)) == nil){
906 replyfuseerrno(m, ESTALE);
907 return;
909 if(in->size > fusemaxwrite){
910 replyfuseerrno(m, EINVAL);
911 return;
913 n = fspwrite(fid, a, in->size, in->offset);
914 if(n < 0){
915 replyfuseerrstr(m);
916 return;
918 out.size = n;
919 replyfuse(m, &out, sizeof out);
922 /*
923 * Flush. Supposed to flush any buffered writes. Don't use this.
925 * Flush is a total crock. It gets called on close() of a file descriptor
926 * associated with this open file. Some open files have multiple file
927 * descriptors and thus multiple closes of those file descriptors.
928 * In those cases, Flush is called multiple times. Some open files
929 * have file descriptors that are closed on process exit instead of
930 * closed explicitly. For those files, Flush is never called.
931 * Even more amusing, Flush gets called before close() of read-only
932 * file descriptors too!
934 * This is just a bad idea.
935 */
936 void
937 fuseflush(FuseMsg *m)
939 replyfuse(m, nil, 0);
942 /*
943 * Unlink & Rmdir.
944 */
945 void
946 _fuseremove(FuseMsg *m, int isdir)
948 char *name;
949 CFid *fid, *newfid;
951 name = m->tx;
952 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
953 replyfuseerrno(m, ESTALE);
954 return;
956 if(strchr(name, '/')){
957 replyfuseerrno(m, ENOENT);
958 return;
960 if((newfid = fswalk(fid, name)) == nil){
961 replyfuseerrstr(m);
962 return;
964 if(isdir && !(fsqid(newfid).type&QTDIR)){
965 replyfuseerrno(m, ENOTDIR);
966 fsclose(newfid);
967 return;
969 if(!isdir && (fsqid(newfid).type&QTDIR)){
970 replyfuseerrno(m, EISDIR);
971 fsclose(newfid);
972 return;
974 if(fsfremove(newfid) < 0){
975 replyfuseerrstr(m);
976 return;
978 replyfuse(m, nil, 0);
981 void
982 fuseunlink(FuseMsg *m)
984 _fuseremove(m, 0);
987 void
988 fusermdir(FuseMsg *m)
990 _fuseremove(m, 1);
993 /*
994 * Rename.
996 * FUSE sends the nodeid for the source and destination
997 * directory and then the before and after names as strings.
998 * 9P can only do the rename if the source and destination
999 * are the same. If the same nodeid is used for source and
1000 * destination, we're fine, but if FUSE gives us different nodeids
1001 * that happen to correspond to the same directory, we have
1002 * no way of figuring that out. Let's hope it doesn't happen too often.
1004 void
1005 fuserename(FuseMsg *m)
1007 struct fuse_rename_in *in;
1008 char *before, *after;
1009 CFid *fid, *newfid;
1010 Dir d;
1012 in = m->tx;
1013 if(in->newdir != m->hdr->nodeid){
1014 replyfuseerrno(m, EXDEV);
1015 return;
1017 before = (char*)(in+1);
1018 after = before + strlen(before) + 1;
1019 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
1020 replyfuseerrno(m, ESTALE);
1021 return;
1023 if(strchr(before, '/') || strchr(after, '/')){
1024 replyfuseerrno(m, ENOENT);
1025 return;
1027 if((newfid = fswalk(fid, before)) == nil){
1028 replyfuseerrstr(m);
1029 return;
1031 nulldir(&d);
1032 d.name = after;
1033 if(fsdirfwstat(newfid, &d) < 0){
1034 replyfuseerrstr(m);
1035 fsclose(newfid);
1036 return;
1038 fsclose(newfid);
1039 replyfuse(m, nil, 0);
1043 * Fsync. Commit file info to stable storage.
1044 * Not sure what in->fsync_flags are.
1046 void
1047 fusefsync(FuseMsg *m)
1049 struct fuse_fsync_in *in;
1050 CFid *fid;
1051 Dir d;
1053 in = m->tx;
1054 if((fid = fh2fid(in->fh)) == nil){
1055 replyfuseerrno(m, ESTALE);
1056 return;
1058 nulldir(&d);
1059 if(fsdirfwstat(fid, &d) < 0){
1060 replyfuseerrstr(m);
1061 return;
1063 replyfuse(m, nil, 0);
1067 * Fsyncdir. Commit dir info to stable storage?
1069 void
1070 fusefsyncdir(FuseMsg *m)
1072 fusefsync(m);
1076 * Statfs. Send back information about file system.
1077 * Not really worth implementing, except that if we
1078 * reply with ENOSYS, programs like df print messages like
1079 * df: `/tmp/z': Function not implemented
1080 * and that gets annoying. Returning all zeros excludes
1081 * us from df without appearing to cause any problems.
1083 void
1084 fusestatfs(FuseMsg *m)
1086 struct fuse_statfs_out out;
1088 memset(&out, 0, sizeof out);
1089 replyfuse(m, &out, sizeof out);
1092 void (*fusehandlers[100])(FuseMsg*);
1094 struct {
1095 int op;
1096 void (*fn)(FuseMsg*);
1097 } fuselist[] = {
1098 { FUSE_LOOKUP, fuselookup },
1099 { FUSE_FORGET, fuseforget },
1100 { FUSE_GETATTR, fusegetattr },
1101 { FUSE_SETATTR, fusesetattr },
1103 * FUSE_READLINK, FUSE_SYMLINK, FUSE_MKNOD are unimplemented.
1105 { FUSE_MKDIR, fusemkdir },
1106 { FUSE_UNLINK, fuseunlink },
1107 { FUSE_RMDIR, fusermdir },
1108 { FUSE_RENAME, fuserename },
1110 * FUSE_LINK is unimplemented.
1112 { FUSE_OPEN, fuseopen },
1113 { FUSE_READ, fuseread },
1114 { FUSE_WRITE, fusewrite },
1115 { FUSE_STATFS, fusestatfs },
1116 { FUSE_RELEASE, fuserelease },
1117 { FUSE_FSYNC, fusefsync },
1119 * FUSE_SETXATTR, FUSE_GETXATTR, FUSE_LISTXATTR, and
1120 * FUSE_REMOVEXATTR are unimplemented.
1121 * FUSE will stop sending these requests after getting
1122 * an -ENOSYS reply (see dispatch below).
1124 { FUSE_FLUSH, fuseflush },
1126 * FUSE_INIT is handled in initfuse and should not be seen again.
1128 { FUSE_OPENDIR, fuseopendir },
1129 { FUSE_READDIR, fusereaddir },
1130 { FUSE_RELEASEDIR, fusereleasedir },
1131 { FUSE_FSYNCDIR, fusefsyncdir },
1132 { FUSE_ACCESS, fuseaccess },
1133 { FUSE_CREATE, fusecreate },
1136 void
1137 fusethread(void *v)
1139 FuseMsg *m;
1141 m = v;
1142 if((uint)m->hdr->opcode >= nelem(fusehandlers)
1143 || !fusehandlers[m->hdr->opcode]){
1144 replyfuseerrno(m, ENOSYS);
1145 return;
1147 fusehandlers[m->hdr->opcode](m);
1150 void
1151 fusedispatch(void *v)
1153 int i;
1154 FuseMsg *m;
1156 eofkill9pclient = 1; /* threadexitsall on 9P eof */
1157 atexit(unmountatexit);
1159 recvp(fusechan); /* sync */
1161 for(i=0; i<nelem(fuselist); i++){
1162 if(fuselist[i].op >= nelem(fusehandlers))
1163 sysfatal("make fusehandlers bigger op=%d", fuselist[i].op);
1164 fusehandlers[fuselist[i].op] = fuselist[i].fn;
1167 while((m = recvp(fusechan)) != nil)
1168 threadcreate(fusethread, m, STACK);
1171 void*
1172 emalloc(uint n)
1174 void *p;
1176 p = malloc(n);
1177 if(p == nil)
1178 sysfatal("malloc(%d): %r", n);
1179 memset(p, 0, n);
1180 return p;
1183 void*
1184 erealloc(void *p, uint n)
1186 p = realloc(p, n);
1187 if(p == nil)
1188 sysfatal("realloc(..., %d): %r", n);
1189 return p;
1192 char*
1193 estrdup(char *p)
1195 char *pp;
1196 pp = strdup(p);
1197 if(pp == nil)
1198 sysfatal("strdup(%.20s): %r", p);
1199 return pp;