shithub: riscv

Download patch

ref: 0ce50ebc5750c15e30c6f2d5ba23a0dd329c6c47
parent: 501774b0968d59994d5012fab62fa8221d8b7923
author: cinap_lenrek <[email protected]>
date: Fri Aug 21 14:43:25 EDT 2015

cwfs: remove 9p1 support

--- a/sys/src/cmd/cwfs/9netics32.16k/conf.c
+++ b/sys/src/cmd/cwfs/9netics32.16k/conf.c
@@ -25,7 +25,6 @@
 }
 
 int (*fsprotocol[])(Msgbuf*) = {
-	serve9p1,
 	serve9p2,
 	nil,
 };
--- a/sys/src/cmd/cwfs/9p1.c
+++ /dev/null
@@ -1,1611 +1,0 @@
-#include "all.h"
-#include "9p1.h"
-
-extern Nvrsafe	nvr;
-
-typedef struct {
-	uchar	chal[CHALLEN];		/* locally generated challenge */
-	uchar	rchal[CHALLEN];		/* remotely generated challenge */
-	Lock	idlock;
-	ulong	idoffset;		/* offset of id vector */
-	ulong	idvec;			/* vector of acceptable id's */
-} Authinfo;
-
-static void
-f_nop(Chan *cp, Fcall*, Fcall*)
-{
-	if(CHAT(cp))
-		fprint(2, "c_nop %d\n", cp->chan);
-}
-
-static void
-f_flush(Chan *cp, Fcall*, Fcall*)
-{
-	if(CHAT(cp))
-		fprint(2, "c_flush %d\n", cp->chan);
-	runlock(&cp->reflock);
-	wlock(&cp->reflock);
-	wunlock(&cp->reflock);
-	rlock(&cp->reflock);
-}
-
-/*
- *  create a challenge for a fid space
- */
-static void
-mkchallenge(Authinfo *aip)
-{
-	int i;
-
-	srand((uintptr)aip + time(nil));
-	for(i = 0; i < CHALLEN; i++)
-		aip->chal[i] = nrand(256);
-
-	aip->idoffset = 0;
-	aip->idvec = 0;
-}
-
-static void
-f_session(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Authinfo *aip;
-
-	aip = (Authinfo*)cp->authinfo;
-
-	if(CHAT(cp))
-		fprint(2, "c_session %d\n", cp->chan);
-	memmove(aip->rchal, in->chal, sizeof(aip->rchal));
-	mkchallenge(aip);
-	memmove(ou->chal, aip->chal, sizeof(ou->chal));
-	if(noauth)
-		memset(ou->authid, 0, sizeof(ou->authid));
-	else
-		memmove(ou->authid, nvr.authid, sizeof(ou->authid));
-
-	sprint(ou->authdom, "%s.%s", service, nvr.authdom);
-	fileinit(cp);
-}
-
-/*
- *  match a challenge from an attach
- */
-static int
-authorize(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Ticket t;
-	Authenticator a;
-	int x;
-	ulong bit;
-	Authinfo *aip;
-
-	if(noauth)
-		return 1;
-
-	if(strcmp(in->uname, "none") == 0)
-		return !nonone || cp->authok;
-
-	if(in->type == Toattach)
-		return 0;
-
-	/* decrypt and unpack ticket */
-	convM2T9p1(in->ticket, &t, nvr.machkey);
-	if(t.num != AuthTs){
-		fprint(2, "9p1: bad AuthTs num\n");
-		return 0;
-	}
-
-	/* decrypt and unpack authenticator */
-	convM2A9p1(in->auth, &a, t.key);
-	if(a.num != AuthAc){
-		fprint(2, "9p1: bad AuthAc num\n");
-		return 0;
-	}
-
-	/* challenges must match */
-	aip = (Authinfo*)cp->authinfo;
-	if(memcmp(a.chal, aip->chal, sizeof(a.chal)) != 0){
-		fprint(2, "9p1: bad challenge\n");
-		return 0;
-	}
-
-	/*
-	 *  the id must be in a valid range.  the range is specified by a
-	 *  lower bound (idoffset) and a bit vector (idvec) where a
-	 *  bit set to 1 means unusable
-	 */
-	lock(&aip->idlock);
-	x = a.id - aip->idoffset;
-	bit = 1<<x;
-	if(x < 0 || x > 31 || (bit&aip->idvec)){
-		unlock(&aip->idlock);
-		fprint(2, "9p1: id out of range: idoff %ld idvec %lux id %ld\n",
-		   aip->idoffset, aip->idvec, a.id);
-		return 0;
-	}
-	aip->idvec |= bit;
-
-	/* normalize the vector */
-	while(aip->idvec&0xffff0001){
-		aip->idvec >>= 1;
-		aip->idoffset++;
-	}
-	unlock(&aip->idlock);
-
-	/* ticket name and attach name must match */
-	if(memcmp(in->uname, t.cuid, sizeof(in->uname)) != 0){
-		fprint(2, "9p1: names don't match\n");
-		return 0;
-	}
-
-	/* copy translated name into input record */
-	memmove(in->uname, t.suid, sizeof(in->uname));
-
-	/* craft a reply */
-	a.num = AuthAs;
-	memmove(a.chal, aip->rchal, CHALLEN);
-	convA2M9p1(&a, ou->rauth, t.key);
-
-	cp->authok = 1;
-
-	return 1;
-}
-
-/*
- * buggery to give false qid for
- * the top 2 levels of the dump fs
- */
-void
-mkqid(Qid* qid, Dentry *d, int buggery)
-{
-	int c;
-
-	if(buggery && d->qid.path == (QPDIR|QPROOT)){
-		c = d->name[0];
-		if(isascii(c) && isdigit(c)){
-			qid->path = 3;
-			qid->vers = d->qid.version;
-			qid->type = QTDIR;
-
-			c = (c-'0')*10 + (d->name[1]-'0');
-			if(c >= 1 && c <= 12)
-				qid->path = 4;
-			return;
-		}
-	}
-
-	mkqid9p2(qid, &d->qid, d->mode);
-}
-
-int
-mkqidcmp(Qid* qid, Dentry *d)
-{
-	Qid tmp;
-
-	mkqid(&tmp, d, 1);
-	if(qid->path == tmp.path && qid->type == tmp.type)
-		return 0;
-	return Eqid;
-}
-
-static void
-f_attach(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Iobuf *p;
-	Dentry *d;
-	File *f;
-	int u;
-	Filsys *fs;
-	Off raddr;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_attach %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-		fprint(2, "\tuid = %s\n", in->uname);
-		fprint(2, "\targ = %s\n", in->aname);
-	}
-
-	ou->qid = QID9P1(0,0);
-	ou->fid = in->fid;
-	if(!in->aname[0])	/* default */
-		strncpy(in->aname, "main", sizeof(in->aname));
-	p = 0;
-	f = filep(cp, in->fid, 1);
-	if(!f) {
-		ou->err = Efid;
-		goto out;
-	}
-
-	u = -1;
-	if(cp != cons.chan) {
-		if(noattach && strcmp(in->uname, "none")) {
-			ou->err = Enoattach;
-			goto out;
-		}
-		if(authorize(cp, in, ou) == 0 || strcmp(in->uname, "adm") == 0) {
-			ou->err = Eauth;
-			goto out;
-		}
-		u = strtouid(in->uname);
-		if(u < 0) {
-			ou->err = Ebadu;
-			goto out;
-		}
-	}
-	f->uid = u;
-
-	fs = fsstr(in->aname);
-	if(fs == 0) {
-		ou->err = Ebadspc;
-		goto out;
-	}
-	raddr = getraddr(fs->dev);
-	p = getbuf(fs->dev, raddr, Brd);
-	d = getdir(p, 0);
-	if(!d || checktag(p, Tdir, QPROOT) || !(d->mode & DALLOC)) {
-		ou->err = Ealloc;
-		goto out;
-	}
-	if(iaccess(f, d, DEXEC) ||
-	    f->uid == 0 && fs->dev->type == Devro) {
-		/*
-		 * 'none' not allowed on dump
-		 */
-		ou->err = Eaccess;
-		goto out;
-	}
-	accessdir(p, d, FREAD, f->uid);
-	mkqid(&f->qid, d, 1);
-	f->fs = fs;
-	f->addr = raddr;
-	f->slot = 0;
-	f->open = 0;
-	freewp(f->wpath);
-	f->wpath = 0;
-
-	mkqid9p1(&ou->qid, &f->qid);
-
-	strncpy(cp->whoname, in->uname, sizeof(cp->whoname));
-	cp->whotime = time(nil);
-
-out:
-	if(p)
-		putbuf(p);
-	if(f) {
-		qunlock(f);
-		if(ou->err)
-			freefp(f);
-	}
-}
-
-static void
-f_clone(Chan *cp, Fcall *in, Fcall *ou)
-{
-	File *f1, *f2;
-	Wpath *p;
-	int fid, fid1;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_clone %d\n", cp->chan);
-		fprint(2, "\told fid = %d\n", in->fid);
-		fprint(2, "\tnew fid = %d\n", in->newfid);
-	}
-
-	fid = in->fid;
-	fid1 = in->newfid;
-
-	f1 = 0;
-	f2 = 0;
-	if(fid < fid1) {
-		f1 = filep(cp, fid, 0);
-		f2 = filep(cp, fid1, 1);
-	} else
-	if(fid1 < fid) {
-		f2 = filep(cp, fid1, 1);
-		f1 = filep(cp, fid, 0);
-	}
-	if(!f1 || !f2) {
-		ou->err = Efid;
-		goto out;
-	}
-
-
-	f2->fs = f1->fs;
-	f2->addr = f1->addr;
-	f2->open = f1->open & ~FREMOV;
-	f2->uid = f1->uid;
-	f2->slot = f1->slot;
-	f2->qid = f1->qid;
-
-	freewp(f2->wpath);
-	lock(&wpathlock);
-	f2->wpath = f1->wpath;
-	for(p = f2->wpath; p; p = p->up)
-		p->refs++;
-	unlock(&wpathlock);
-
-out:
-	ou->fid = fid;
-	if(f1)
-		qunlock(f1);
-	if(f2) {
-		qunlock(f2);
-		if(ou->err)
-			freefp(f2);
-	}
-}
-
-static void
-f_walk(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Iobuf *p, *p1;
-	Dentry *d, *d1;
-	File *f;
-	Wpath *w;
-	int slot, mask;
-	Off addr, qpath;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_walk %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-		fprint(2, "\tname = %s\n", in->name);
-	}
-
-	ou->fid = in->fid;
-	ou->qid = QID9P1(0,0);
-	p = 0;
-	f = filep(cp, in->fid, 0);
-	if(!f) {
-		ou->err = Efid;
-		goto out;
-	}
-	p = getbuf(f->fs->dev, f->addr, Brd);
-	d = getdir(p, f->slot);
-	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-		ou->err = Ealloc;
-		goto out;
-	}
-	if(!(d->mode & DDIR)) {
-		ou->err = Edir1;
-		goto out;
-	}
-	if(ou->err = mkqidcmp(&f->qid, d))
-		goto out;
-	if(iaccess(f, d, DEXEC)) {
-		ou->err = Eaccess;
-		goto out;
-	}
-	accessdir(p, d, FREAD, f->uid);
-	if(strcmp(in->name, ".") == 0)
-		goto setdot;
-	if(strcmp(in->name, "..") == 0) {
-		if(f->wpath == 0)
-			goto setdot;
-		putbuf(p);
-		p = 0;
-		addr = f->wpath->addr;
-		slot = f->wpath->slot;
-		p1 = getbuf(f->fs->dev, addr, Brd);
-		d1 = getdir(p1, slot);
-		if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
-			if(p1)
-				putbuf(p1);
-			ou->err = Ephase;
-			goto out;
-		}
-		lock(&wpathlock);
-		f->wpath->refs--;
-		f->wpath = f->wpath->up;
-		unlock(&wpathlock);
-		goto found;
-	}
-	for(addr=0;; addr++) {
-		if(p == 0) {
-			p = getbuf(f->fs->dev, f->addr, Brd);
-			d = getdir(p, f->slot);
-			if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-				ou->err = Ealloc;
-				goto out;
-			}
-		}
-		qpath = d->qid.path;
-		p1 = dnodebuf1(p, d, addr, 0, f->uid);
-		p = 0;
-		if(!p1 || checktag(p1, Tdir, qpath) ) {
-			if(p1)
-				putbuf(p1);
-			ou->err = Eentry;
-			goto out;
-		}
-		mask = DALLOC;
-		if(f->fs->dev->type == Devro)
-			mask |= DTMP;
-		for(slot=0; slot<DIRPERBUF; slot++) {
-			d1 = getdir(p1, slot);
-			if((d1->mode & mask) != DALLOC)
-				continue;
-			if(strncmp(in->name, d1->name, sizeof(in->name)) != 0)
-				continue;
-			/*
-			 * update walk path
-			 */
-			w = newwp();
-			if(!w) {
-				ou->err = Ewalk;
-				putbuf(p1);
-				goto out;
-			}
-			w->addr = f->addr;
-			w->slot = f->slot;
-			w->up = f->wpath;
-			f->wpath = w;
-			slot += DIRPERBUF*addr;
-			goto found;
-		}
-		putbuf(p1);
-	}
-
-found:
-	f->addr = p1->addr;
-	mkqid(&f->qid, d1, 1);
-	putbuf(p1);
-	f->slot = slot;
-
-setdot:
-	mkqid9p1(&ou->qid, &f->qid);
-	f->open = 0;
-
-out:
-	if(p)
-		putbuf(p);
-	if(f)
-		qunlock(f);
-}
-
-static void
-f_open(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Iobuf *p;
-	Dentry *d;
-	File *f;
-	Tlock *t;
-	Qid qid;
-	int ro, fmod;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_open %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-		fprint(2, "\tmode = %o\n", in->mode);
-	}
-
-	p = 0;
-	f = filep(cp, in->fid, 0);
-	if(!f) {
-		ou->err = Efid;
-		goto out;
-	}
-
-	/*
-	 * if remove on close, check access here
-	 */
-	ro = f->fs->dev->type == Devro;
-	if(in->mode & ORCLOSE) {
-		if(ro) {
-			ou->err = Eronly;
-			goto out;
-		}
-		/*
-		 * check on parent directory of file to be deleted
-		 */
-		if(f->wpath == 0 || f->wpath->addr == f->addr) {
-			ou->err = Ephase;
-			goto out;
-		}
-		p = getbuf(f->fs->dev, f->wpath->addr, Brd);
-		d = getdir(p, f->wpath->slot);
-		if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-			ou->err = Ephase;
-			goto out;
-		}
-		if(iaccess(f, d, DWRITE)) {
-			ou->err = Eaccess;
-			goto out;
-		}
-		putbuf(p);
-	}
-	p = getbuf(f->fs->dev, f->addr, Brd);
-	d = getdir(p, f->slot);
-	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-		ou->err = Ealloc;
-		goto out;
-	}
-	if(ou->err = mkqidcmp(&f->qid, d))
-		goto out;
-	mkqid(&qid, d, 1);
-	switch(in->mode & 7) {
-
-	case OREAD:
-		if(iaccess(f, d, DREAD))
-			goto badaccess;
-		fmod = FREAD;
-		break;
-
-	case OWRITE:
-		if((d->mode & DDIR) || iaccess(f, d, DWRITE))
-			goto badaccess;
-		if(ro) {
-			ou->err = Eronly;
-			goto out;
-		}
-		fmod = FWRITE;
-		break;
-
-	case ORDWR:
-		if((d->mode & DDIR) || iaccess(f, d, DREAD) || iaccess(f, d, DWRITE))
-			goto badaccess;
-		if(ro) {
-			ou->err = Eronly;
-			goto out;
-		}
-		fmod = FREAD+FWRITE;
-		break;
-
-	case OEXEC:
-		if((d->mode & DDIR) || iaccess(f, d, DEXEC))
-			goto badaccess;
-		fmod = FREAD;
-		break;
-
-	default:
-		ou->err = Emode;
-		goto out;
-	}
-	if(in->mode & OTRUNC) {
-		if((d->mode & DDIR) || iaccess(f, d, DWRITE))
-			goto badaccess;
-		if(ro) {
-			ou->err = Eronly;
-			goto out;
-		}
-	}
-	t = 0;
-	if(d->mode & DLOCK) {
-		t = tlocked(p, d);
-		if(t == nil) {
-			ou->err = Elocked;
-			goto out;
-		}
-	}
-	if(in->mode & ORCLOSE)
-		fmod |= FREMOV;
-	f->open = fmod;
-	if(in->mode & OTRUNC)
-		if(!(d->mode & DAPND)) {
-			dtrunc(p, d, f->uid);
-			qid.vers = d->qid.version;
-		}
-	f->tlock = t;
-	if(t)
-		t->file = f;
-	f->lastra = 1;
-	mkqid9p1(&ou->qid, &qid);
-	goto out;
-
-badaccess:
-	ou->err = Eaccess;
-	f->open = 0;
-
-out:
-	if(p)
-		putbuf(p);
-	if(f)
-		qunlock(f);
-	ou->fid = in->fid;
-}
-
-static void
-f_create(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Iobuf *p, *p1;
-	Dentry *d, *d1;
-	File *f;
-	int slot, slot1, fmod;
-	Off addr, addr1, path;
-	Qid qid;
-	Tlock *t;
-	Wpath *w;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_create %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-		fprint(2, "\tname = %s\n", in->name);
-		fprint(2, "\tperm = %lx+%lo\n", (in->perm>>28)&0xf,
-				in->perm&0777);
-		fprint(2, "\tmode = %o\n", in->mode);
-	}
-
-	p = 0;
-	f = filep(cp, in->fid, 0);
-	if(!f) {
-		ou->err = Efid;
-		goto out;
-	}
-	if(f->fs->dev->type == Devro) {
-		ou->err = Eronly;
-		goto out;
-	}
-
-	p = getbuf(f->fs->dev, f->addr, Brd);
-	d = getdir(p, f->slot);
-	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-		ou->err = Ealloc;
-		goto out;
-	}
-	if(ou->err = mkqidcmp(&f->qid, d))
-		goto out;
-	if(!(d->mode & DDIR)) {
-		ou->err = Edir2;
-		goto out;
-	}
-	if(iaccess(f, d, DWRITE)) {
-		ou->err = Eaccess;
-		goto out;
-	}
-	accessdir(p, d, FREAD, f->uid);
-	if(ou->err = checkname(in->name))
-		goto out;
-	addr1 = 0;
-	slot1 = 0;	/* set */
-	for(addr=0;; addr++) {
-		p1 = dnodebuf(p, d, addr, 0, f->uid);
-		if(!p1) {
-			if(addr1)
-				break;
-			p1 = dnodebuf(p, d, addr, Tdir, f->uid);
-		}
-		if(p1 == 0) {
-			ou->err = Efull;
-			goto out;
-		}
-		if(checktag(p1, Tdir, d->qid.path)) {
-			putbuf(p1);
-			goto phase;
-		}
-		for(slot=0; slot<DIRPERBUF; slot++) {
-			d1 = getdir(p1, slot);
-			if(!(d1->mode & DALLOC)) {
-				if(!addr1) {
-					addr1 = p1->addr;
-					slot1 = slot + addr*DIRPERBUF;
-				}
-				continue;
-			}
-			if(!strncmp(in->name, d1->name, sizeof(in->name))) {
-				putbuf(p1);
-				ou->err = Eexist;
-				goto out;
-			}
-		}
-		putbuf(p1);
-	}
-	switch(in->mode & 7) {
-	case OEXEC:
-	case OREAD:		/* seems only useful to make directories */
-		fmod = FREAD;
-		break;
-
-	case OWRITE:
-		fmod = FWRITE;
-		break;
-
-	case ORDWR:
-		fmod = FREAD+FWRITE;
-		break;
-
-	default:
-		ou->err = Emode;
-		goto out;
-	}
-	if(in->perm & PDIR)
-		if((in->mode & OTRUNC) || (in->perm & PAPND) || (fmod & FWRITE))
-			goto badaccess;
-	/*
-	 * do it
-	 */
-	path = qidpathgen(f->fs->dev);
-	p1 = getbuf(f->fs->dev, addr1, Brd|Bimm|Bmod);
-	d1 = getdir(p1, slot1);
-	if(!d1 || checktag(p1, Tdir, d->qid.path)) {
-		if(p1)
-			putbuf(p1);
-		goto phase;
-	}
-	if(d1->mode & DALLOC) {
-		putbuf(p1);
-		goto phase;
-	}
-
-	strncpy(d1->name, in->name, sizeof(in->name));
-	if(cp == cons.chan) {
-		d1->uid = cons.uid;
-		d1->gid = cons.gid;
-	} else {
-		d1->uid = f->uid;
-		d1->gid = d->gid;
-		in->perm &= d->mode | ~0666;
-		if(in->perm & PDIR)
-			in->perm &= d->mode | ~0777;
-	}
-	d1->qid.path = path;
-	d1->qid.version = 0;
-	d1->mode = DALLOC | (in->perm & 0777);
-	if(in->perm & PDIR) {
-		d1->mode |= DDIR;
-		d1->qid.path |= QPDIR;
-	}
-	if(in->perm & PAPND)
-		d1->mode |= DAPND;
-	t = 0;
-	if(in->perm & PLOCK) {
-		d1->mode |= DLOCK;
-		t = tlocked(p1, d1);
-		/* if nil, out of tlock structures */
-	}
-	accessdir(p1, d1, FWRITE, f->uid);
-	mkqid(&qid, d1, 0);
-	putbuf(p1);
-	accessdir(p, d, FWRITE, f->uid);
-
-	/*
-	 * do a walk to new directory entry
-	 */
-	w = newwp();
-	if(!w) {
-		ou->err = Ewalk;
-		goto out;
-	}
-	w->addr = f->addr;
-	w->slot = f->slot;
-	w->up = f->wpath;
-	f->wpath = w;
-	f->qid = qid;
-	f->tlock = t;
-	if(t)
-		t->file = f;
-	f->lastra = 1;
-	if(in->mode & ORCLOSE)
-		fmod |= FREMOV;
-	f->open = fmod;
-	f->addr = addr1;
-	f->slot = slot1;
-	mkqid9p1(&ou->qid, &qid);
-	goto out;
-
-badaccess:
-	ou->err = Eaccess;
-	goto out;
-
-phase:
-	ou->err = Ephase;
-
-out:
-	if(p)
-		putbuf(p);
-	if(f)
-		qunlock(f);
-	ou->fid = in->fid;
-}
-
-static void
-f_read(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Iobuf *p, *p1;
-	File *f;
-	Dentry *d, *d1;
-	Tlock *t;
-	Off addr, offset;
-	Timet tim;
-	int nread, count, mask, n, o, slot;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_read %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-		fprint(2, "\toffset = %lld\n", (Wideoff)in->offset);
-		fprint(2, "\tcount = %ld\n", in->count);
-	}
-
-	p = 0;
-	count = in->count;
-	offset = in->offset;
-	nread = 0;
-	f = filep(cp, in->fid, 0);
-	if(!f) {
-		ou->err = Efid;
-		goto out;
-	}
-	if(!(f->open & FREAD)) {
-		ou->err = Eopen;
-		goto out;
-	}
-	if(count < 0 || count > MAXDAT) {
-		ou->err = Ecount;
-		goto out;
-	}
-	if(offset < 0) {
-		ou->err = Eoffset;
-		goto out;
-	}
-	p = getbuf(f->fs->dev, f->addr, Brd);
-	d = getdir(p, f->slot);
-	if(!d || !(d->mode & DALLOC)) {
-		ou->err = Ealloc;
-		goto out;
-	}
-	if(ou->err = mkqidcmp(&f->qid, d))
-		goto out;
-	if(t = f->tlock) {
-		tim = toytime();
-		if(t->time < tim || t->file != f) {
-			ou->err = Ebroken;
-			goto out;
-		}
-		/* renew the lock */
-		t->time = tim + TLOCK;
-	}
-	accessdir(p, d, FREAD, f->uid);
-	if(d->mode & DDIR) {
-		addr = 0;
-		goto dread;
-	}
-
-	/* XXXX terrible hack to get at raw data XXXX */
-	if(rawreadok && strncmp(d->name, "--raw--", 7) == 0) {
-		Device *dev;
-		Devsize boff, bsize;
-
-		dev = p->dev;
-		putbuf(p);
-		p = 0;
-
-		boff = number(d->name + 7, 0, 10) * 100000;
-		if(boff < 0)
-			boff = 0;
-		if(boff > devsize(dev))
-			boff = devsize(dev);
-		bsize = devsize(dev) - boff;
-
-		if(offset+count >= 100000*RBUFSIZE)
-			count = 100000*RBUFSIZE - offset;
-
-		if((offset+count)/RBUFSIZE >= bsize)
-			/* will not overflow */
-			count = bsize*RBUFSIZE - offset;
-
-		while(count > 0) {
-			addr = offset / RBUFSIZE;
-			addr += boff;
-			o = offset % RBUFSIZE;
-			n = RBUFSIZE - o;
-			if(n > count)
-				n = count;
-
-			p1 = getbuf(dev, addr, Brd);
-			if(p1) {
-				memmove(ou->data+nread, p1->iobuf+o, n);
-				putbuf(p1);
-			} else
-				memset(ou->data+nread, 0, n);
-			count -= n;
-			nread += n;
-			offset += n;
-		}
-		goto out;
-	}
-	if(offset >= d->size)
-		count = 0;
-	else if(offset+count > d->size)
-		count = d->size - offset;
-	while(count > 0) {
-		if(p == 0) {
-			p = getbuf(f->fs->dev, f->addr, Brd);
-			d = getdir(p, f->slot);
-			if(!d || !(d->mode & DALLOC)) {
-				ou->err = Ealloc;
-				goto out;
-			}
-		}
-		addr = offset / BUFSIZE;
-		f->lastra = dbufread(p, d, addr, f->lastra, f->uid);
-		o = offset % BUFSIZE;
-		n = BUFSIZE - o;
-		if(n > count)
-			n = count;
-		p1 = dnodebuf1(p, d, addr, 0, f->uid);
-		p = 0;
-		if(p1) {
-			if(checktag(p1, Tfile, QPNONE)) {
-				ou->err = Ephase;
-				putbuf(p1);
-				goto out;
-			}
-			memmove(ou->data+nread, p1->iobuf+o, n);
-			putbuf(p1);
-		} else
-			memset(ou->data+nread, 0, n);
-		count -= n;
-		nread += n;
-		offset += n;
-	}
-	goto out;
-
-dread:
-	for (;;) {
-		if(p == 0) {
-			p = getbuf(f->fs->dev, f->addr, Brd);
-			d = getdir(p, f->slot);
-			if(!d || !(d->mode & DALLOC)) {
-				ou->err = Ealloc;
-				goto out;
-			}
-		}
-		p1 = dnodebuf1(p, d, addr, 0, f->uid);
-		p = 0;
-		if(!p1)
-			goto out;
-		if(checktag(p1, Tdir, QPNONE)) {
-			ou->err = Ephase;
-			putbuf(p1);
-			goto out;
-		}
-		n = DIRREC;
-		mask = DALLOC;
-		if(f->fs->dev->type == Devro)
-			mask |= DTMP;
-		for(slot=0; slot<DIRPERBUF; slot++) {
-			d1 = getdir(p1, slot);
-			if((d1->mode & mask) != DALLOC)
-				continue;
-			if(offset >= n) {
-				offset -= n;
-				continue;
-			}
-			if(count < n) {
-				putbuf(p1);
-				goto out;
-			}
-			if(convD2M9p1(d1, ou->data+nread) != n)
-				fprint(2, "9p1: dirread convD2M1990\n");
-			nread += n;
-			count -= n;
-		}
-		putbuf(p1);
-		addr++;
-	}
-out:
-	count = in->count - nread;
-	if(count > 0)
-		memset(ou->data+nread, 0, count);
-	if(p)
-		putbuf(p);
-	if(f)
-		qunlock(f);
-	ou->fid = in->fid;
-	ou->count = nread;
-	if(CHAT(cp))
-		fprint(2, "\tnread = %d\n", nread);
-}
-
-static void
-f_write(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Iobuf *p, *p1;
-	Dentry *d;
-	File *f;
-	Tlock *t;
-	Off offset, addr, qpath;
-	Timet tim;
-	int count, nwrite, o, n;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_write %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-		fprint(2, "\toffset = %lld\n", (Wideoff)in->offset);
-		fprint(2, "\tcount = %ld\n", in->count);
-	}
-
-	offset = in->offset;
-	count = in->count;
-	nwrite = 0;
-	p = 0;
-	f = filep(cp, in->fid, 0);
-	if(!f) {
-		ou->err = Efid;
-		goto out;
-	}
-	if(!(f->open & FWRITE)) {
-		ou->err = Eopen;
-		goto out;
-	}
-	if(f->fs->dev->type == Devro) {
-		ou->err = Eronly;
-		goto out;
-	}
-	if(count < 0 || count > MAXDAT) {
-		ou->err = Ecount;
-		goto out;
-	}
-	if(offset < 0) {
-		ou->err = Eoffset;
-		goto out;
-	}
-	p = getbuf(f->fs->dev, f->addr, Brd|Bmod);
-	d = getdir(p, f->slot);
-	if(!d || !(d->mode & DALLOC)) {
-		ou->err = Ealloc;
-		goto out;
-	}
-	if(ou->err = mkqidcmp(&f->qid, d))
-		goto out;
-	if(t = f->tlock) {
-		tim = toytime();
-		if(t->time < tim || t->file != f) {
-			ou->err = Ebroken;
-			goto out;
-		}
-		/* renew the lock */
-		t->time = tim + TLOCK;
-	}
-	accessdir(p, d, FWRITE, f->uid);
-	if(d->mode & DAPND)
-		offset = d->size;
-	if(offset+count > d->size)
-		d->size = offset+count;
-	while(count > 0) {
-		if(p == 0) {
-			p = getbuf(f->fs->dev, f->addr, Brd|Bmod);
-			d = getdir(p, f->slot);
-			if(!d || !(d->mode & DALLOC)) {
-				ou->err = Ealloc;
-				goto out;
-			}
-		}
-		addr = offset / BUFSIZE;
-		o = offset % BUFSIZE;
-		n = BUFSIZE - o;
-		if(n > count)
-			n = count;
-		qpath = d->qid.path;
-		p1 = dnodebuf1(p, d, addr, Tfile, f->uid);
-		p = 0;
-		if(p1 == 0) {
-			ou->err = Efull;
-			goto out;
-		}
-		if(checktag(p1, Tfile, qpath)) {
-			putbuf(p1);
-			ou->err = Ephase;
-			goto out;
-		}
-		memmove(p1->iobuf+o, in->data+nwrite, n);
-		p1->flags |= Bmod;
-		putbuf(p1);
-		count -= n;
-		nwrite += n;
-		offset += n;
-	}
-	if(CHAT(cp))
-		fprint(2, "\tnwrite = %d\n", nwrite);
-
-out:
-	if(p)
-		putbuf(p);
-	if(f)
-		qunlock(f);
-	ou->fid = in->fid;
-	ou->count = nwrite;
-}
-
-int
-doremove(File *f)
-{
-	Iobuf *p, *p1;
-	Dentry *d, *d1;
-	Off addr;
-	int slot, err;
-
-	p = 0;
-	p1 = 0;
-	if(f->fs->dev->type == Devro) {
-		err = Eronly;
-		goto out;
-	}
-	/*
-	 * check on parent directory of file to be deleted
-	 */
-	if(f->wpath == 0 || f->wpath->addr == f->addr) {
-		err = Ephase;
-		goto out;
-	}
-	p1 = getbuf(f->fs->dev, f->wpath->addr, Brd);
-	d1 = getdir(p1, f->wpath->slot);
-	if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
-		err = Ephase;
-		goto out;
-	}
-	if(iaccess(f, d1, DWRITE)) {
-		err = Eaccess;
-		goto out;
-	}
-	accessdir(p1, d1, FWRITE, f->uid);
-	putbuf(p1);
-	p1 = 0;
-
-	/*
-	 * check on file to be deleted
-	 */
-	p = getbuf(f->fs->dev, f->addr, Brd);
-	d = getdir(p, f->slot);
-	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-		err = Ealloc;
-		goto out;
-	}
-	if(err = mkqidcmp(&f->qid, d))
-		goto out;
-
-	/*
-	 * if deleting a directory, make sure it is empty
-	 */
-	if((d->mode & DDIR))
-	for(addr=0;; addr++) {
-		p1 = dnodebuf(p, d, addr, 0, f->uid);
-		if(!p1)
-			break;
-		if(checktag(p1, Tdir, d->qid.path)) {
-			err = Ephase;
-			goto out;
-		}
-		for(slot=0; slot<DIRPERBUF; slot++) {
-			d1 = getdir(p1, slot);
-			if(!(d1->mode & DALLOC))
-				continue;
-			err = Eempty;
-			goto out;
-		}
-		putbuf(p1);
-	}
-
-	/*
-	 * do it
-	 */
-	dtrunc(p, d, f->uid);
-	memset(d, 0, sizeof(Dentry));
-	settag(p, Tdir, QPNONE);
-
-out:
-	if(p1)
-		putbuf(p1);
-	if(p)
-		putbuf(p);
-	return err;
-}
-
-static int
-doclunk(File* f, int remove)
-{
-	Tlock *t;
-	int err;
-
-	err = 0;
-	if(t = f->tlock) {
-		if(t->file == f)
-			t->time = 0;	/* free the lock */
-		f->tlock = 0;
-	}
-	if(remove)
-		err = doremove(f);
-	f->open = 0;
-	freewp(f->wpath);
-	freefp(f);
-
-	return err;
-}
-
-static void
-f_clunk(Chan *cp, Fcall *in, Fcall *ou)
-{
-	File *f;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_clunk %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-	}
-
-	f = filep(cp, in->fid, 0);
-	if(!f)
-		ou->err = Efid;
-	else {
-		doclunk(f, f->open & FREMOV);
-		qunlock(f);
-	}
-	ou->fid = in->fid;
-}
-
-static void
-f_remove(Chan *cp, Fcall *in, Fcall *ou)
-{
-	File *f;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_remove %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-	}
-
-	f = filep(cp, in->fid, 0);
-	if(!f)
-		ou->err = Efid;
-	else {
-		ou->err = doclunk(f, 1);
-		qunlock(f);
-	}
-	ou->fid = in->fid;
-}
-
-static void
-f_stat(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Iobuf *p;
-	Dentry *d;
-	File *f;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_stat %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-	}
-
-	p = 0;
-	memset(ou->stat, 0, sizeof(ou->stat));
-	f = filep(cp, in->fid, 0);
-	if(!f) {
-		ou->err = Efid;
-		goto out;
-	}
-	p = getbuf(f->fs->dev, f->addr, Brd);
-	d = getdir(p, f->slot);
-	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-		ou->err = Ealloc;
-		goto out;
-	}
-	if(ou->err = mkqidcmp(&f->qid, d))
-		goto out;
-	if(d->qid.path == QPROOT)	/* stat of root gives time */
-		d->atime = time(nil);
-	if(convD2M9p1(d, ou->stat) != DIRREC)
-		fprint(2, "9p1: stat convD2M\n");
-
-out:
-	if(p)
-		putbuf(p);
-	if(f)
-		qunlock(f);
-	ou->fid = in->fid;
-}
-
-static void
-f_wstat(Chan *cp, Fcall *in, Fcall *ou)
-{
-	Iobuf *p, *p1;
-	Dentry *d, *d1, xd;
-	File *f;
-	int slot;
-	Off addr;
-
-	if(CHAT(cp)) {
-		fprint(2, "c_wstat %d\n", cp->chan);
-		fprint(2, "\tfid = %d\n", in->fid);
-	}
-
-	p = 0;
-	p1 = 0;
-	d1 = 0;
-	f = filep(cp, in->fid, 0);
-	if(!f) {
-		ou->err = Efid;
-		goto out;
-	}
-	if(f->fs->dev->type == Devro) {
-		ou->err = Eronly;
-		goto out;
-	}
-
-	/*
-	 * first get parent
-	 */
-	if(f->wpath) {
-		p1 = getbuf(f->fs->dev, f->wpath->addr, Brd);
-		d1 = getdir(p1, f->wpath->slot);
-		if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
-			ou->err = Ephase;
-			goto out;
-		}
-	}
-
-	p = getbuf(f->fs->dev, f->addr, Brd);
-	d = getdir(p, f->slot);
-	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-		ou->err = Ealloc;
-		goto out;
-	}
-	if(ou->err = mkqidcmp(&f->qid, d))
-		goto out;
-
-	convM2D9p1(in->stat, &xd);
-	if(CHAT(cp)) {
-		fprint(2, "\td.name = %s\n", xd.name);
-		fprint(2, "\td.uid  = %d\n", xd.uid);
-		fprint(2, "\td.gid  = %d\n", xd.gid);
-		fprint(2, "\td.mode = %o\n", xd.mode);
-	}
-
-	/*
-	 * if user none,
-	 * cant do anything
-	 */
-	if(f->uid == 0) {
-		ou->err = Eaccess;
-		goto out;
-	}
-
-	/*
-	 * if chown,
-	 * must be god
-	 */
-	if(xd.uid != d->uid && !isallowed(f)) {
-		ou->err = Ewstatu;
-		goto out;
-	}
-
-	/*
-	 * if chgroup,
-	 * must be either
-	 *	a) owner and in new group
-	 *	b) leader of both groups
-	 */
-	if (xd.gid != d->gid && !isallowed(f) && 
-	     (d->uid != f->uid || !ingroup(f->uid, xd.gid)) &&
-	     (!leadgroup(f->uid, xd.gid) || !leadgroup(f->uid, d->gid))) {
-		ou->err = Ewstatg;
-		goto out;
-	}
-
-	/*
-	 * if rename,
-	 * must have write permission in parent
-	 */
-	if (strncmp(d->name, xd.name, sizeof(d->name)) != 0) {
-		if(ou->err = checkname(xd.name))
-			goto out;
-
-		/* rename root? */
-		if(!d1){
-			ou->err = Ename;
-			goto out;
-		}
-
-		/*
-		 * drop entry to prevent lock, then
-		 * check that destination name is unique,
-		 */
-		putbuf(p);
-		for(addr=0;; addr++) {
-			p = dnodebuf(p1, d1, addr, 0, f->uid);
-			if(!p)
-				break;
-			if(checktag(p, Tdir, d1->qid.path)) {
-				putbuf(p);
-				continue;
-			}
-			for(slot=0; slot<DIRPERBUF; slot++) {
-				d = getdir(p, slot);
-				if(!(d->mode & DALLOC))
-					continue;
-				if(!strncmp(xd.name, d->name, sizeof(xd.name))) {
-					ou->err = Eexist;
-					goto out;
-				}
-			}
-			putbuf(p);
-		}
-
-		/*
-		 * reacquire entry
-		 */
-		p = getbuf(f->fs->dev, f->addr, Brd);
-		d = getdir(p, f->slot);
-		if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
-			ou->err = Ephase;
-			goto out;
-		}
-
-		if(iaccess(f, d1, DWRITE)) {
-			ou->err = Eaccess;
-			goto out;
-		}
-	}
-
-	/*
-	 * if mode/time, either
-	 *	a) owner
-	 *	b) leader of either group
-	 */
-	if (d->mtime != xd.mtime ||
-	    ((d->mode^xd.mode) & (DAPND|DLOCK|0777)))
-		if (d->uid != f->uid && !isallowed(f) &&
-		    !leadgroup(f->uid, xd.gid) &&
-		    !leadgroup(f->uid, d->gid)) {
-			ou->err = Ewstatu;
-			goto out;
-		}
-	d->mtime = xd.mtime;
-	d->uid = xd.uid;
-	d->gid = xd.gid;
-	d->mode = (xd.mode & (DAPND|DLOCK|0777)) | (d->mode & (DALLOC|DDIR));
-
-	strncpy(d->name, xd.name, sizeof(d->name));
-	accessdir(p, d, FREAD, f->uid);
-
-out:
-	if(p)
-		putbuf(p);
-	if(p1)
-		putbuf(p1);
-	if(f)
-		qunlock(f);
-	ou->fid = in->fid;
-}
-
-static void
-f_clwalk(Chan *cp, Fcall *in, Fcall *ou)
-{
-	int er, fid;
-
-	if(CHAT(cp))
-		fprint(2, "c_clwalk macro\n");
-
-	f_clone(cp, in, ou);		/* sets tag, fid */
-	if(ou->err)
-		return;
-	fid = in->fid;
-	in->fid = in->newfid;
-	f_walk(cp, in, ou);		/* sets tag, fid, qid */
-	er = ou->err;
-	if(er == Eentry) {
-		/*
-		 * if error is "no entry"
-		 * return non error and fid
-		 */
-		ou->err = 0;
-		f_clunk(cp, in, ou);	/* sets tag, fid */
-		ou->err = 0;
-		ou->fid = fid;
-		if(CHAT(cp))
-			fprint(2, "\terror: %s\n", errstr9p[er]);
-	} else if(er) {
-		/*
-		 * if any other error
-		 * return an error
-		 */
-		ou->err = 0;
-		f_clunk(cp, in, ou);	/* sets tag, fid */
-		ou->err = er;
-	}
-	/*
-	 * non error
-	 * return newfid
-	 */
-}
-
-void (*call9p1[MAXSYSCALL])(Chan*, Fcall*, Fcall*) =
-{
-	[Tnop]		f_nop,
-	[Tosession]	f_session,
-	[Tsession]	f_session,
-	[Tflush]	f_flush,
-	[Toattach]	f_attach,
-	[Tattach]	f_attach,
-	[Tclone]	f_clone,
-	[Twalk]		f_walk,
-	[Topen]		f_open,
-	[Tcreate]	f_create,
-	[Tread]		f_read,
-	[Twrite]	f_write,
-	[Tclunk]	f_clunk,
-	[Tremove]	f_remove,
-	[Tstat]		f_stat,
-	[Twstat]	f_wstat,
-	[Tclwalk]	f_clwalk,
-};
-
-int
-error9p1(Chan* cp, Msgbuf* mb)
-{
-	Msgbuf *mb1;
-
-	fprint(2, "type=%d count=%d\n", mb->data[0], mb->count);
-	hexdump(mb->data, 12);
-
-	mb1 = mballoc(3, cp, Mbreply4);
-	mb1->data[0] = Rnop;	/* your nop was ok */
-	mb1->data[1] = ~0;
-	mb1->data[2] = ~0;
-	mb1->count = 3;
-	mb1->param = mb->param;
-	fs_send(cp->reply, mb1);
-
-	return 1;
-}
-
-int
-serve9p1(Msgbuf* mb)
-{
-	int t, n;
-	Chan *cp;
-	Msgbuf *mb1;
-	Fcall fi, fo;
-
-	assert(mb != nil);
-	cp = mb->chan;
-	assert(mb->data != nil);
-	if(convM2S9p1(mb->data, &fi, mb->count) == 0){
-		assert(cp != nil);
-		if(cp->protocol == nil)
-			return 0;
-		fprint(2, "9p1: bad M2S conversion\n");
-		return error9p1(cp, mb);
-	}
-
-	t = fi.type;
-	if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) {
-		fprint(2, "9p1: bad message type\n");
-		return error9p1(cp, mb);
-	}
-
-	/*
-	 * allocate reply message
-	 */
-	if(t == Tread) {
-		mb1 = mballoc(MAXMSG+MAXDAT, cp, Mbreply2);
-		fo.data = (char*)(mb1->data + 8);
-	} else
-		mb1 = mballoc(MAXMSG, cp, Mbreply3);
-
-	/*
-	 * call the file system
-	 */
-	assert(cp != nil);
-	fo.err = 0;
-
-	(*call9p1[t])(cp, &fi, &fo);
-
-	fo.type = t+1;
-	fo.tag = fi.tag;
-
-	if(fo.err) {
-		if(cons.flags&errorflag)
-			fprint(2, "\ttype %d: error: %s\n", t, errstr9p[fo.err]);
-		if(CHAT(cp))
-			fprint(2, "\terror: %s\n", errstr9p[fo.err]);
-		fo.type = Rerror;
-		strncpy(fo.ename, errstr9p[fo.err], sizeof(fo.ename));
-	}
-
-	n = convS2M9p1(&fo, mb1->data);
-	if(n == 0) {
-		fprint(2, "9p1: bad S2M conversion\n");
-		mbfree(mb1);
-		return error9p1(cp, mb);
-	}
-	mb1->count = n;
-	mb1->param = mb->param;
-	fs_send(cp->reply, mb1);
-
-	return 1;
-}
--- a/sys/src/cmd/cwfs/9p1.h
+++ /dev/null
@@ -1,116 +1,0 @@
-#include <authsrv.h>
-
-enum {
-	DIRREC	= 116,		/* size of a directory ascii record */
-	ERRREC	= 64,		/* size of a error record */
-};
-
-typedef	struct	Fcall	Fcall;
-
-struct	Fcall
-{
-	char	type;
-	ushort	fid;
-	short	err;
-	short	tag;
-	union
-	{
-		struct
-		{
-			short	uid;		/* T-Userstr [obs.] */
-			short	oldtag;		/* T-nFlush */
-			Qid9p1	qid;		/* R-Attach, R-Clwalk, R-Walk,
-						 * R-Open, R-Create */
-			char	rauth[AUTHENTLEN];	/* R-attach */
-		};
-		struct
-		{
-			char	uname[NAMELEN];	/* T-nAttach */
-			char	aname[NAMELEN];	/* T-nAttach */
-			char	ticket[TICKETLEN];	/* T-attach */
-			char	auth[AUTHENTLEN];	/* T-attach */
-		};
-		struct
-		{
-			char	ename[ERRREC];	/* R-nError */
-			char	chal[CHALLEN];	/* T-session, R-session */
-			char	authid[NAMELEN];	/* R-session */
-			char	authdom[DOMLEN];	/* R-session */
-		};
-		struct
-		{
-			char	name[NAMELEN];	/* T-Walk, T-Clwalk, T-Create, T-Remove */
-			long	perm;		/* T-Create */
-			ushort	newfid;		/* T-Clone, T-Clwalk */
-			char	mode;		/* T-Create, T-Open */
-		};
-		struct
-		{
-			Off	offset;		/* T-Read, T-Write */
-			long	count;		/* T-Read, T-Write, R-Read */
-			char*	data;		/* T-Write, R-Read */
-		};
-		struct
-		{
-			char	stat[DIRREC];	/* T-Wstat, R-Stat */
-		};
-	};
-};
-
-/*
- * P9 protocol message types
- */
-enum
-{
-	Tnop =		50,
-	Rnop,
-	Tosession =	52,
-	Rosession,
-	Terror =	54,	/* illegal */
-	Rerror,
-	Tflush =	56,
-	Rflush,
-	Toattach =	58,
-	Roattach,
-	Tclone =	60,
-	Rclone,
-	Twalk =		62,
-	Rwalk,
-	Topen =		64,
-	Ropen,
-	Tcreate =	66,
-	Rcreate,
-	Tread =		68,
-	Rread,
-	Twrite =	70,
-	Rwrite,
-	Tclunk =	72,
-	Rclunk,
-	Tremove =	74,
-	Rremove,
-	Tstat =		76,
-	Rstat,
-	Twstat =	78,
-	Rwstat,
-	Tclwalk =	80,
-	Rclwalk,
-	Tauth =		82,	/* illegal */
-	Rauth,			/* illegal */
-	Tsession =	84,
-	Rsession,
-	Tattach =	86,
-	Rattach,
-
-	MAXSYSCALL
-};
-
-int	convA2M9p1(Authenticator*, char*, char*);
-void	convM2A9p1(char*, Authenticator*, char*);
-void	convM2T9p1(char*, Ticket*, char*);
-int	convD2M9p1(Dentry*, char*);
-int	convM2D9p1(char*, Dentry*);
-int	convM2S9p1(uchar*, Fcall*, int);
-int	convS2M9p1(Fcall*, uchar*);
-void	fcall9p1(Chan*, Fcall*, Fcall*);
-
-void	(*call9p1[MAXSYSCALL])(Chan*, Fcall*, Fcall*);
--- a/sys/src/cmd/cwfs/9p1lib.c
+++ /dev/null
@@ -1,523 +1,0 @@
-#include "all.h"
-
-/* BUG transition */
-// int client9p = 2;
-// int kernel9p = 2;
-
-#include "9p1.h"
-
-#define	CHAR(x)		*p++ = f->x
-#define	SHORT(x)	{ ulong vvv = f->x; *p++ = vvv; *p++ = vvv>>8; }
-#define	LONGINT(q) {*p++ = (q); *p++ = (q)>>8; *p++ = (q)>>16; *p++ = (q)>>24;}
-#define	LONG(x)		{ ulong vvv = f->x; LONGINT(vvv); }
-#define	VLONG(x) { \
-	uvlong q = f->x; \
-	*p++ = (q)>> 0; *p++ = (q)>> 8; *p++ = (q)>>16; *p++ = (q)>>24; \
-	*p++ = (q)>>32; *p++ = (q)>>40; *p++ = (q)>>48; *p++ = (q)>>56; \
-	}
-
-#define	BYTES(x,n)	memmove(p, f->x, n); p += n
-#define	STRING(x,n)	strncpy((char*)p, f->x, n); p += n
-
-int
-convS2M9p1(Fcall *f, uchar *ap)
-{
-	uchar *p;
-	int t;
-
-	p = ap;
-	CHAR(type);
-	t = f->type;
-	SHORT(tag);
-	switch(t) {
-	default:
-		fprint(2, "convS2M9p1: bad type: %d\n", t);
-		return 0;
-
-	case Tnop:
-	case Tosession:
-		break;
-
-	case Tsession:
-		BYTES(chal, sizeof(f->chal));
-		break;
-
-	case Tflush:
-		SHORT(oldtag);
-		break;
-
-	case Tattach:
-		SHORT(fid);
-		STRING(uname, sizeof(f->uname));
-		STRING(aname, sizeof(f->aname));
-		BYTES(ticket, sizeof(f->ticket));
-		BYTES(auth, sizeof(f->auth));
-		break;
-
-	case Toattach:
-		SHORT(fid);
-		STRING(uname, sizeof(f->uname));
-		STRING(aname, sizeof(f->aname));
-		BYTES(ticket, NAMELEN);
-		break;
-
-	case Tclone:
-		SHORT(fid);
-		SHORT(newfid);
-		break;
-
-	case Twalk:
-		SHORT(fid);
-		STRING(name, sizeof(f->name));
-		break;
-
-	case Tclwalk:
-		SHORT(fid);
-		SHORT(newfid);
-		STRING(name, sizeof(f->name));
-		break;
-
-	case Topen:
-		SHORT(fid);
-		CHAR(mode);
-		break;
-
-	case Tcreate:
-		SHORT(fid);
-		STRING(name, sizeof(f->name));
-		LONG(perm);
-		CHAR(mode);
-		break;
-
-	case Tread:
-		SHORT(fid);
-		VLONG(offset);
-		SHORT(count);
-		break;
-
-	case Twrite:
-		SHORT(fid);
-		VLONG(offset);
-		SHORT(count);
-		p++;
-		if((uchar*)p == (uchar*)f->data) {
-			p += f->count;
-			break;
-		}
-		BYTES(data, f->count);
-		break;
-
-	case Tclunk:
-	case Tremove:
-	case Tstat:
-		SHORT(fid);
-		break;
-
-	case Twstat:
-		SHORT(fid);
-		BYTES(stat, sizeof(f->stat));
-		break;
-/*
- */
-	case Rnop:
-	case Rosession:
-	case Rflush:
-		break;
-
-	case Rsession:
-		BYTES(chal, sizeof(f->chal));
-		BYTES(authid, sizeof(f->authid));
-		BYTES(authdom, sizeof(f->authdom));
-		break;
-
-	case Rerror:
-		STRING(ename, sizeof(f->ename));
-		break;
-
-	case Rclone:
-	case Rclunk:
-	case Rremove:
-	case Rwstat:
-		SHORT(fid);
-		break;
-
-	case Rwalk:
-	case Ropen:
-	case Rcreate:
-	case Rclwalk:
-		SHORT(fid);
-		LONG(qid.path);
-		LONG(qid.version);
-		break;
-
-	case Rattach:
-		SHORT(fid);
-		LONG(qid.path);
-		LONG(qid.version);
-		BYTES(rauth, sizeof(f->rauth));
-		break;
-
-	case Roattach:
-		SHORT(fid);
-		LONG(qid.path);
-		LONG(qid.version);
-		break;
-
-	case Rread:
-		SHORT(fid);
-		SHORT(count);
-		p++;
-		if((uchar*)p == (uchar*)f->data) {
-			p += f->count;
-			break;
-		}
-		BYTES(data, f->count);
-		break;
-
-	case Rwrite:
-		SHORT(fid);
-		SHORT(count);
-		break;
-
-	case Rstat:
-		SHORT(fid);
-		BYTES(stat, sizeof(f->stat));
-		break;
-	}
-	return p - (uchar*)ap;
-}
-
-/*
- * buggery to give false qid for
- * the top 2 levels of the dump fs
- */
-static ulong
-fakeqid9p1(Dentry *f)
-{
-	ulong q;
-	int c;
-
-	q = f->qid.path;
-	if(q == (QPROOT|QPDIR)) {
-		c = f->name[0];
-		if(isascii(c) && isdigit(c)) {
-			q = 3|QPDIR;
-			c = (c-'0')*10 + (f->name[1]-'0');
-			if(c >= 1 && c <= 12)
-				q = 4|QPDIR;
-		}
-	}
-	return q;
-}
-
-int
-convD2M9p1(Dentry *f, char *ap)
-{
-	uchar *p;
-	ulong q;
-
-	p = (uchar*)ap;
-	STRING(name, sizeof(f->name));
-
-	memset(p, 0, 2*NAMELEN);
-	uidtostr((char*)p, f->uid, 1);
-	p += NAMELEN;
-
-	uidtostr((char*)p, f->gid, 1);
-	p += NAMELEN;
-
-	q = fakeqid9p1(f);
-	LONGINT(q);
-	LONG(qid.version);
-
-	q = f->mode & 0x0fff;
-	if(f->mode & DDIR)
-		q |= PDIR;
-	if(f->mode & DAPND)
-		q |= PAPND;
-	if(f->mode & DLOCK)
-		q |= PLOCK;
-	LONGINT(q);
-
-	LONG(atime);
-	LONG(mtime);
-	VLONG(size);
-	LONGINT(0);
-	return p - (uchar*)ap;
-}
-
-int
-convA2M9p1(Authenticator *f, char *ap, char *key)
-{
-	int n;
-	uchar *p;
-
-	p = (uchar*)ap;
-	CHAR(num);
-	BYTES(chal, CHALLEN);
-	LONG(id);
-	n = p - (uchar*)ap;
-	if(key)
-		encrypt(key, ap, n);
-	return n;
-}
-
-#undef	CHAR
-#undef	SHORT
-#undef	LONG
-#undef	LONGINT
-#undef	VLONG
-#undef	BYTES
-#undef	STRING
-
-#define	CHAR(x)		f->x = *p++
-#define	SHORT(x)	f->x = (p[0] | (p[1]<<8)); p += 2
-#define	LONG(x)	f->x = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); p += 4
-#define	VLONG(x) { \
-	f->x =	    (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)) | \
-	    (uvlong)(p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24)) << 32; \
-	p += 8; \
-}
-
-#define	BYTES(x,n)	memmove(f->x, p, n); p += n
-#define	STRING(x,n)	memmove(f->x, p, n); p += n
-
-int
-convM2S9p1(uchar *ap, Fcall *f, int n)
-{
-	uchar *p;
-	int t;
-
-	p = ap;
-	CHAR(type);
-	t = f->type;
-	SHORT(tag);
-	switch(t) {
-	default:
-		/*
-		 * only whine if it couldn't be a 9P2000 Tversion.
-		 */
-		if(t != 19 || ap[4] != 100)
-			fprint(2, "convM2S9p1: bad type: %d\n", f->type);
-		return 0;
-
-	case Tnop:
-	case Tosession:
-		break;
-
-	case Tsession:
-		BYTES(chal, sizeof(f->chal));
-		break;
-
-	case Tflush:
-		SHORT(oldtag);
-		break;
-
-	case Tattach:
-		SHORT(fid);
-		BYTES(uname, sizeof(f->uname));
-		BYTES(aname, sizeof(f->aname));
-		BYTES(ticket, sizeof(f->ticket));
-		BYTES(auth, sizeof(f->auth));
-		break;
-
-	case Toattach:
-		SHORT(fid);
-		BYTES(uname, sizeof(f->uname));
-		BYTES(aname, sizeof(f->aname));
-		BYTES(ticket, NAMELEN);
-		break;
-
-	case Tclone:
-		SHORT(fid);
-		SHORT(newfid);
-		break;
-
-	case Twalk:
-		SHORT(fid);
-		BYTES(name, sizeof(f->name));
-		break;
-
-	case Tclwalk:
-		SHORT(fid);
-		SHORT(newfid);
-		BYTES(name, sizeof(f->name));
-		break;
-
-	case Tremove:
-		SHORT(fid);
-		break;
-
-	case Topen:
-		SHORT(fid);
-		CHAR(mode);
-		break;
-
-	case Tcreate:
-		SHORT(fid);
-		BYTES(name, sizeof(f->name));
-		LONG(perm);
-		CHAR(mode);
-		break;
-
-	case Tread:
-		SHORT(fid);
-		VLONG(offset);
-		SHORT(count);
-		break;
-
-	case Twrite:
-		SHORT(fid);
-		VLONG(offset);
-		SHORT(count);
-		p++;
-		f->data = (char*)p; p += f->count;
-		break;
-
-	case Tclunk:
-	case Tstat:
-		SHORT(fid);
-		break;
-
-	case Twstat:
-		SHORT(fid);
-		BYTES(stat, sizeof(f->stat));
-		break;
-
-/*
- */
-	case Rnop:
-	case Rosession:
-		break;
-
-	case Rsession:
-		BYTES(chal, sizeof(f->chal));
-		BYTES(authid, sizeof(f->authid));
-		BYTES(authdom, sizeof(f->authdom));
-		break;
-
-	case Rerror:
-		BYTES(ename, sizeof(f->ename));
-		break;
-
-	case Rflush:
-		break;
-
-	case Rclone:
-	case Rclunk:
-	case Rremove:
-	case Rwstat:
-		SHORT(fid);
-		break;
-
-	case Rwalk:
-	case Rclwalk:
-	case Ropen:
-	case Rcreate:
-		SHORT(fid);
-		LONG(qid.path);
-		LONG(qid.version);
-		break;
-
-	case Rattach:
-		SHORT(fid);
-		LONG(qid.path);
-		LONG(qid.version);
-		BYTES(rauth, sizeof(f->rauth));
-		break;
-
-	case Roattach:
-		SHORT(fid);
-		LONG(qid.path);
-		LONG(qid.version);
-		break;
-
-	case Rread:
-		SHORT(fid);
-		SHORT(count);
-		p++;
-		f->data = (char*)p; p += f->count;
-		break;
-
-	case Rwrite:
-		SHORT(fid);
-		SHORT(count);
-		break;
-
-	case Rstat:
-		SHORT(fid);
-		BYTES(stat, sizeof(f->stat));
-		break;
-	}
-	if((uchar*)ap+n == p)
-		return n;
-	return 0;
-}
-
-int
-convM2D9p1(char *ap, Dentry *f)
-{
-	uchar *p;
-	char str[NAMELEN];
-
-	p = (uchar*)ap;
-	BYTES(name, sizeof(f->name));
-
-	memmove(str, p, NAMELEN);
-	p += NAMELEN;
-	f->uid = strtouid(str);
-
-	memmove(str, p, NAMELEN);
-	p += NAMELEN;
-	f->gid = strtouid(str);
-
-	LONG(qid.path);
-	LONG(qid.version);
-
-	LONG(atime);
-	f->mode = (f->atime & 0x0fff) | DALLOC;
-	if(f->atime & PDIR)
-		f->mode |= DDIR;
-	if(f->atime & PAPND)
-		f->mode |= DAPND;
-	if(f->atime & PLOCK)
-		f->mode |= DLOCK;
-
-	LONG(atime);
-	LONG(mtime);
-	VLONG(size);
-	p += 4;
-	return p - (uchar*)ap;
-}
-
-void
-convM2A9p1(char *ap, Authenticator *f, char *key)
-{
-	uchar *p;
-
-	if(key)
-		decrypt(key, ap, AUTHENTLEN);
-	p = (uchar*)ap;
-	CHAR(num);
-	BYTES(chal, CHALLEN);
-	LONG(id);
-	USED(p);
-}
-
-void
-convM2T9p1(char *ap, Ticket *f, char *key)
-{
-	uchar *p;
-
-	if(key)
-		decrypt(key, ap, TICKETLEN);
-	p = (uchar*)ap;
-	CHAR(num);
-	BYTES(chal, CHALLEN);
-	STRING(cuid, NAMELEN);
-	f->cuid[NAMELEN-1] = 0;
-	STRING(suid, NAMELEN);
-	f->suid[NAMELEN-1] = 0;
-	BYTES(key, DESKEYLEN);
-	USED(p);
-}
--- a/sys/src/cmd/cwfs/9p2.c
+++ b/sys/src/cmd/cwfs/9p2.c
@@ -110,7 +110,44 @@
 	return p-op;
 }
 
