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