plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

main.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 }