-static int
+/*
+ * buggery to give false qid for
+ * the top 2 levels of the dump fs
+ */
+void
+mkqid(Qid* qid, Dentry *d, int buggery)
+{
+	int c;
+
+	if(buggery && d->qid.path == (QPDIR|QPROOT)){
+		c = d->name[0];
+		if(isascii(c) && isdigit(c)){
+			qid->path = 3;
+			qid->vers = d->qid.version;
+			qid->type = QTDIR;
+
+			c = (c-'0')*10 + (d->name[1]-'0');
+			if(c >= 1 && c <= 12)
+				qid->path = 4;
+			return;
+		}
+	}
+
+	mkqid9p2(qid, &d->qid, d->mode);
+}
+
+int
+mkqidcmp(Qid* qid, Dentry *d)
+{
+	Qid tmp;
+
+	mkqid(&tmp, d, 1);
+	if(qid->path == tmp.path && qid->type == tmp.type)
+		return 0;
+	return Eqid;
+}
+
+int
 version(Chan* chan, Fcall* f, Fcall* r)
 {
 	if(chan->protocol != nil || f->msize < 256)
@@ -237,7 +274,7 @@
 	return uid;
 }
 
-static int
+int
 attach(Chan* chan, Fcall* f, Fcall* r)
 {
 	char *aname;
@@ -494,7 +531,7 @@
 	return error;
 }
 
