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
26 #ifndef O_LARGEFILE
27 # define O_LARGEFILE 0
28 #endif
30 /*
31 * Work around glibc's broken <bits/fcntl.h> which defines
32 * O_LARGEFILE to 0 on 64 bit architectures. But, on those same
33 * architectures, linux _forces_ O_LARGEFILE (which is always
34 * 0100000 in the kernel) at each file open. FUSE is all too
35 * happy to pass the flag onto us, where we'd have no idea what
36 * to do with it if we trusted glibc.
37 */
38 #if defined(__linux__)
39 # undef O_LARGEFILE
40 # define O_LARGEFILE 0100000
41 #endif
43 #ifndef O_CLOEXEC
44 # if defined(__linux__)
45 # define O_CLOEXEC 02000000 /* Sigh */
46 # else
47 # define O_CLOEXEC 0
48 # endif
49 #endif
51 int debug;
52 char *argv0;
53 char *aname = "";
54 void fusedispatch(void*);
55 Channel *fusechan;
57 enum
58 {
59 STACK = 8192
60 };
62 /*
63 * The number of seconds that the kernel can cache
64 * returned file attributes. FUSE's default is 1.0.
65 * I haven't experimented with using 0.
66 */
67 double attrtimeout = 1.0;
69 /*
70 * The number of seconds that the kernel can cache
71 * the returned entry nodeids returned by lookup.
72 * I haven't experimented with other values.
73 */
74 double entrytimeout = 1.0;
76 CFsys *fsys;
77 CFid *fsysroot;
78 void init9p(char*, char*);
80 void
81 usage(void)
82 {
83 fprint(2, "usage: 9pfuse [-D] [-A attrtimeout] [-a aname] address mtpt\n");
84 exit(1);
85 }
87 void fusereader(void*);
88 void watchfd(void*);
90 void
91 threadmain(int argc, char **argv)
92 {
93 ARGBEGIN{
94 case 'D':
95 chatty9pclient++;
96 debug++;
97 break;
98 case 'A':
99 attrtimeout = atof(EARGF(usage()));
100 break;
101 case 'a':
102 aname = EARGF(usage());
103 break;
104 default:
105 usage();
106 }ARGEND
108 if(argc != 2)
109 usage();
111 quotefmtinstall();
112 fmtinstall('F', fcallfmt);
113 fmtinstall('M', dirmodefmt);
114 fmtinstall('G', fusefmt);
116 setsid(); /* won't be able to use console, but can't be interrupted */
118 init9p(argv[0], aname);
119 initfuse(argv[1]);
121 fusechan = chancreate(sizeof(void*), 0);
122 proccreate(fusedispatch, nil, STACK);
123 sendp(fusechan, nil); /* sync */
125 proccreate(fusereader, nil, STACK);
126 /*
127 * Now that we're serving FUSE, we can wait
128 * for the mount to finish and exit back to the user.
129 */
130 waitfuse();
131 threadexits(0);
134 void
135 fusereader(void *v)
137 FuseMsg *m;
139 while((m = readfusemsg()) != nil)
140 sendp(fusechan, m);
142 fusemtpt = nil; /* no need to unmount */
143 threadexitsall(0);
146 void
147 init9p(char *addr, char *spec)
149 int fd;
151 if(strcmp(addr, "-") == 0)
152 fd = 0;
153 else
154 if((fd = dial(netmkaddr(addr, "tcp", "564"), nil, nil, nil)) < 0)
155 sysfatal("dial %s: %r", addr);
156 proccreate(watchfd, (void*)(uintptr)fd, STACK);
157 if((fsys = fsmount(fd, spec)) == nil)
158 sysfatal("fsmount: %r");
159 fsysroot = fsroot(fsys);
162 /*
163 * FUSE uses nodeids to refer to active "struct inodes"
164 * (9P's unopened fids). FUSE uses fhs to refer to active
165 * "struct fuse_files" (9P's opened fids). The choice of
166 * numbers is up to us except that nodeid 1 is the root directory.
167 * We use the same number space for both and call the
168 * bookkeeping structure a FuseFid.
170 * FUSE requires nodeids to have associated generation
171 * numbers. If we reuse a nodeid, we have to bump the
172 * generation number to guarantee that the nodeid,gen
173 * combination is never reused.
175 * There are also inode numbers returned in directory reads
176 * and file attributes, but these do NOT need to match the nodeids.
177 * We use a combination of qid.path and qid.type as the inode
178 * number.
179 */
180 /*
181 * TO DO: reference count the fids.
182 */
183 typedef struct Fusefid Fusefid;
184 struct Fusefid
186 Fusefid *next;
187 CFid *fid;
188 int ref;
189 int id;
190 int gen;
191 int isnodeid;
193 /* directory read state */
194 Dir *d0;
195 Dir *d;
196 int nd;
197 int off;
198 };
200 Fusefid **fusefid;
201 int nfusefid;
202 Fusefid *freefusefidlist;
204 Fusefid*
205 allocfusefid(void)
207 Fusefid *f;
209 if((f = freefusefidlist) == nil){
210 f = emalloc(sizeof *f);
211 fusefid = erealloc(fusefid, (nfusefid+1)*sizeof *fusefid);
212 f->id = nfusefid;
213 fusefid[f->id] = f;
214 nfusefid++;
215 }else
216 freefusefidlist = f->next;
217 f->next = nil;
218 f->ref = 1;
219 f->isnodeid = -1;
220 return f;
223 void
224 freefusefid(Fusefid *f)
226 if(--f->ref > 0)
227 return;
228 assert(f->ref == 0);
229 if(f->fid)
230 fsclose(f->fid);
231 if(f->d0)
232 free(f->d0);
233 f->off = 0;
234 f->d0 = nil;
235 f->fid = nil;
236 f->d = nil;
237 f->nd = 0;
238 f->next = freefusefidlist;
239 f->isnodeid = -1;
240 freefusefidlist = f;
243 uvlong
244 _alloc(CFid *fid, int isnodeid)
246 Fusefid *ff;
248 ff = allocfusefid();
249 ff->fid = fid;
250 ff->isnodeid = isnodeid;
251 ff->gen++;
252 return ff->id+2; /* skip 0 and 1 */
255 uvlong
256 allocfh(CFid *fid)
258 return _alloc(fid, 0);
260 uvlong
261 allocnodeid(CFid *fid)
263 return _alloc(fid, 1);
266 Fusefid*
267 lookupfusefid(uvlong id, int isnodeid)
269 Fusefid *ff;
270 if(id < 2 || id >= nfusefid+2)
271 return nil;
272 ff = fusefid[(int)id-2];
273 if(ff->isnodeid != isnodeid)
274 return nil;
275 return ff;
278 CFid*
279 _lookupcfid(uvlong id, int isnodeid)
281 Fusefid *ff;
283 if((ff = lookupfusefid(id, isnodeid)) == nil)
284 return nil;
285 return ff->fid;
288 CFid*
289 fh2fid(uvlong fh)
291 return _lookupcfid(fh, 0);
294 CFid*
295 nodeid2fid(uvlong nodeid)
297 if(nodeid == 1)
298 return fsysroot;
299 return _lookupcfid(nodeid, 1);
302 uvlong
303 qid2inode(Qid q)
305 return q.path | ((uvlong)q.type<<56);
308 void
309 dir2attr(Dir *d, struct fuse_attr *attr)
311 attr->ino = qid2inode(d->qid);
312 attr->size = d->length;
313 attr->blocks = (d->length+8191)/8192;
314 attr->atime = d->atime;
315 attr->mtime = d->mtime;
316 attr->ctime = d->mtime; /* not right */
317 attr->atimensec = 0;
318 attr->mtimensec = 0;
319 attr->ctimensec = 0;
320 attr->mode = d->mode&0777;
321 if(d->mode&DMDIR)
322 attr->mode |= S_IFDIR;
323 else if(d->mode&DMSYMLINK)
324 attr->mode |= S_IFLNK;
325 else
326 attr->mode |= S_IFREG;
327 attr->nlink = 1; /* works for directories! - see FUSE FAQ */
328 attr->uid = getuid();
329 attr->gid = getgid();
330 attr->rdev = 0;
333 void
334 f2timeout(double f, __u64 *s, __u32 *ns)
336 *s = f;
337 *ns = (f - (int)f)*1e9;
340 void
341 dir2attrout(Dir *d, struct fuse_attr_out *out)
343 f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
344 dir2attr(d, &out->attr);
347 /*
348 * Lookup. Walk to the name given as the argument.
349 * The response is a fuse_entry_out giving full stat info.
350 */
351 void
352 fuselookup(FuseMsg *m)
354 char *name;
355 Fusefid *ff;
356 CFid *fid, *newfid;
357 Dir *d;
358 struct fuse_entry_out out;
360 name = m->tx;
361 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
362 replyfuseerrno(m, ESTALE);
363 return;
365 if(strchr(name, '/')){
366 replyfuseerrno(m, ENOENT);
367 return;
369 if((newfid = fswalk(fid, name)) == nil){
370 replyfuseerrstr(m);
371 return;
373 if((d = fsdirfstat(newfid)) == nil){
374 fsclose(newfid);
375 replyfuseerrstr(m);
376 return;
378 out.nodeid = allocnodeid(newfid);
379 ff = lookupfusefid(out.nodeid, 1);
380 out.generation = ff->gen;
381 f2timeout(attrtimeout, &out.attr_valid, &out.attr_valid_nsec);
382 f2timeout(entrytimeout, &out.entry_valid, &out.entry_valid_nsec);
383 dir2attr(d, &out.attr);
384 free(d);
385 replyfuse(m, &out, sizeof out);
388 /*
389 * Forget. Reference-counted clunk for nodeids.
390 * Does not send a reply.
391 * Each lookup response gives the kernel an additional reference
392 * to the returned nodeid. Forget says "drop this many references
393 * to this nodeid". Our fuselookup, when presented with the same query,
394 * does not return the same results (it allocates a new nodeid for each
395 * call), but if that ever changes, fuseforget already handles the ref
396 * counts properly.
397 */
398 void
399 fuseforget(FuseMsg *m)
401 struct fuse_forget_in *in;
402 Fusefid *ff;
404 in = m->tx;
405 if((ff = lookupfusefid(m->hdr->nodeid, 1)) == nil)
406 return;
407 if(ff->ref > in->nlookup){
408 ff->ref -= in->nlookup;
409 return;
411 if(ff->ref < in->nlookup)
412 fprint(2, "bad count in forget\n");
413 ff->ref = 1;
414 freefusefid(ff);
417 /*
418 * Getattr.
419 * Replies with a fuse_attr_out structure giving the
420 * attr for the requested nodeid in out.attr.
421 * Out.attr_valid and out.attr_valid_nsec give
422 * the amount of time that the attributes can
423 * be cached.
425 * Empirically, though, if I run ls -ld on the root
426 * twice back to back, I still get two getattrs,
427 * even with a one second attribute timeout!
428 */
429 void
430 fusegetattr(FuseMsg *m)
432 CFid *fid;
433 struct fuse_attr_out out;
434 Dir *d;
436 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
437 replyfuseerrno(m, ESTALE);
438 return;
440 if((d = fsdirfstat(fid)) == nil){
441 replyfuseerrstr(m);
442 return;
444 memset(&out, 0, sizeof out);
445 dir2attrout(d, &out);
446 free(d);
447 replyfuse(m, &out, sizeof out);
450 /*
451 * Setattr.
452 * FUSE treats the many Unix attribute setting routines
453 * more or less like 9P does, with a single message.
454 */
455 void
456 fusesetattr(FuseMsg *m)
458 CFid *fid, *nfid;
459 Dir d, *dd;
460 struct fuse_setattr_in *in;
461 struct fuse_attr_out out;
463 in = m->tx;
464 if(in->valid&FATTR_FH){
465 if((fid = fh2fid(in->fh)) == nil){
466 replyfuseerrno(m, ESTALE);
467 return;
469 }else{
470 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
471 replyfuseerrno(m, ESTALE);
472 return;
474 /*
475 * Special case: Linux issues a size change to
476 * truncate a file before opening it OTRUNC.
477 * Synthetic file servers (e.g., plumber) honor
478 * open(OTRUNC) but not wstat.
479 */
480 if(in->valid == FATTR_SIZE && in->size == 0){
481 if((nfid = fswalk(fid, nil)) == nil){
482 replyfuseerrstr(m);
483 return;
485 if(fsfopen(nfid, OWRITE|OTRUNC) < 0){
486 replyfuseerrstr(m);
487 fsclose(nfid);
488 return;
490 fsclose(nfid);
491 goto stat;
495 nulldir(&d);
496 if(in->valid&FATTR_SIZE)
497 d.length = in->size;
498 if(in->valid&FATTR_ATIME)
499 d.atime = in->atime;
500 if(in->valid&FATTR_MTIME)
501 d.mtime = in->mtime;
502 if(in->valid&FATTR_MODE)
503 d.mode = in->mode;
504 if((in->valid&FATTR_UID) || (in->valid&FATTR_GID)){
505 /*
506 * I can't be bothered with these yet.
507 */
508 replyfuseerrno(m, EPERM);
509 return;
511 if(fsdirfwstat(fid, &d) < 0){
512 replyfuseerrstr(m);
513 return;
515 stat:
516 if((dd = fsdirfstat(fid)) == nil){
517 replyfuseerrstr(m);
518 return;
520 memset(&out, 0, sizeof out);
521 dir2attrout(dd, &out);
522 free(dd);
523 replyfuse(m, &out, sizeof out);
526 CFid*
527 _fuseopenfid(uvlong nodeid, int isdir, int openmode, int *err)
529 CFid *fid, *newfid;
531 if((fid = nodeid2fid(nodeid)) == nil){
532 *err = ESTALE;
533 return nil;
535 if(isdir && !(fsqid(fid).type&QTDIR)){
536 *err = ENOTDIR;
537 return nil;
539 if(openmode != OREAD && fsqid(fid).type&QTDIR){
540 *err = EISDIR;
541 return nil;
544 /* Clone fid to get one we can open. */
545 newfid = fswalk(fid, nil);
546 if(newfid == nil){
547 *err = errstr2errno();
548 return nil;
551 if(fsfopen(newfid, openmode) < 0){
552 *err = errstr2errno();
553 fsclose(newfid);
554 return nil;
557 return newfid;
560 /*
561 * Open & Opendir.
562 * Argument is a struct fuse_open_in.
563 * The mode field is ignored (presumably permission bits)
564 * and flags is the open mode.
565 * Replies with a struct fuse_open_out.
566 */
567 void
568 _fuseopen(FuseMsg *m, int isdir)
570 struct fuse_open_in *in;
571 struct fuse_open_out out;
572 CFid *fid;
573 int openmode, flags, err;
575 in = m->tx;
576 flags = in->flags;
577 openmode = flags&3;
578 flags &= ~3;
579 flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC);
580 #ifdef O_NOFOLLOW
581 flags &= ~O_NOFOLLOW;
582 #endif
583 #ifdef O_LARGEFILE
584 flags &= ~O_LARGEFILE;
585 #endif
587 /*
588 * Discarding O_APPEND here is not completely wrong,
589 * because the host kernel will rewrite the offsets
590 * of write system calls for us. That's the best we
591 * can do on Unix anyway.
592 */
593 flags &= ~O_APPEND;
594 if(flags & O_TRUNC){
595 openmode |= OTRUNC;
596 flags &= ~O_TRUNC;
598 /*
599 * Could translate but not standard 9P:
600 * O_DIRECT -> ODIRECT
601 * O_NONBLOCK -> ONONBLOCK
602 */
603 if(flags){
604 fprint(2, "unexpected open flags %#uo\n", (uint)in->flags);
605 replyfuseerrno(m, EACCES);
606 return;
608 if((fid = _fuseopenfid(m->hdr->nodeid, isdir, openmode, &err)) == nil){
609 replyfuseerrno(m, err);
610 return;
612 out.fh = allocfh(fid);
613 out.open_flags = FOPEN_DIRECT_IO; /* no page cache */
614 replyfuse(m, &out, sizeof out);
617 void
618 fuseopen(FuseMsg *m)
620 _fuseopen(m, 0);
623 void
624 fuseopendir(FuseMsg *m)
626 _fuseopen(m, 1);
629 /*
630 * Create & Mkdir.
631 */
632 CFid*
633 _fusecreate(uvlong nodeid, char *name, int perm, int ismkdir, int omode, struct fuse_entry_out *out, int *err)
635 CFid *fid, *newfid, *newfid2;
636 Dir *d;
637 Fusefid *ff;
639 if((fid = nodeid2fid(nodeid)) == nil){
640 *err = ESTALE;
641 return nil;
643 perm &= 0777;
644 if(ismkdir)
645 perm |= DMDIR;
646 if(ismkdir && omode != OREAD){
647 *err = EPERM;
648 return nil;
650 if((newfid = fswalk(fid, nil)) == nil){
651 *err = errstr2errno();
652 return nil;
654 if(fsfcreate(newfid, name, omode, perm) < 0){
655 *err = errstr2errno();
656 fsclose(newfid);
657 return nil;
659 if((d = fsdirfstat(newfid)) == nil){
660 *err = errstr2errno();
661 fsfremove(newfid);
662 return nil;
664 /*
665 * This fid is no good, because it's open.
666 * We need an unopened fid. Sigh.
667 */
668 if((newfid2 = fswalk(fid, name)) == nil){
669 *err = errstr2errno();
670 free(d);
671 fsfremove(newfid);
672 return nil;
674 out->nodeid = allocnodeid(newfid2);
675 ff = lookupfusefid(out->nodeid, 1);
676 out->generation = ff->gen;
677 f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
678 f2timeout(entrytimeout, &out->entry_valid, &out->entry_valid_nsec);
679 dir2attr(d, &out->attr);
680 free(d);
681 return newfid;
684 void
685 fusemkdir(FuseMsg *m)
687 struct fuse_mkdir_in *in;
688 struct fuse_entry_out out;
689 CFid *fid;
690 int err;
691 char *name;
693 in = m->tx;
694 name = (char*)(in+1);
695 if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 1, OREAD, &out, &err)) == nil){
696 replyfuseerrno(m, err);
697 return;
699 /* Toss the open fid. */
700 fsclose(fid);
701 replyfuse(m, &out, sizeof out);
704 void
705 fusecreate(FuseMsg *m)
707 struct fuse_open_in *in;
708 struct fuse_create_out out;
709 CFid *fid;
710 int err, openmode, flags;
711 char *name;
713 in = m->tx;
714 flags = in->flags;
715 openmode = in->flags&3;
716 flags &= ~3;
717 flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_EXCL);
718 flags &= ~O_APPEND; /* see comment in _fuseopen */
719 flags &= ~(O_CREAT|O_TRUNC); /* huh? */
720 if(flags){
721 fprint(2, "bad mode %#uo\n", in->flags);
722 replyfuseerrno(m, EACCES);
723 return;
725 name = (char*)(in+1);
726 if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 0, openmode, &out.e, &err)) == nil){
727 replyfuseerrno(m, err);
728 return;
730 out.o.fh = allocfh(fid);
731 out.o.open_flags = FOPEN_DIRECT_IO; /* no page cache */
732 replyfuse(m, &out, sizeof out);
735 /*
736 * Access.
737 * Lib9pclient implements this just as Plan 9 does,
738 * by opening the file (or not) and then closing it.
739 */
740 void
741 fuseaccess(FuseMsg *m)
743 struct fuse_access_in *in;
744 CFid *fid;
745 int err, omode;
746 static int a2o[] = {
747 0,
748 OEXEC,
749 OWRITE,
750 ORDWR,
751 OREAD,
752 OEXEC,
753 ORDWR,
754 ORDWR
755 };
757 in = m->tx;
758 if(in->mask >= nelem(a2o)){
759 replyfuseerrno(m, EINVAL);
760 return;
762 omode = a2o[in->mask];
763 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
764 replyfuseerrno(m, ESTALE);
765 return;
767 if(fsqid(fid).type&QTDIR)
768 omode = OREAD;
769 if((fid = _fuseopenfid(m->hdr->nodeid, 0, omode, &err)) == nil){
770 replyfuseerrno(m, err);
771 return;
773 fsclose(fid);
774 replyfuse(m, nil, 0);
777 /*
778 * Release.
779 * Equivalent of clunk for file handles.
780 * in->flags is the open mode used in Open or Opendir.
781 */
782 void
783 fuserelease(FuseMsg *m)
785 struct fuse_release_in *in;
786 Fusefid *ff;
788 in = m->tx;
789 if((ff = lookupfusefid(in->fh, 0)) != nil)
790 freefusefid(ff);
791 else
792 fprint(2, "fuserelease: fh not found\n");
793 replyfuse(m, nil, 0);
796 void
797 fusereleasedir(FuseMsg *m)
799 fuserelease(m);
802 /*
803 * Read.
804 * Read from file handle in->fh at offset in->offset for size in->size.
805 * We truncate size to maxwrite just to keep the buffer reasonable.
806 */
807 void
808 fuseread(FuseMsg *m)
810 int n;
811 uchar *buf;
812 CFid *fid;
813 struct fuse_read_in *in;
815 in = m->tx;
816 if((fid = fh2fid(in->fh)) == nil){
817 replyfuseerrno(m, ESTALE);
818 return;
820 n = in->size;
821 if(n > fusemaxwrite)
822 n = fusemaxwrite;
823 buf = emalloc(n);
824 n = fspread(fid, buf, n, in->offset);
825 if(n < 0){
826 free(buf);
827 replyfuseerrstr(m);
828 return;
830 replyfuse(m, buf, n);
831 free(buf);
834 /*
835 * Readlink.
836 */
837 void
838 fusereadlink(FuseMsg *m)
840 Dir *d;
841 CFid *fid;
843 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
844 replyfuseerrno(m, ESTALE);
845 return;
847 if((d = fsdirfstat(fid)) == nil){
848 replyfuseerrstr(m);
849 return;
851 if(!(d->mode&DMSYMLINK)){
852 replyfuseerrno(m, EINVAL);
853 return;
855 replyfuse(m, d->ext, strlen(d->ext));
856 free(d);
857 return;
860 /*
861 * Readdir.
862 * Read from file handle in->fh at offset in->offset for size in->size.
863 * We truncate size to maxwrite just to keep the buffer reasonable.
864 * We assume 9P directory read semantics: a read at offset 0 rewinds
865 * and a read at any other offset starts where we left off.
866 * If it became necessary, we could implement a crude seek
867 * or cache the entire list of directory entries.
868 * Directory entries read from 9P but not yet handed to FUSE
869 * are stored in m->d,nd,d0.
870 */
871 int canpack(Dir*, uvlong, uchar**, uchar*);
872 Dir *dotdirs(CFid*);
873 void
874 fusereaddir(FuseMsg *m)
876 struct fuse_read_in *in;
877 uchar *buf, *p, *ep;
878 int n;
879 Fusefid *ff;
881 in = m->tx;
882 if((ff = lookupfusefid(in->fh, 0)) == nil){
883 replyfuseerrno(m, ESTALE);
884 return;
886 if(in->offset == 0){
887 fsseek(ff->fid, 0, 0);
888 free(ff->d0);
889 ff->d0 = ff->d = dotdirs(ff->fid);
890 ff->nd = 2;
892 n = in->size;
893 if(n > fusemaxwrite)
894 n = fusemaxwrite;
895 buf = emalloc(n);
896 p = buf;
897 ep = buf + n;
898 for(;;){
899 while(ff->nd > 0){
900 if(!canpack(ff->d, ff->off, &p, ep))
901 goto out;
902 ff->off++;
903 ff->d++;
904 ff->nd--;
906 free(ff->d0);
907 ff->d0 = nil;
908 ff->d = nil;
909 if((ff->nd = fsdirread(ff->fid, &ff->d0)) < 0){
910 replyfuseerrstr(m);
911 free(buf);
912 return;
914 if(ff->nd == 0)
915 break;
916 ff->d = ff->d0;
918 out:
919 replyfuse(m, buf, p - buf);
920 free(buf);
923 /*
924 * Fuse assumes that it can always read two directory entries.
925 * If it gets just one, it will double it in the dirread results.
926 * Thus if a directory contains just "a", you see "a" twice.
927 * Adding . as the first directory entry works around this.
928 * We could add .. too, but it isn't necessary.
929 */
930 Dir*
931 dotdirs(CFid *f)
933 Dir *d;
934 CFid *f1;
936 d = emalloc(2*sizeof *d);
937 d[0].name = ".";
938 d[0].qid = fsqid(f);
939 d[1].name = "..";
940 f1 = fswalk(f, "..");
941 if(f1){
942 d[1].qid = fsqid(f1);
943 fsclose(f1);
945 return d;
948 int
949 canpack(Dir *d, uvlong off, uchar **pp, uchar *ep)
951 uchar *p;
952 struct fuse_dirent *de;
953 int pad, size;
955 p = *pp;
956 size = FUSE_NAME_OFFSET + strlen(d->name);
957 pad = 0;
958 if(size%8)
959 pad = 8 - size%8;
960 if(size+pad > ep - p)
961 return 0;
962 de = (struct fuse_dirent*)p;
963 de->ino = qid2inode(d->qid);
964 de->off = off;
965 de->namelen = strlen(d->name);
966 memmove(de->name, d->name, de->namelen);
967 if(pad > 0)
968 memset(de->name+de->namelen, 0, pad);
969 *pp = p+size+pad;
970 return 1;
973 /*
974 * Write.
975 * Write from file handle in->fh at offset in->offset for size in->size.
976 * Don't know what in->write_flags means.
978 * Apparently implementations are allowed to buffer these writes
979 * and wait until Flush is sent, but FUSE docs say flush may be
980 * called zero, one, or even more times per close. So better do the
981 * actual writing here. Also, errors that happen during Flush just
982 * show up in the close() return status, which no one checks anyway.
983 */
984 void
985 fusewrite(FuseMsg *m)
987 struct fuse_write_in *in;
988 struct fuse_write_out out;
989 void *a;
990 CFid *fid;
991 int n;
993 in = m->tx;
994 a = in+1;
995 if((fid = fh2fid(in->fh)) == nil){
996 replyfuseerrno(m, ESTALE);
997 return;
999 if(in->size > fusemaxwrite){
1000 replyfuseerrno(m, EINVAL);
1001 return;
1003 n = fspwrite(fid, a, in->size, in->offset);
1004 if(n < 0){
1005 replyfuseerrstr(m);
1006 return;
1008 out.size = n;
1009 replyfuse(m, &out, sizeof out);
1013 * Flush. Supposed to flush any buffered writes. Don't use this.
1015 * Flush is a total crock. It gets called on close() of a file descriptor
1016 * associated with this open file. Some open files have multiple file
1017 * descriptors and thus multiple closes of those file descriptors.
1018 * In those cases, Flush is called multiple times. Some open files
1019 * have file descriptors that are closed on process exit instead of
1020 * closed explicitly. For those files, Flush is never called.
1021 * Even more amusing, Flush gets called before close() of read-only
1022 * file descriptors too!
1024 * This is just a bad idea.
1026 void
1027 fuseflush(FuseMsg *m)
1029 replyfuse(m, nil, 0);
1033 * Unlink & Rmdir.
1035 void
1036 _fuseremove(FuseMsg *m, int isdir)
1038 char *name;
1039 CFid *fid, *newfid;
1041 name = m->tx;
1042 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
1043 replyfuseerrno(m, ESTALE);
1044 return;
1046 if(strchr(name, '/')){
1047 replyfuseerrno(m, ENOENT);
1048 return;
1050 if((newfid = fswalk(fid, name)) == nil){
1051 replyfuseerrstr(m);
1052 return;
1054 if(isdir && !(fsqid(newfid).type&QTDIR)){
1055 replyfuseerrno(m, ENOTDIR);
1056 fsclose(newfid);
1057 return;
1059 if(!isdir && (fsqid(newfid).type&QTDIR)){
1060 replyfuseerrno(m, EISDIR);
1061 fsclose(newfid);
1062 return;
1064 if(fsfremove(newfid) < 0){
1065 replyfuseerrstr(m);
1066 return;
1068 replyfuse(m, nil, 0);
1071 void
1072 fuseunlink(FuseMsg *m)
1074 _fuseremove(m, 0);
1077 void
1078 fusermdir(FuseMsg *m)
1080 _fuseremove(m, 1);
1084 * Rename.
1086 * FUSE sends the nodeid for the source and destination
1087 * directory and then the before and after names as strings.
1088 * 9P can only do the rename if the source and destination
1089 * are the same. If the same nodeid is used for source and
1090 * destination, we're fine, but if FUSE gives us different nodeids
1091 * that happen to correspond to the same directory, we have
1092 * no way of figuring that out. Let's hope it doesn't happen too often.
1094 void
1095 fuserename(FuseMsg *m)
1097 struct fuse_rename_in *in;
1098 char *before, *after;
1099 CFid *fid, *newfid;
1100 Dir d;
1102 in = m->tx;
1103 if(in->newdir != m->hdr->nodeid){
1104 replyfuseerrno(m, EXDEV);
1105 return;
1107 before = (char*)(in+1);
1108 after = before + strlen(before) + 1;
1109 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
1110 replyfuseerrno(m, ESTALE);
1111 return;
1113 if(strchr(before, '/') || strchr(after, '/')){
1114 replyfuseerrno(m, ENOENT);
1115 return;
1117 if((newfid = fswalk(fid, before)) == nil){
1118 replyfuseerrstr(m);
1119 return;
1121 nulldir(&d);
1122 d.name = after;
1123 if(fsdirfwstat(newfid, &d) < 0){
1124 replyfuseerrstr(m);
1125 fsclose(newfid);
1126 return;
1128 fsclose(newfid);
1129 replyfuse(m, nil, 0);
1133 * Fsync. Commit file info to stable storage.
1134 * Not sure what in->fsync_flags are.
1136 void
1137 fusefsync(FuseMsg *m)
1139 struct fuse_fsync_in *in;
1140 CFid *fid;
1141 Dir d;
1143 in = m->tx;
1144 if((fid = fh2fid(in->fh)) == nil){
1145 replyfuseerrno(m, ESTALE);
1146 return;
1148 nulldir(&d);
1149 if(fsdirfwstat(fid, &d) < 0){
1150 replyfuseerrstr(m);
1151 return;
1153 replyfuse(m, nil, 0);
1157 * Fsyncdir. Commit dir info to stable storage?
1159 void
1160 fusefsyncdir(FuseMsg *m)
1162 fusefsync(m);
1166 * Statfs. Send back information about file system.
1167 * Not really worth implementing, except that if we
1168 * reply with ENOSYS, programs like df print messages like
1169 * df: `/tmp/z': Function not implemented
1170 * and that gets annoying. Returning all zeros excludes
1171 * us from df without appearing to cause any problems.
1173 void
1174 fusestatfs(FuseMsg *m)
1176 struct fuse_statfs_out out;
1178 memset(&out, 0, sizeof out);
1179 replyfuse(m, &out, sizeof out);
1182 void (*fusehandlers[100])(FuseMsg*);
1184 struct {
1185 int op;
1186 void (*fn)(FuseMsg*);
1187 } fuselist[] = {
1188 { FUSE_LOOKUP, fuselookup },
1189 { FUSE_FORGET, fuseforget },
1190 { FUSE_GETATTR, fusegetattr },
1191 { FUSE_SETATTR, fusesetattr },
1193 * FUSE_SYMLINK, FUSE_MKNOD are unimplemented.
1195 { FUSE_READLINK, fusereadlink },
1196 { FUSE_MKDIR, fusemkdir },
1197 { FUSE_UNLINK, fuseunlink },
1198 { FUSE_RMDIR, fusermdir },
1199 { FUSE_RENAME, fuserename },
1201 * FUSE_LINK is unimplemented.
1203 { FUSE_OPEN, fuseopen },
1204 { FUSE_READ, fuseread },
1205 { FUSE_WRITE, fusewrite },
1206 { FUSE_STATFS, fusestatfs },
1207 { FUSE_RELEASE, fuserelease },
1208 { FUSE_FSYNC, fusefsync },
1210 * FUSE_SETXATTR, FUSE_GETXATTR, FUSE_LISTXATTR, and
1211 * FUSE_REMOVEXATTR are unimplemented.
1212 * FUSE will stop sending these requests after getting
1213 * an -ENOSYS reply (see dispatch below).
1215 { FUSE_FLUSH, fuseflush },
1217 * FUSE_INIT is handled in initfuse and should not be seen again.
1219 { FUSE_OPENDIR, fuseopendir },
1220 { FUSE_READDIR, fusereaddir },
1221 { FUSE_RELEASEDIR, fusereleasedir },
1222 { FUSE_FSYNCDIR, fusefsyncdir },
1223 { FUSE_ACCESS, fuseaccess },
1224 { FUSE_CREATE, fusecreate },
1227 void
1228 fusethread(void *v)
1230 FuseMsg *m;
1232 m = v;
1233 if((uint)m->hdr->opcode >= nelem(fusehandlers)
1234 || !fusehandlers[m->hdr->opcode]){
1235 replyfuseerrno(m, ENOSYS);
1236 return;
1238 fusehandlers[m->hdr->opcode](m);
1241 void
1242 fusedispatch(void *v)
1244 int i;
1245 FuseMsg *m;
1247 eofkill9pclient = 1; /* threadexitsall on 9P eof */
1248 atexit(unmountatexit);
1250 recvp(fusechan); /* sync */
1252 for(i=0; i<nelem(fuselist); i++){
1253 if(fuselist[i].op >= nelem(fusehandlers))
1254 sysfatal("make fusehandlers bigger op=%d", fuselist[i].op);
1255 fusehandlers[fuselist[i].op] = fuselist[i].fn;
1258 while((m = recvp(fusechan)) != nil)
1259 threadcreate(fusethread, m, STACK);
1262 void*
1263 emalloc(uint n)
1265 void *p;
1267 p = malloc(n);
1268 if(p == nil)
1269 sysfatal("malloc(%d): %r", n);
1270 memset(p, 0, n);
1271 return p;
1274 void*
1275 erealloc(void *p, uint n)
1277 p = realloc(p, n);
1278 if(p == nil)
1279 sysfatal("realloc(..., %d): %r", n);
1280 return p;
1283 char*
1284 estrdup(char *p)
1286 char *pp;
1287 pp = strdup(p);
1288 if(pp == nil)
1289 sysfatal("strdup(%.20s): %r", p);
1290 return pp;
1293 void
1294 watchfd(void *v)
1296 int fd = (int)(uintptr)v;
1298 /* wait for exception (file closed) */
1299 fd_set set;
1300 FD_ZERO(&set);
1301 FD_SET(fd, &set);
1302 if(select(fd+1, NULL, NULL, &set, NULL) >= 0)
1303 threadexitsall(nil);
1304 return;