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 void fusedispatch(void*);
37 Channel *fusechan;
39 enum
40 {
41 STACK = 8192
42 };
44 /*
45 * The number of seconds that the kernel can cache
46 * returned file attributes. FUSE's default is 1.0.
47 * I haven't experimented with using 0.
48 */
49 double attrtimeout = 1.0;
51 /*
52 * The number of seconds that the kernel can cache
53 * the returned entry nodeids returned by lookup.
54 * I haven't experimented with other values.
55 */
56 double entrytimeout = 1.0;
58 CFsys *fsys;
59 CFid *fsysroot;
60 void init9p(char*);
62 void
63 usage(void)
64 {
65 fprint(2, "usage: 9pfuse [-D] [-a attrtimeout] address mtpt\n");
66 exit(1);
67 }
69 void fusereader(void*);
71 void
72 threadmain(int argc, char **argv)
73 {
74 ARGBEGIN{
75 case 'D':
76 chatty9pclient++;
77 debug++;
78 break;
79 case 'a':
80 attrtimeout = atof(EARGF(usage()));
81 break;
82 default:
83 usage();
84 }ARGEND
86 if(argc != 2)
87 usage();
89 quotefmtinstall();
90 fmtinstall('F', fcallfmt);
91 fmtinstall('M', dirmodefmt);
92 fmtinstall('G', fusefmt);
94 setsid(); /* won't be able to use console, but can't be interrupted */
96 init9p(argv[0]);
97 initfuse(argv[1]);
99 fusechan = chancreate(sizeof(void*), 0);
100 proccreate(fusedispatch, nil, STACK);
101 sendp(fusechan, nil); /* sync */
103 proccreate(fusereader, nil, STACK);
104 /*
105 * Now that we're serving FUSE, we can wait
106 * for the mount to finish and exit back to the user.
107 */
108 waitfuse();
109 threadexits(0);
112 void
113 fusereader(void *v)
115 FuseMsg *m;
117 while((m = readfusemsg()) != nil)
118 sendp(fusechan, m);
120 fusemtpt = nil; /* no need to unmount */
121 threadexitsall(0);
124 void
125 init9p(char *addr)
127 int fd;
129 if((fd = dial(netmkaddr(addr, "tcp", "564"), nil, nil, nil)) < 0)
130 sysfatal("dial %s: %r", addr);
131 if((fsys = fsmount(fd, "")) == nil)
132 sysfatal("fsmount: %r");
133 fsysroot = fsroot(fsys);
136 /*
137 * FUSE uses nodeids to refer to active "struct inodes"
138 * (9P's unopened fids). FUSE uses fhs to refer to active
139 * "struct fuse_files" (9P's opened fids). The choice of
140 * numbers is up to us except that nodeid 1 is the root directory.
141 * We use the same number space for both and call the
142 * bookkeeping structure a FuseFid.
144 * FUSE requires nodeids to have associated generation
145 * numbers. If we reuse a nodeid, we have to bump the
146 * generation number to guarantee that the nodeid,gen
147 * combination is never reused.
149 * There are also inode numbers returned in directory reads
150 * and file attributes, but these do NOT need to match the nodeids.
151 * We use a combination of qid.path and qid.type as the inode
152 * number.
153 */
154 /*
155 * TO DO: reference count the fids.
156 */
157 typedef struct Fusefid Fusefid;
158 struct Fusefid
160 Fusefid *next;
161 CFid *fid;
162 int ref;
163 int id;
164 int gen;
165 int isnodeid;
167 /* directory read state */
168 Dir *d0;
169 Dir *d;
170 int nd;
171 int off;
172 };
174 Fusefid **fusefid;
175 int nfusefid;
176 Fusefid *freefusefidlist;
178 Fusefid*
179 allocfusefid(void)
181 Fusefid *f;
183 if((f = freefusefidlist) == nil){
184 f = emalloc(sizeof *f);
185 fusefid = erealloc(fusefid, (nfusefid+1)*sizeof *fusefid);
186 f->id = nfusefid;
187 fusefid[f->id] = f;
188 nfusefid++;
189 }else
190 freefusefidlist = f->next;
191 f->next = nil;
192 f->ref = 1;
193 f->isnodeid = -1;
194 return f;
197 void
198 freefusefid(Fusefid *f)
200 if(--f->ref > 0)
201 return;
202 assert(f->ref == 0);
203 if(f->fid)
204 fsclose(f->fid);
205 if(f->d0)
206 free(f->d0);
207 f->off = 0;
208 f->d0 = nil;
209 f->fid = nil;
210 f->d = nil;
211 f->nd = 0;
212 f->next = freefusefidlist;
213 f->isnodeid = -1;
214 freefusefidlist = f;
217 uvlong
218 _alloc(CFid *fid, int isnodeid)
220 Fusefid *ff;
222 ff = allocfusefid();
223 ff->fid = fid;
224 ff->isnodeid = isnodeid;
225 ff->gen++;
226 return ff->id+2; /* skip 0 and 1 */
229 uvlong
230 allocfh(CFid *fid)
232 return _alloc(fid, 0);
234 uvlong
235 allocnodeid(CFid *fid)
237 return _alloc(fid, 1);
240 Fusefid*
241 lookupfusefid(uvlong id, int isnodeid)
243 Fusefid *ff;
244 if(id < 2 || id >= nfusefid+2)
245 return nil;
246 ff = fusefid[(int)id-2];
247 if(ff->isnodeid != isnodeid)
248 return nil;
249 return ff;
252 CFid*
253 _lookupcfid(uvlong id, int isnodeid)
255 Fusefid *ff;
257 if((ff = lookupfusefid(id, isnodeid)) == nil)
258 return nil;
259 return ff->fid;
262 CFid*
263 fh2fid(uvlong fh)
265 return _lookupcfid(fh, 0);
268 CFid*
269 nodeid2fid(uvlong nodeid)
271 if(nodeid == 1)
272 return fsysroot;
273 return _lookupcfid(nodeid, 1);
276 uvlong
277 qid2inode(Qid q)
279 return q.path | ((uvlong)q.type<<56);
282 void
283 dir2attr(Dir *d, struct fuse_attr *attr)
285 attr->ino = qid2inode(d->qid);
286 attr->size = d->length;
287 attr->blocks = (d->length+8191)/8192;
288 attr->atime = d->atime;
289 attr->mtime = d->mtime;
290 attr->ctime = d->mtime; /* not right */
291 attr->atimensec = 0;
292 attr->mtimensec = 0;
293 attr->ctimensec = 0;
294 attr->mode = d->mode&0777;
295 if(d->mode&DMDIR)
296 attr->mode |= S_IFDIR;
297 else
298 attr->mode |= S_IFREG;
299 attr->nlink = 1; /* works for directories! - see FUSE FAQ */
300 attr->uid = getuid();
301 attr->gid = getgid();
302 attr->rdev = 0;
305 void
306 f2timeout(double f, __u64 *s, __u32 *ns)
308 *s = f;
309 *ns = (f - (int)f)*1e9;
312 void
313 dir2attrout(Dir *d, struct fuse_attr_out *out)
315 f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
316 dir2attr(d, &out->attr);
319 /*
320 * Lookup. Walk to the name given as the argument.
321 * The response is a fuse_entry_out giving full stat info.
322 */
323 void
324 fuselookup(FuseMsg *m)
326 char *name;
327 Fusefid *ff;
328 CFid *fid, *newfid;
329 Dir *d;
330 struct fuse_entry_out out;
332 name = m->tx;
333 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
334 replyfuseerrno(m, ESTALE);
335 return;
337 if(strchr(name, '/')){
338 replyfuseerrno(m, ENOENT);
339 return;
341 if((newfid = fswalk(fid, name)) == nil){
342 replyfuseerrstr(m);
343 return;
345 if((d = fsdirfstat(newfid)) == nil){
346 fsclose(newfid);
347 replyfuseerrstr(m);
348 return;
350 out.nodeid = allocnodeid(newfid);
351 ff = lookupfusefid(out.nodeid, 1);
352 out.generation = ff->gen;
353 f2timeout(attrtimeout, &out.attr_valid, &out.attr_valid_nsec);
354 f2timeout(entrytimeout, &out.entry_valid, &out.entry_valid_nsec);
355 dir2attr(d, &out.attr);
356 free(d);
357 replyfuse(m, &out, sizeof out);
360 /*
361 * Forget. Reference-counted clunk for nodeids.
362 * Does not send a reply.
363 * Each lookup response gives the kernel an additional reference
364 * to the returned nodeid. Forget says "drop this many references
365 * to this nodeid". Our fuselookup, when presented with the same query,
366 * does not return the same results (it allocates a new nodeid for each
367 * call), but if that ever changes, fuseforget already handles the ref
368 * counts properly.
369 */
370 void
371 fuseforget(FuseMsg *m)
373 struct fuse_forget_in *in;
374 Fusefid *ff;
376 in = m->tx;
377 if((ff = lookupfusefid(m->hdr->nodeid, 1)) == nil)
378 return;
379 if(ff->ref > in->nlookup){
380 ff->ref -= in->nlookup;
381 return;
383 if(ff->ref < in->nlookup)
384 fprint(2, "bad count in forget\n");
385 ff->ref = 1;
386 freefusefid(ff);
389 /*
390 * Getattr.
391 * Replies with a fuse_attr_out structure giving the
392 * attr for the requested nodeid in out.attr.
393 * Out.attr_valid and out.attr_valid_nsec give
394 * the amount of time that the attributes can
395 * be cached.
397 * Empirically, though, if I run ls -ld on the root
398 * twice back to back, I still get two getattrs,
399 * even with a one second attribute timeout!
400 */
401 void
402 fusegetattr(FuseMsg *m)
404 CFid *fid;
405 struct fuse_attr_out out;
406 Dir *d;
408 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
409 replyfuseerrno(m, ESTALE);
410 return;
412 if((d = fsdirfstat(fid)) == nil){
413 replyfuseerrstr(m);
414 return;
416 memset(&out, 0, sizeof out);
417 dir2attrout(d, &out);
418 free(d);
419 replyfuse(m, &out, sizeof out);
422 /*
423 * Setattr.
424 * FUSE treats the many Unix attribute setting routines
425 * more or less like 9P does, with a single message.
426 */
427 void
428 fusesetattr(FuseMsg *m)
430 CFid *fid, *nfid;
431 Dir d, *dd;
432 struct fuse_setattr_in *in;
433 struct fuse_attr_out out;
435 in = m->tx;
436 if(in->valid&FATTR_FH){
437 if((fid = fh2fid(in->fh)) == nil){
438 replyfuseerrno(m, ESTALE);
439 return;
441 }else{
442 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
443 replyfuseerrno(m, ESTALE);
444 return;
446 /*
447 * Special case: Linux issues a size change to
448 * truncate a file before opening it OTRUNC.
449 * Synthetic file servers (e.g., plumber) honor
450 * open(OTRUNC) but not wstat.
451 */
452 if(in->valid == FATTR_SIZE && in->size == 0){
453 if((nfid = fswalk(fid, nil)) == nil){
454 replyfuseerrstr(m);
455 return;
457 if(fsfopen(nfid, OWRITE|OTRUNC) < 0){
458 replyfuseerrstr(m);
459 fsclose(nfid);
460 return;
462 fsclose(nfid);
463 goto stat;
467 nulldir(&d);
468 if(in->valid&FATTR_SIZE)
469 d.length = in->size;
470 if(in->valid&FATTR_ATIME)
471 d.atime = in->atime;
472 if(in->valid&FATTR_MTIME)
473 d.mtime = in->mtime;
474 if(in->valid&FATTR_MODE)
475 d.mode = in->mode;
476 if((in->valid&FATTR_UID) || (in->valid&FATTR_GID)){
477 /*
478 * I can't be bothered with these yet.
479 */
480 replyfuseerrno(m, EPERM);
481 return;
483 if(fsdirfwstat(fid, &d) < 0){
484 replyfuseerrstr(m);
485 return;
487 stat:
488 if((dd = fsdirfstat(fid)) == nil){
489 replyfuseerrstr(m);
490 return;
492 memset(&out, 0, sizeof out);
493 dir2attrout(dd, &out);
494 free(dd);
495 replyfuse(m, &out, sizeof out);
498 CFid*
499 _fuseopenfid(uvlong nodeid, int isdir, int openmode, int *err)
501 CFid *fid, *newfid;
503 if((fid = nodeid2fid(nodeid)) == nil){
504 *err = ESTALE;
505 return nil;
507 if(isdir && !(fsqid(fid).type&QTDIR)){
508 *err = ENOTDIR;
509 return nil;
511 if(openmode != OREAD && fsqid(fid).type&QTDIR){
512 *err = EISDIR;
513 return nil;
516 /* Clone fid to get one we can open. */
517 newfid = fswalk(fid, nil);
518 if(newfid == nil){
519 *err = errstr2errno();
520 return nil;
523 if(fsfopen(newfid, openmode) < 0){
524 *err = errstr2errno();
525 fsclose(newfid);
526 return nil;
529 return newfid;
532 /*
533 * Open & Opendir.
534 * Argument is a struct fuse_open_in.
535 * The mode field is ignored (presumably permission bits)
536 * and flags is the open mode.
537 * Replies with a struct fuse_open_out.
538 */
539 void
540 _fuseopen(FuseMsg *m, int isdir)
542 struct fuse_open_in *in;
543 struct fuse_open_out out;
544 CFid *fid;
545 int openmode, flags, err;
547 in = m->tx;
548 flags = in->flags;
549 openmode = flags&3;
550 flags &= ~3;
551 flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE);
552 if(flags & O_TRUNC){
553 openmode |= OTRUNC;
554 flags &= ~O_TRUNC;
556 /*
557 * Could translate but not standard 9P:
558 * O_DIRECT -> ODIRECT
559 * O_NONBLOCK -> ONONBLOCK
560 * O_APPEND -> OAPPEND
561 */
562 if(flags){
563 fprint(2, "unexpected open flags %#uo", (uint)in->flags);
564 replyfuseerrno(m, EACCES);
565 return;
567 if((fid = _fuseopenfid(m->hdr->nodeid, isdir, openmode, &err)) == nil){
568 replyfuseerrno(m, err);
569 return;
571 out.fh = allocfh(fid);
572 out.open_flags = FOPEN_DIRECT_IO; /* no page cache */
573 replyfuse(m, &out, sizeof out);
576 void
577 fuseopen(FuseMsg *m)
579 _fuseopen(m, 0);
582 void
583 fuseopendir(FuseMsg *m)
585 _fuseopen(m, 1);
588 /*
589 * Create & Mkdir.
590 */
591 CFid*
592 _fusecreate(uvlong nodeid, char *name, int perm, int ismkdir, int omode, struct fuse_entry_out *out, int *err)
594 CFid *fid, *newfid, *newfid2;
595 Dir *d;
596 Fusefid *ff;
598 if((fid = nodeid2fid(nodeid)) == nil){
599 *err = ESTALE;
600 return nil;
602 perm &= 0777;
603 if(ismkdir)
604 perm |= DMDIR;
605 if(ismkdir && omode != OREAD){
606 *err = EPERM;
607 return nil;
609 if((newfid = fswalk(fid, nil)) == nil){
610 *err = errstr2errno();
611 return nil;
613 if(fsfcreate(newfid, name, omode, perm) < 0){
614 *err = errstr2errno();
615 fsclose(newfid);
616 return nil;
618 if((d = fsdirfstat(newfid)) == nil){
619 *err = errstr2errno();
620 fsfremove(newfid);
621 return nil;
623 /*
624 * This fid is no good, because it's open.
625 * We need an unopened fid. Sigh.
626 */
627 if((newfid2 = fswalk(fid, name)) == nil){
628 *err = errstr2errno();
629 free(d);
630 fsfremove(newfid);
631 return nil;
633 out->nodeid = allocnodeid(newfid2);
634 ff = lookupfusefid(out->nodeid, 1);
635 out->generation = ff->gen;
636 f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
637 f2timeout(entrytimeout, &out->entry_valid, &out->entry_valid_nsec);
638 dir2attr(d, &out->attr);
639 free(d);
640 return newfid;
643 void
644 fusemkdir(FuseMsg *m)
646 struct fuse_mkdir_in *in;
647 struct fuse_entry_out out;
648 CFid *fid;
649 int err;
650 char *name;
652 in = m->tx;
653 name = (char*)(in+1);
654 if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 1, OREAD, &out, &err)) == nil){
655 replyfuseerrno(m, err);
656 return;
658 /* Toss the open fid. */
659 fsclose(fid);
660 replyfuse(m, &out, sizeof out);
663 void
664 fusecreate(FuseMsg *m)
666 struct fuse_open_in *in;
667 struct fuse_create_out out;
668 CFid *fid;
669 int err, openmode, flags;
670 char *name;
672 in = m->tx;
673 flags = in->flags;
674 openmode = in->flags&3;
675 flags &= ~3;
676 flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE);
677 flags &= ~(O_CREAT|O_TRUNC); /* huh? */
678 if(flags){
679 fprint(2, "bad mode %#uo\n", in->flags);
680 replyfuseerrno(m, EACCES);
681 return;
683 name = (char*)(in+1);
684 if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 0, openmode, &out.e, &err)) == nil){
685 replyfuseerrno(m, err);
686 return;
688 out.o.fh = allocfh(fid);
689 out.o.open_flags = FOPEN_DIRECT_IO; /* no page cache */
690 replyfuse(m, &out, sizeof out);
693 /*
694 * Access.
695 * Lib9pclient implements this just as Plan 9 does,
696 * by opening the file (or not) and then closing it.
697 */
698 void
699 fuseaccess(FuseMsg *m)
701 struct fuse_access_in *in;
702 CFid *fid;
703 int err, omode;
704 static int a2o[] = {
705 0,
706 OEXEC,
707 OWRITE,
708 ORDWR,
709 OREAD,
710 OEXEC,
711 ORDWR,
712 ORDWR
713 };
715 in = m->tx;
716 if(in->mask >= nelem(a2o)){
717 replyfuseerrno(m, EINVAL);
718 return;
720 omode = a2o[in->mask];
721 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
722 replyfuseerrno(m, ESTALE);
723 return;
725 if(fsqid(fid).type&QTDIR)
726 omode = OREAD;
727 if((fid = _fuseopenfid(m->hdr->nodeid, 0, omode, &err)) == nil){
728 replyfuseerrno(m, err);
729 return;
731 fsclose(fid);
732 replyfuse(m, nil, 0);
735 /*
736 * Release.
737 * Equivalent of clunk for file handles.
738 * in->flags is the open mode used in Open or Opendir.
739 */
740 void
741 fuserelease(FuseMsg *m)
743 struct fuse_release_in *in;
744 Fusefid *ff;
746 in = m->tx;
747 if((ff = lookupfusefid(in->fh, 0)) != nil)
748 freefusefid(ff);
749 else
750 fprint(2, "fuserelease: fh not found\n");
751 replyfuse(m, nil, 0);
754 void
755 fusereleasedir(FuseMsg *m)
757 fuserelease(m);
760 /*
761 * Read.
762 * Read from file handle in->fh at offset in->offset for size in->size.
763 * We truncate size to maxwrite just to keep the buffer reasonable.
764 */
765 void
766 fuseread(FuseMsg *m)
768 int n;
769 uchar *buf;
770 CFid *fid;
771 struct fuse_read_in *in;
773 in = m->tx;
774 if((fid = fh2fid(in->fh)) == nil){
775 replyfuseerrno(m, ESTALE);
776 return;
778 n = in->size;
779 if(n > fusemaxwrite)
780 n = fusemaxwrite;
781 buf = emalloc(n);
782 n = fspread(fid, buf, n, in->offset);
783 if(n < 0){
784 free(buf);
785 replyfuseerrstr(m);
787 replyfuse(m, buf, n);
788 free(buf);
791 /*
792 * Readdir.
793 * Read from file handle in->fh at offset in->offset for size in->size.
794 * We truncate size to maxwrite just to keep the buffer reasonable.
795 * We assume 9P directory read semantics: a read at offset 0 rewinds
796 * and a read at any other offset starts where we left off.
797 * If it became necessary, we could implement a crude seek
798 * or cache the entire list of directory entries.
799 * Directory entries read from 9P but not yet handed to FUSE
800 * are stored in m->d,nd,d0.
801 */
802 int canpack(Dir*, uvlong, uchar**, uchar*);
803 void
804 fusereaddir(FuseMsg *m)
806 struct fuse_read_in *in;
807 uchar *buf, *p, *ep;
808 int n;
809 Fusefid *ff;
811 in = m->tx;
812 if((ff = lookupfusefid(in->fh, 0)) == nil){
813 replyfuseerrno(m, ESTALE);
814 return;
816 if(in->offset == 0){
817 fsseek(ff->fid, 0, 0);
818 free(ff->d0);
819 ff->d0 = nil;
820 ff->d = nil;
821 ff->nd = 0;
823 n = in->size;
824 if(n > fusemaxwrite)
825 n = fusemaxwrite;
826 buf = emalloc(n);
827 p = buf;
828 ep = buf + n;
829 for(;;){
830 while(ff->nd > 0){
831 if(!canpack(ff->d, ff->off, &p, ep))
832 goto out;
833 ff->off++;
834 ff->d++;
835 ff->nd--;
837 free(ff->d0);
838 ff->d0 = nil;
839 ff->d = nil;
840 if((ff->nd = fsdirread(ff->fid, &ff->d0)) < 0){
841 replyfuseerrstr(m);
842 free(buf);
843 return;
845 if(ff->nd == 0)
846 break;
847 ff->d = ff->d0;
849 out:
850 replyfuse(m, buf, p - buf);
851 free(buf);
854 int
855 canpack(Dir *d, uvlong off, uchar **pp, uchar *ep)
857 uchar *p;
858 struct fuse_dirent *de;
859 int pad, size;
861 p = *pp;
862 size = FUSE_NAME_OFFSET + strlen(d->name);
863 pad = 0;
864 if(size%8)
865 pad = 8 - size%8;
866 if(size+pad > ep - p)
867 return 0;
868 de = (struct fuse_dirent*)p;
869 de->ino = qid2inode(d->qid);
870 de->off = off;
871 de->namelen = strlen(d->name);
872 memmove(de->name, d->name, de->namelen);
873 if(pad > 0)
874 memset(de->name+de->namelen, 0, pad);
875 *pp = p+size+pad;
876 return 1;
879 /*
880 * Write.
881 * Write from file handle in->fh at offset in->offset for size in->size.
882 * Don't know what in->write_flags means.
884 * Apparently implementations are allowed to buffer these writes
885 * and wait until Flush is sent, but FUSE docs say flush may be
886 * called zero, one, or even more times per close. So better do the
887 * actual writing here. Also, errors that happen during Flush just
888 * show up in the close() return status, which no one checks anyway.
889 */
890 void
891 fusewrite(FuseMsg *m)
893 struct fuse_write_in *in;
894 struct fuse_write_out out;
895 void *a;
896 CFid *fid;
897 int n;
899 in = m->tx;
900 a = in+1;
901 if((fid = fh2fid(in->fh)) == nil){
902 replyfuseerrno(m, ESTALE);
903 return;
905 if(in->size > fusemaxwrite){
906 replyfuseerrno(m, EINVAL);
907 return;
909 n = fspwrite(fid, a, in->size, in->offset);
910 if(n < 0){
911 replyfuseerrstr(m);
912 return;
914 out.size = n;
915 replyfuse(m, &out, sizeof out);
918 /*
919 * Flush. Supposed to flush any buffered writes. Don't use this.
921 * Flush is a total crock. It gets called on close() of a file descriptor
922 * associated with this open file. Some open files have multiple file
923 * descriptors and thus multiple closes of those file descriptors.
924 * In those cases, Flush is called multiple times. Some open files
925 * have file descriptors that are closed on process exit instead of
926 * closed explicitly. For those files, Flush is never called.
927 * Even more amusing, Flush gets called before close() of read-only
928 * file descriptors too!
930 * This is just a bad idea.
931 */
932 void
933 fuseflush(FuseMsg *m)
935 replyfuse(m, nil, 0);
938 /*
939 * Unlink & Rmdir.
940 */
941 void
942 _fuseremove(FuseMsg *m, int isdir)
944 char *name;
945 CFid *fid, *newfid;
947 name = m->tx;
948 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
949 replyfuseerrno(m, ESTALE);
950 return;
952 if(strchr(name, '/')){
953 replyfuseerrno(m, ENOENT);
954 return;
956 if((newfid = fswalk(fid, name)) == nil){
957 replyfuseerrstr(m);
958 return;
960 if(isdir && !(fsqid(newfid).type&QTDIR)){
961 replyfuseerrno(m, ENOTDIR);
962 fsclose(newfid);
963 return;
965 if(!isdir && (fsqid(newfid).type&QTDIR)){
966 replyfuseerrno(m, EISDIR);
967 fsclose(newfid);
968 return;
970 if(fsfremove(newfid) < 0){
971 replyfuseerrstr(m);
972 return;
974 replyfuse(m, nil, 0);
977 void
978 fuseunlink(FuseMsg *m)
980 _fuseremove(m, 0);
983 void
984 fusermdir(FuseMsg *m)
986 _fuseremove(m, 1);
989 /*
990 * Rename.
992 * FUSE sends the nodeid for the source and destination
993 * directory and then the before and after names as strings.
994 * 9P can only do the rename if the source and destination
995 * are the same. If the same nodeid is used for source and
996 * destination, we're fine, but if FUSE gives us different nodeids
997 * that happen to correspond to the same directory, we have
998 * no way of figuring that out. Let's hope it doesn't happen too often.
999 */
1000 void
1001 fuserename(FuseMsg *m)
1003 struct fuse_rename_in *in;
1004 char *before, *after;
1005 CFid *fid, *newfid;
1006 Dir d;
1008 in = m->tx;
1009 if(in->newdir != m->hdr->nodeid){
1010 replyfuseerrno(m, EXDEV);
1011 return;
1013 before = (char*)(in+1);
1014 after = before + strlen(before) + 1;
1015 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
1016 replyfuseerrno(m, ESTALE);
1017 return;
1019 if(strchr(before, '/') || strchr(after, '/')){
1020 replyfuseerrno(m, ENOENT);
1021 return;
1023 if((newfid = fswalk(fid, before)) == nil){
1024 replyfuseerrstr(m);
1025 return;
1027 nulldir(&d);
1028 d.name = after;
1029 if(fsdirfwstat(newfid, &d) < 0){
1030 replyfuseerrstr(m);
1031 fsclose(newfid);
1032 return;
1034 fsclose(newfid);
1035 replyfuse(m, nil, 0);
1039 * Fsync. Commit file info to stable storage.
1040 * Not sure what in->fsync_flags are.
1042 void
1043 fusefsync(FuseMsg *m)
1045 struct fuse_fsync_in *in;
1046 CFid *fid;
1047 Dir d;
1049 in = m->tx;
1050 if((fid = fh2fid(in->fh)) == nil){
1051 replyfuseerrno(m, ESTALE);
1052 return;
1054 nulldir(&d);
1055 if(fsdirfwstat(fid, &d) < 0){
1056 replyfuseerrstr(m);
1057 return;
1059 replyfuse(m, nil, 0);
1063 * Fsyncdir. Commit dir info to stable storage?
1065 void
1066 fusefsyncdir(FuseMsg *m)
1068 fusefsync(m);
1072 * Statfs. Send back information about file system.
1073 * Not really worth implementing, except that if we
1074 * reply with ENOSYS, programs like df print messages like
1075 * df: `/tmp/z': Function not implemented
1076 * and that gets annoying. Returning all zeros excludes
1077 * us from df without appearing to cause any problems.
1079 void
1080 fusestatfs(FuseMsg *m)
1082 struct fuse_statfs_out out;
1084 memset(&out, 0, sizeof out);
1085 replyfuse(m, &out, sizeof out);
1088 void (*fusehandlers[100])(FuseMsg*);
1090 struct {
1091 int op;
1092 void (*fn)(FuseMsg*);
1093 } fuselist[] = {
1094 { FUSE_LOOKUP, fuselookup },
1095 { FUSE_FORGET, fuseforget },
1096 { FUSE_GETATTR, fusegetattr },
1097 { FUSE_SETATTR, fusesetattr },
1099 * FUSE_READLINK, FUSE_SYMLINK, FUSE_MKNOD are unimplemented.
1101 { FUSE_MKDIR, fusemkdir },
1102 { FUSE_UNLINK, fuseunlink },
1103 { FUSE_RMDIR, fusermdir },
1104 { FUSE_RENAME, fuserename },
1106 * FUSE_LINK is unimplemented.
1108 { FUSE_OPEN, fuseopen },
1109 { FUSE_READ, fuseread },
1110 { FUSE_WRITE, fusewrite },
1111 { FUSE_STATFS, fusestatfs },
1112 { FUSE_RELEASE, fuserelease },
1113 { FUSE_FSYNC, fusefsync },
1115 * FUSE_SETXATTR, FUSE_GETXATTR, FUSE_LISTXATTR, and
1116 * FUSE_REMOVEXATTR are unimplemented.
1117 * FUSE will stop sending these requests after getting
1118 * an -ENOSYS reply (see dispatch below).
1120 { FUSE_FLUSH, fuseflush },
1122 * FUSE_INIT is handled in initfuse and should not be seen again.
1124 { FUSE_OPENDIR, fuseopendir },
1125 { FUSE_READDIR, fusereaddir },
1126 { FUSE_RELEASEDIR, fusereleasedir },
1127 { FUSE_FSYNCDIR, fusefsyncdir },
1128 { FUSE_ACCESS, fuseaccess },
1129 { FUSE_CREATE, fusecreate },
1132 void
1133 fusethread(void *v)
1135 FuseMsg *m;
1137 m = v;
1138 if((uint)m->hdr->opcode >= nelem(fusehandlers)
1139 || !fusehandlers[m->hdr->opcode]){
1140 replyfuseerrno(m, ENOSYS);
1141 return;
1143 fusehandlers[m->hdr->opcode](m);
1146 void
1147 fusedispatch(void *v)
1149 int i;
1150 FuseMsg *m;
1152 eofkill9pclient = 1; /* threadexitsall on 9P eof */
1153 atexit(unmountatexit);
1155 recvp(fusechan); /* sync */
1157 for(i=0; i<nelem(fuselist); i++){
1158 if(fuselist[i].op >= nelem(fusehandlers))
1159 sysfatal("make fusehandlers bigger op=%d", fuselist[i].op);
1160 fusehandlers[fuselist[i].op] = fuselist[i].fn;
1163 while((m = recvp(fusechan)) != nil)
1164 threadcreate(fusethread, m, STACK);
1167 void*
1168 emalloc(uint n)
1170 void *p;
1172 p = malloc(n);
1173 if(p == nil)
1174 sysfatal("malloc(%d): %r", n);
1175 memset(p, 0, n);
1176 return p;
1179 void*
1180 erealloc(void *p, uint n)
1182 p = realloc(p, n);
1183 if(p == nil)
1184 sysfatal("realloc(..., %d): %r", n);
1185 return p;
1188 char*
1189 estrdup(char *p)
1191 char *pp;
1192 pp = strdup(p);
1193 if(pp == nil)
1194 sysfatal("strdup(%.20s): %r", p);
1195 return pp;