-static int
+int
 walk(Chan* chan, Fcall* f, Fcall* r)
 {
 	int error, nwname;
@@ -599,7 +636,7 @@
 	return error;
 }
 
-static int
+int
 fs_open(Chan* chan, Fcall* f, Fcall* r)
 {
 	Iobuf *p;
@@ -748,7 +785,7 @@
 	return error;
 }
 
-static int
+int
 fs_create(Chan* chan, Fcall* f, Fcall* r)
 {
 	Iobuf *p, *p1;
@@ -946,7 +983,7 @@
 	return error;
 }
 
-static int
+int
 fs_read(Chan* chan, Fcall* f, Fcall* r, uchar* data)
 {
 	Iobuf *p, *p1;
@@ -975,6 +1012,7 @@
 	}
 	iounit = chan->msize-IOHDRSZ;
 	if(count < 0 || count > iounit){
+fprint(2, "fs_read %d %d\n", count, iounit);
 		error = Ecount;
 		goto out;
 	}
@@ -1149,7 +1187,7 @@
 	return error;
 }
 
-static int
+int
 fs_write(Chan* chan, Fcall* f, Fcall* r)
 {
 	Iobuf *p, *p1;
@@ -1263,6 +1301,90 @@
 	return error;
 }
 
+int
+doremove(File *f)
+{
+	Iobuf *p, *p1;
+	Dentry *d, *d1;
+	Off addr;
+	int slot, err;
+
+	p = 0;
+	p1 = 0;
+	if(f->fs->dev->type == Devro) {
+		err = Eronly;
+		goto out;
+	}
+	/*
+	 * check on parent directory of file to be deleted
+	 */
+	if(f->wpath == 0 || f->wpath->addr == f->addr) {
+		err = Ephase;
+		goto out;
+	}
+	p1 = getbuf(f->fs->dev, f->wpath->addr, Brd);
+	d1 = getdir(p1, f->wpath->slot);
+	if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
+		err = Ephase;
+		goto out;
+	}
+	if(iaccess(f, d1, DWRITE)) {
+		err = Eaccess;
+		goto out;
+	}
+	accessdir(p1, d1, FWRITE, f->uid);
+	putbuf(p1);
+	p1 = 0;
+
+	/*
+	 * check on file to be deleted
+	 */
+	p = getbuf(f->fs->dev, f->addr, Brd);
+	d = getdir(p, f->slot);
+	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
+		err = Ealloc;
+		goto out;
+	}
+	if(err = mkqidcmp(&f->qid, d))
+		goto out;
+
+	/*
+	 * if deleting a directory, make sure it is empty
+	 */
+	if((d->mode & DDIR))
+	for(addr=0;; addr++) {
+		p1 = dnodebuf(p, d, addr, 0, f->uid);
+		if(!p1)
+			break;
+		if(checktag(p1, Tdir, d->qid.path)) {
+			err = Ephase;
+			goto out;
+		}
+		for(slot=0; slot<DIRPERBUF; slot++) {
+			d1 = getdir(p1, slot);
+			if(!(d1->mode & DALLOC))
+				continue;
+			err = Eempty;
+			goto out;
+		}
+		putbuf(p1);
+	}
+
+	/*
+	 * do it
+	 */
+	dtrunc(p, d, f->uid);
+	memset(d, 0, sizeof(Dentry));
+	settag(p, Tdir, QPNONE);
+
+out:
+	if(p1)
+		putbuf(p1);
+	if(p)
+		putbuf(p);
+	return err;
+}
+
 static int
 _clunk(File* file, int remove)
 {
@@ -1299,7 +1421,7 @@
 	return 0;
 }
 
-static int
+int
 fs_remove(Chan* chan, Fcall* f, Fcall*)
 {
 	File *file;
@@ -1309,7 +1431,7 @@
 	return _clunk(file, 1);
 }
 
-static int
+int
 fs_stat(Chan* chan, Fcall* f, Fcall* r, uchar* data)
 {
 	Dir dir;
--- a/sys/src/cmd/cwfs/auth.c
+++ b/sys/src/cmd/cwfs/auth.c
@@ -1,12 +1,7 @@
 #include "all.h"
 #include "io.h"
-#include <authsrv.h>
 #include <auth.h>
 
-Nvrsafe	nvr;
-
-static int gotnvr;	/* flag: nvr contains nvram; it could be bad */
-
 char*
 nvrgetconfig(void)
 {
@@ -13,75 +8,12 @@
 	return conf.confdev;
 }
 
-/*
- * we shouldn't be writing nvram any more.
- * the secstore/config field is now just secstore key.
- */
-
 int
-nvrcheck(void)
-{
-	uchar csum;
-
-	if (readnvram(&nvr, NVread) < 0) {
-		fprint(2, "nvrcheck: can't read nvram\n");
-		return 1;
-	} else
-		gotnvr = 1;
-
-	if(chatty)
-		print("nvr read\n");
-
-	csum = nvcsum(nvr.machkey, sizeof nvr.machkey);
-	if(csum != nvr.machsum) {
-		fprint(2, "\n\n ** NVR key checksum is incorrect  **\n");
-		fprint(2, " ** set password to allow attaches **\n\n");
-		memset(nvr.machkey, 0, sizeof nvr.machkey);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
 nvrsetconfig(char* word)
 {
 	/* config block is on device `word' */
 	USED(word);
 	return 0;
-}
-
-int
-conslock(void)
-{
-	char *ln;
-	Authkey nkey1;
-	static char zeroes[DESKEYLEN];
-
-	if(memcmp(nvr.machkey, zeroes, DESKEYLEN) == 0) {
-		print("no password set\n");
-		return 0;
-	}
-
-	for(;;) {
-		print("%s password:", service);
-		/* could turn off echo here */
-
-		if ((ln = Brdline(&bin, '\n')) == nil)
-			return 0;
-		ln[Blinelen(&bin)-1] = '\0';
-
-		/* could turn on echo here */
-		passtokey(&nkey1, ln);
-		if(memcmp(nkey1.des, nvr.machkey, DESKEYLEN) == 0) {
-			prdate();
-			break;
-		}
-
-		print("Bad password\n");
-		delay(1000);
-	}
-	return 1;
 }
 
 static char *keyspec = "proto=p9any role=server";
--- a/sys/src/cmd/cwfs/choline/conf.c
+++ b/sys/src/cmd/cwfs/choline/conf.c
@@ -25,7 +25,6 @@
 }
 
 int (*fsprotocol[])(Msgbuf*) = {
-	serve9p1,
 	serve9p2,
 	nil,
 };
--- a/sys/src/cmd/cwfs/config.c
+++ b/sys/src/cmd/cwfs/config.c
@@ -965,7 +965,6 @@
 	char word[Maxword+1], *cp;
 	Filsys *fs;
 
-	nvrcheck();
 	if(!setconfig(conf.confdev) && !conf.configfirst)
 		return;
 
--- a/sys/src/cmd/cwfs/console.c
+++ b/sys/src/cmd/cwfs/console.c
@@ -1,37 +1,34 @@
 #include	"all.h"
-#include	"9p1.h"
+#include	<fcall.h>
 
-void
-fcall9p1(Chan *cp, Fcall *in, Fcall *ou)
-{
-	int t;
+/* 9p2 */
+int	version(Chan*, Fcall*, Fcall*);
+int	attach(Chan*, Fcall*, Fcall*);
+int	walk(Chan*, Fcall*, Fcall*);
+int	fs_open(Chan*, Fcall*, Fcall*);
+int	fs_create(Chan*, Fcall*, Fcall*);
+int	fs_read(Chan*, Fcall*, Fcall*, uchar*);
+int	fs_write(Chan*, Fcall*, Fcall*);
+int	fs_remove(Chan*, Fcall*, Fcall*);
 
-	rlock(&mainlock);
-	t = in->type;
-	if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) {
-		fprint(2, "bad message type %d\n", t);
-		panic("");
-	}
-	ou->type = t+1;
-	ou->err = 0;
-
-	rlock(&cp->reflock);
-	(*call9p1[t])(cp, in, ou);
-	runlock(&cp->reflock);
-
-	if(ou->err && CHAT(cp))
-		fprint(2, "\terror: %s\n", errstr9p[ou->err]);
-	runlock(&mainlock);
-}
-
 int
 con_session(void)
 {
 	Fcall in, ou;
+	int err;
 
-	in.type = Tsession;
-	fcall9p1(cons.chan, &in, &ou);
-	return ou.err;
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
+	in.type = Tversion;
+	in.version = VERSION9P;
+	in.msize = MAXDAT + IOHDRSZ;
+
+	rlock(&mainlock);
+	err = version(cons.chan, &in, &ou);
+	runlock(&mainlock);
+
+	return err;
 }
 
 int
@@ -38,13 +35,21 @@
 con_attach(int fid, char *uid, char *arg)
 {
 	Fcall in, ou;
+	int err;
 
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
 	in.type = Tattach;
 	in.fid = fid;
-	strncpy(in.uname, uid, NAMELEN);
-	strncpy(in.aname, arg, NAMELEN);
-	fcall9p1(cons.chan, &in, &ou);
-	return ou.err;
+	in.uname = uid;
+	in.aname = arg;
+
+	rlock(&mainlock);
+	err = attach(cons.chan, &in, &ou);
+	runlock(&mainlock);
+
+	return err;
 }
 
 int
@@ -51,12 +56,21 @@
 con_clone(int fid1, int fid2)
 {
 	Fcall in, ou;
+	int err;
 
-	in.type = Tclone;
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
+	in.type = Twalk;
 	in.fid = fid1;
 	in.newfid = fid2;
-	fcall9p1(cons.chan, &in, &ou);
-	return ou.err;
+	in.nwname = 0;
+
+	rlock(&mainlock);
+	err = walk(cons.chan, &in, &ou);
+	runlock(&mainlock);
+
+	return err;
 }
 
 int
@@ -63,12 +77,22 @@
 con_walk(int fid, char *name)
 {
 	Fcall in, ou;
+	int err;
 
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
 	in.type = Twalk;
 	in.fid = fid;
-	strncpy(in.name, name, NAMELEN);
-	fcall9p1(cons.chan, &in, &ou);
-	return ou.err;
+	in.newfid = fid;
+	in.wname[0] = name;
+	in.nwname = 1;
+
+	rlock(&mainlock);
+	err = walk(cons.chan, &in, &ou);
+	runlock(&mainlock);
+
+	return err;
 }
 
 int
@@ -75,28 +99,66 @@
 con_open(int fid, int mode)
 {
 	Fcall in, ou;
+	int err;
 
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
 	in.type = Topen;
 	in.fid = fid;
 	in.mode = mode;
-	fcall9p1(cons.chan, &in, &ou);
-	return ou.err;
+
+	rlock(&mainlock);
+	err = fs_open(cons.chan, &in, &ou);
+	runlock(&mainlock);
+
+	return err;
 }
 
 int
+con_create(int fid, char *name, int uid, int gid, long perm, int mode)
+{
+	Fcall in, ou;
+	int err;
+
+	cons.uid = uid;			/* beyond ugly */
+	cons.gid = gid;
+
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
+	in.type = Tcreate;
+	in.fid = fid;
+	in.mode = mode;
+	in.perm = perm;
+	in.name = name;
+
+	rlock(&mainlock);
+	err = fs_create(cons.chan, &in, &ou);
+	runlock(&mainlock);
+
+	return err;
+}
+
+int
 con_read(int fid, char *data, Off offset, int count)
 {
 	Fcall in, ou;
+	int err;
 
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
 	in.type = Tread;
 	in.fid = fid;
 	in.offset = offset;
 	in.count = count;
-	ou.data = data;
-	fcall9p1(cons.chan, &in, &ou);
-	if(ou.err)
-		return 0;
-	return ou.count;
+
+	rlock(&mainlock);
+	err = fs_read(cons.chan, &in, &ou, (uchar*)data);
+	runlock(&mainlock);
+
+	return err ? 0 : ou.count;
 }
 
 int
@@ -103,16 +165,22 @@
 con_write(int fid, char *data, Off offset, int count)
 {
 	Fcall in, ou;
+	int err;
 
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
 	in.type = Twrite;
 	in.fid = fid;
-	in.data = data;
 	in.offset = offset;
 	in.count = count;
-	fcall9p1(cons.chan, &in, &ou);
-	if(ou.err)
-		return 0;
-	return ou.count;
+	in.data = data;
+
+	rlock(&mainlock);
+	err = fs_write(cons.chan, &in, &ou);
+	runlock(&mainlock);
+
+	return err ? 0 : ou.count;
 }
 
 int
@@ -119,29 +187,22 @@
 con_remove(int fid)
 {
 	Fcall in, ou;
+	int err;
 
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
 	in.type = Tremove;
 	in.fid = fid;
-	fcall9p1(cons.chan, &in, &ou);
-	return ou.err;
-}
 
-int
-con_create(int fid, char *name, int uid, int gid, long perm, int mode)
-{
-	Fcall in, ou;
+	rlock(&mainlock);
+	err = fs_remove(cons.chan, &in, &ou);
+	runlock(&mainlock);
 
-	in.type = Tcreate;
-	in.fid = fid;
-	strncpy(in.name, name, NAMELEN);
-	in.perm = perm;
-	in.mode = mode;
-	cons.uid = uid;			/* beyond ugly */
-	cons.gid = gid;
-	fcall9p1(cons.chan, &in, &ou);
-	return ou.err;
+	return err;
 }
 
+
 int
 doclri(File *f)
 {
@@ -196,14 +257,15 @@
 	return err;
 }
 
-void
+static int
 f_fstat(Chan *cp, Fcall *in, Fcall *ou)
 {
 	File *f;
 	Iobuf *p;
 	Dentry *d;
-	int i;
+	int i, err;
 
+	err = 0;
 	if(CHAT(cp)) {
 		fprint(2, "c_fstat %d\n", cp->chan);
 		fprint(2, "\tfid = %d\n", in->fid);
@@ -212,7 +274,7 @@
 	p = 0;
 	f = filep(cp, in->fid, 0);
 	if(!f) {
-		ou->err = Efid;
+		err = Efid;
 		goto out;
 	}
 	p = getbuf(f->fs->dev, f->addr, Brd);
@@ -238,12 +300,33 @@
 	ou->fid = in->fid;
 	if(f)
 		qunlock(f);
+	return err;
 }
 
-void
+int
+con_fstat(int fid)
+{
+	Fcall in, ou;
+	int err;
+
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
+	in.type = Tstat;
+	in.fid = fid;
+
+	rlock(&mainlock);
+	err = f_fstat(cons.chan, &in, &ou);
+	runlock(&mainlock);
+
+	return err;
+}
+
+static int
 f_clri(Chan *cp, Fcall *in, Fcall *ou)
 {
 	File *f;
+	int err;
 
 	if(CHAT(cp)) {
 		fprint(2, "c_clri %d\n", cp->chan);
@@ -252,15 +335,16 @@
 
 	f = filep(cp, in->fid, 0);
 	if(!f) {
-		ou->err = Efid;
+		err = Efid;
 		goto out;
 	}
-	ou->err = doclri(f);
+	err = doclri(f);
 
 out:
 	ou->fid = in->fid;
 	if(f)
 		qunlock(f);
+	return err;
 }
 
 int
@@ -267,42 +351,17 @@
 con_clri(int fid)
 {
 	Fcall in, ou;
-	Chan *cp;
+	int err;
 
+	memset(&in, 0, sizeof(in));
+	memset(&ou, 0, sizeof(ou));
+
 	in.type = Tremove;
 	in.fid = fid;
-	cp = cons.chan;
 
 	rlock(&mainlock);
-	ou.type = Tremove+1;
-	ou.err = 0;
-
-	rlock(&cp->reflock);
-	f_clri(cp, &in, &ou);
-	runlock(&cp->reflock);
-
+	err = f_clri(cons.chan, &in, &ou);
 	runlock(&mainlock);
-	return ou.err;
-}
 
-int
-con_fstat(int fid)
-{
-	Fcall in, ou;
-	Chan *cp;
-
-	in.type = Tstat;
-	in.fid = fid;
-	cp = cons.chan;
-
-	rlock(&mainlock);
-	ou.type = Tstat+1;
-	ou.err = 0;
-
-	rlock(&cp->reflock);
-	f_fstat(cp, &in, &ou);
-	runlock(&cp->reflock);
-
-	runlock(&mainlock);
-	return ou.err;
+	return err;
 }
--- a/sys/src/cmd/cwfs/cwfs/conf.c
+++ b/sys/src/cmd/cwfs/cwfs/conf.c
@@ -26,7 +26,6 @@
 }
 
 int (*fsprotocol[])(Msgbuf*) = {
-	serve9p1,
 	serve9p2,
 	nil,
 };
--- a/sys/src/cmd/cwfs/emelie/conf.c
+++ b/sys/src/cmd/cwfs/emelie/conf.c
@@ -27,7 +27,6 @@
 }
 
 int (*fsprotocol[])(Msgbuf*) = {
-	serve9p1,
 	serve9p2,
 	nil,
 };
--- a/sys/src/cmd/cwfs/fs/conf.c
+++ b/sys/src/cmd/cwfs/fs/conf.c
@@ -26,7 +26,6 @@
 }
 
 int (*fsprotocol[])(Msgbuf*) = {
-	serve9p1,
 	serve9p2,
 	nil,
 };
--- a/sys/src/cmd/cwfs/main.c
+++ b/sys/src/cmd/cwfs/main.c
@@ -1,7 +1,6 @@
 /* cached-worm file server */
 #include "all.h"
 #include "io.h"
-#include "9p1.h"
 
 Map *devmap;
 
@@ -466,10 +465,11 @@
 
 		if (mb->data == nil)
 			panic("serve: nil mb->data");
-		/* better sniffing code in /sys/src/cmd/disk/kfs/9p12.c */
-		if(cp->protocol == nil){
+		if(cp->protocol != nil){
+			/* process the request, generate an answer and reply */
+			cp->protocol(mb);
+		} else {
 			/* do we recognise the protocol in this packet? */
-			/* better sniffing code: /sys/src/cmd/disk/kfs/9p12.c */
 			for(i = 0; fsprotocol[i] != nil; i++)
 				if(fsprotocol[i](mb) != 0) {
 					cp->protocol = fsprotocol[i];
@@ -479,9 +479,7 @@
 				fprint(2, "no protocol for message\n");
 				hexdump(mb->data, 12);
 			}
-		} else
-			/* process the request, generate an answer and reply */
-			cp->protocol(mb);
+		}
 
 		mbfree(mb);
 		runlock(&mainlock);
--- a/sys/src/cmd/cwfs/portfns.h
+++ b/sys/src/cmd/cwfs/portfns.h
@@ -1,6 +1,5 @@
 void	accessdir(Iobuf*, Dentry*, int, int);
 void	addfree(Device*, Off, Superb*);
-void	arpstart(void);
 void	arginit(void);
 void*	authnew(void);
 void	authfree(void*);
@@ -12,8 +11,6 @@
 Off	bufalloc(Device*, int, long, int);
 void	buffree(Device*, Off, int, Truncstate *);
 int	byuid(void*, void*);
-int	canlock(Lock*);
-int	canqlock(QLock*);
 void	cfsdump(Filsys*);
 void	chanhangup(Chan *cp, char *msg);
 Chan*	fs_chaninit(int, int);
@@ -20,17 +17,11 @@
 void	cmd_check(int, char*[]);
 void	cmd_users(int, char*[]);
 void	cmd_newuser(int, char*[]);
-void	cmd_netdb(int, char*[]);
 void	cmd_printconf(int, char*[]);
 void	cmd_wormreset(int, char *[]);
 int	checkname(char*);
 int	checktag(Iobuf*, int, Off);
-int	cksum(void*, int, int);
-int	cksum0(int, int);
-void	cyclstart(void);
-void	dotrace(int);
 void	consserve(void);
-int	conslock(void);
 int	con_attach(int, char*, char*);
 int	con_clone(int, int);
 int	con_create(int, char*, int, int, long, int);
@@ -75,11 +66,7 @@
 void	exit(void);
 void	fileinit(Chan*);
 File*	filep(Chan*, ulong, int);
-void	firmware(void);
-int	fname(char*);
-int	fpair(char*, char*);
 void	formatinit(void);
-int	fread(void*, int);
 void	freefp(File*);
 void	freewp(Wpath*);
 Filsys*	fsstr(char*);
@@ -91,7 +78,6 @@
 Iobuf*	getbuf(Device*, Off, int);
 char*	getwrd(char*, char*);
 Dentry*	getdir(Iobuf*, int);
-Chan*	getlcp(uchar*, long);
 Off	getraddr(Device*);
 void	hexdump(void*, int);
 int	iaccess(File*, Dentry*, int);
@@ -101,7 +87,6 @@
 Device*	iconfig(char *);
 Off	indfetch(Device*, Off, Off, Off , int, int, int);
 int	ingroup(int, int);
-int	inh(int, uchar*);
 Devsize	inqsize(char *file);
 void	iobufinit(void);
 void*	iobufmap(Iobuf*);
@@ -115,13 +100,8 @@
 void	jukerecover(Device*);
 Off	jukesaddr(Device*);
 Devsize	jukesize(Device*);
-void	kbdchar(int);
-void	lights(int, int);
-void	launchinit(void);
 void	localconfinit(void);
 int	leadgroup(int, int);
-void	lock(Lock*);
-void	lockinit(void);
 void	machinit(void);
 Msgbuf*	mballoc(int, Chan*, int);
 void	mbinit(void);
@@ -143,13 +123,11 @@
 int	mlevread(Device*, Off, void*);
 Devsize	mlevsize(Device*);
 int	mlevwrite(Device*, Off, void*);
-int	nametokey(char*, char*);
 File*	newfp(void);
 void	newscsi(Device *d, Scsi *sc);
 Queue*	newqueue(int, char*);
 void	newstart(void);
 Wpath*	newwp(void);
-int	nvrcheck(void);
 char*	nvrgetconfig(void);
 int	nvrsetconfig(char*);
 int	walkto(char*);
@@ -164,23 +142,15 @@
 void	prdate(void);
 void	preread(Device*, Off);
 int	prime(vlong);
-void	printinit(void);
-void	procinit(void);
 void	procsetname(char *fmt, ...);
 void	putbuf(Iobuf*);
 Off	qidpathgen(Device*);
-void	qlock(QLock*);
 void*	querychanger(Device *);
-void	qunlock(QLock*);
 void	rahead(void *);
 void	ream(Filsys*);
 void*	fs_recv(Queue*, int);
 void	rootream(Device*, Off);
 int	roread(Device*, Off, void*);
-void	rstate(Chan*, int);
-Timet	rtc2sec(Rtc *);
-void	sched(void);
-void	schedinit(void);
 int	scsiio(Device*, int, uchar*, int, void*, int);
 void	scsiinit(void);
 Off	scsiread(int, void*, long);
@@ -190,10 +160,8 @@
 void	sec2rtc(Timet, Rtc *);
 void	fs_send(Queue*, void*);
 void	serve(void *);
-int	serve9p1(Msgbuf*);
 int	serve9p2(Msgbuf*);
 void	settag(Iobuf*, int, long);
-void	settime(Timet);
 int	strtouid(char*);
 Off	superaddr(Device*);
 void	superream(Device*, Off);
@@ -208,11 +176,8 @@
 Timet	nextime(Timet, int, int);
 Tlock*	tlocked(Iobuf*, Dentry*);
 Timet	toytime(void);
-Timet	rtctime(void);
-void	setrtc(Timet);
 void	uidtostr(char*, int, int);
 Uid*	uidpstr(char*);
-void	unlock(Lock*);
 void	newproc(void(*)(void *), void*, char*);
 void	wormcopy(void *);
 void	wormprobe(void);
@@ -232,4 +197,3 @@
 ulong	flag_install(char*, char*);
 void	srvinit(void);
 Chan	*srvchan(int, char *);
-
--- a/sys/src/cmd/cwfs/portmkfile
+++ b/sys/src/cmd/cwfs/portmkfile
@@ -3,8 +3,6 @@
 BIN=/$objtype/bin
 TARG=cwfs$FS
 OFILES=\
-	9p1.$O\
-	9p1lib.$O\
 	9p2.$O\
 	auth.$O\
 	chk.$O\
@@ -33,7 +31,6 @@
 	../32bit.h\
 	../64bit.h\
 	../64xbit.h\
-	../9p1.h\
 	../all.h\
 	dat.h\
 	../io.h\