⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devmnt.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"error.h"/* * References are managed as follows: * The channel to the server - a network connection or pipe - has one * reference for every Chan open on the server.  The server channel has * c->mux set to the Mnt used for muxing control to that server.  Mnts * have no reference count; they go away when c goes away. * Each channel derived from the mount point has mchan set to c, * and increfs/decrefs mchan to manage references on the server * connection. */#define MAXRPC (IOHDRSZ+8192)struct Mntrpc{	Chan*	c;		/* Channel for whom we are working */	Mntrpc*	list;		/* Free/pending list */	Fcall	request;	/* Outgoing file system protocol message */	Fcall 	reply;		/* Incoming reply */	Mnt*	m;		/* Mount device during rpc */	Rendez	r;		/* Place to hang out */	uchar*	rpc;		/* I/O Data buffer */	uint	rpclen;		/* len of buffer */	Block	*b;		/* reply blocks */	char	done;		/* Rpc completed */	uvlong	stime;		/* start time for mnt statistics */	ulong	reqlen;		/* request length for mnt statistics */	ulong	replen;		/* reply length for mnt statistics */	Mntrpc*	flushed;	/* message this one flushes */};enum{	TAGSHIFT = 5,			/* ulong has to be 32 bits */	TAGMASK = (1<<TAGSHIFT)-1,	NMASK = (64*1024)>>TAGSHIFT,};struct Mntalloc{	Lock lk;	Mnt*	list;		/* Mount devices in use */	Mnt*	mntfree;	/* Free list */	Mntrpc*	rpcfree;	int	nrpcfree;	int	nrpcused;	ulong	id;	ulong	tagmask[NMASK];}mntalloc;Mnt*	mntchk(Chan*);void	mntdirfix(uchar*, Chan*);Mntrpc*	mntflushalloc(Mntrpc*, ulong);void	mntflushfree(Mnt*, Mntrpc*);void	mntfree(Mntrpc*);void	mntgate(Mnt*);void	mntpntfree(Mnt*);void	mntqrm(Mnt*, Mntrpc*);Mntrpc*	mntralloc(Chan*, ulong);long	mntrdwr(int, Chan*, void*, long, vlong);int	mntrpcread(Mnt*, Mntrpc*);void	mountio(Mnt*, Mntrpc*);void	mountmux(Mnt*, Mntrpc*);void	mountrpc(Mnt*, Mntrpc*);int	rpcattn(void*);Chan*	mntchan(void);char	Esbadstat[] = "invalid directory entry received from server";char	Enoversion[] = "version not established for mount channel";void (*mntstats)(int, Chan*, uvlong, ulong);static voidmntreset(void){	mntalloc.id = 1;	mntalloc.tagmask[0] = 1;			/* don't allow 0 as a tag */	mntalloc.tagmask[NMASK-1] = 0x80000000UL;	/* don't allow NOTAG */	fmtinstall('F', fcallfmt);	fmtinstall('D', dirfmt);/* We can't install %M since eipfmt does and is used in the kernel [sape] */	cinit();}/* * Version is not multiplexed: message sent only once per connection. */longmntversion(Chan *c, char *version, int msize, int returnlen){	Fcall f;	uchar *msg;	Mnt *m;	char *v;	long k, l;	uvlong oo;	char buf[128];	qlock(&c->umqlock);	/* make sure no one else does this until we've established ourselves */	if(waserror()){		qunlock(&c->umqlock);		nexterror();	}	/* defaults */	if(msize == 0)		msize = MAXRPC;	if(msize > c->iounit && c->iounit != 0)		msize = c->iounit;	v = version;	if(v == nil || v[0] == '\0')		v = VERSION9P;	/* validity */	if(msize < 0)		error("bad iounit in version call");	if(strncmp(v, VERSION9P, strlen(VERSION9P)) != 0)		error("bad 9P version specification");	m = c->mux;	if(m != nil){		qunlock(&c->umqlock);		poperror();		strecpy(buf, buf+sizeof buf, m->version);		k = strlen(buf);		if(strncmp(buf, v, k) != 0){			snprint(buf, sizeof buf, "incompatible 9P versions %s %s", m->version, v);			error(buf);		}		if(returnlen > 0){			if(returnlen < k)				error(Eshort);			memmove(version, buf, k);		}		return k;	}	f.type = Tversion;	f.tag = NOTAG;	f.msize = msize;	f.version = v;	msg = malloc(8192+IOHDRSZ);	if(msg == nil)		exhausted("version memory");	if(waserror()){		free(msg);		nexterror();	}	k = convS2M(&f, msg, 8192+IOHDRSZ);	if(k == 0)		error("bad fversion conversion on send");	lock(&c->ref.lk);	oo = c->offset;	c->offset += k;	unlock(&c->ref.lk);	l = devtab[c->type]->write(c, msg, k, oo);	if(l < k){		lock(&c->ref.lk);		c->offset -= k - l;		unlock(&c->ref.lk);		error("short write in fversion");	}	/* message sent; receive and decode reply */	k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);	if(k <= 0)		error("EOF receiving fversion reply");	lock(&c->ref.lk);	c->offset += k;	unlock(&c->ref.lk);	l = convM2S(msg, k, &f);	if(l != k)		error("bad fversion conversion on reply");	if(f.type != Rversion){		if(f.type == Rerror)			error(f.ename);		error("unexpected reply type in fversion");	}	if(f.msize > msize)		error("server tries to increase msize in fversion");	if(f.msize<256 || f.msize>1024*1024)		error("nonsense value of msize in fversion");	k = strlen(f.version);	if(strncmp(f.version, v, k) != 0)		error("bad 9P version returned from server");	/* now build Mnt associated with this connection */	lock(&mntalloc.lk);	m = mntalloc.mntfree;	if(m != 0)		mntalloc.mntfree = m->list;	else {		m = malloc(sizeof(Mnt));		if(m == 0) {			unlock(&mntalloc.lk);			exhausted("mount devices");		}	}	m->list = mntalloc.list;	mntalloc.list = m;	m->version = nil;	kstrdup(&m->version, f.version);	m->id = mntalloc.id++;	m->q = qopen(10*MAXRPC, 0, nil, nil);	m->msize = f.msize;	unlock(&mntalloc.lk);	if(returnlen > 0){		if(returnlen < k)			error(Eshort);		memmove(version, f.version, k);	}	poperror();	/* msg */	free(msg);	lock(&m->lk);	m->queue = 0;	m->rip = 0;	c->flag |= CMSG;	c->mux = m;	m->c = c;	unlock(&m->lk);	poperror();	/* c */	qunlock(&c->umqlock);	return k;}Chan*mntauth(Chan *c, char *spec){	Mnt *m;	Mntrpc *r;	m = c->mux;	if(m == nil){		mntversion(c, VERSION9P, MAXRPC, 0);		m = c->mux;		if(m == nil)			error(Enoversion);	}	c = mntchan();	if(waserror()) {		/* Close must not be called since it will		 * call mnt recursively		 */		chanfree(c);		nexterror();	}	r = mntralloc(0, m->msize);	if(waserror()) {		mntfree(r);		nexterror();	}	r->request.type = Tauth;	r->request.afid = c->fid;	r->request.uname = up->user;	r->request.aname = spec;	mountrpc(m, r);	c->qid = r->reply.aqid;	c->mchan = m->c;	incref(&m->c->ref);	c->mqid = c->qid;	c->mode = ORDWR;	poperror();	/* r */	mntfree(r);	poperror();	/* c */	return c;}static Chan*mntattach(char *muxattach){	Mnt *m;	Chan *c;	Mntrpc *r;	struct bogus{		Chan	*chan;		Chan	*authchan;		char	*spec;		int	flags;	}bogus;	bogus = *((struct bogus *)muxattach);	c = bogus.chan;	{ // Plan 9 VX addition		extern Dev mntloopdevtab;		Chan *mc;		if(devtab[c->type] == &mntloopdevtab){			if(bogus.authchan || (bogus.spec && bogus.spec[0]))				error(Ebadarg);			mc = c->aux;			incref(&mc->ref);			return mc;		}	}	m = c->mux;	if(m == nil){		mntversion(c, nil, 0, 0);		m = c->mux;		if(m == nil)			error(Enoversion);	}	c = mntchan();	if(waserror()) {		/* Close must not be called since it will		 * call mnt recursively		 */		chanfree(c);		nexterror();	}	r = mntralloc(0, m->msize);	if(waserror()) {		mntfree(r);		nexterror();	}	r->request.type = Tattach;	r->request.fid = c->fid;	if(bogus.authchan == nil)		r->request.afid = NOFID;	else		r->request.afid = bogus.authchan->fid;	r->request.uname = up->user;	r->request.aname = bogus.spec;	mountrpc(m, r);	c->qid = r->reply.qid;	c->mchan = m->c;	incref(&m->c->ref);	c->mqid = c->qid;	poperror();	/* r */	mntfree(r);	poperror();	/* c */	if(bogus.flags&MCACHE)		c->flag |= CCACHE;	return c;}Chan*mntchan(void){	Chan *c;	c = devattach('M', 0);	lock(&mntalloc.lk);	c->dev = mntalloc.id++;	unlock(&mntalloc.lk);	if(c->mchan)		panic("mntchan non-zero %p", c->mchan);	return c;}static Walkqid*mntwalk(Chan *c, Chan *nc, char **name, int nname){	int i, alloc;	Mnt *m;	Mntrpc *r;	Walkqid *wq;	if(nc != nil)		print("mntwalk: nc != nil\n");	if(nname > MAXWELEM)		error("devmnt: too many name elements");	alloc = 0;	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));	if(waserror()){		if(alloc && wq->clone!=nil)			cclose(wq->clone);		free(wq);		return nil;	}	alloc = 0;	m = mntchk(c);	r = mntralloc(c, m->msize);	if(nc == nil){		nc = devclone(c);		/*		 * Until the other side accepts this fid, we can't mntclose it.		 * Therefore set type to 0 for now; rootclose is known to be safe.		 */		nc->type = 0;		alloc = 1;	}	wq->clone = nc;	if(waserror()) {		mntfree(r);		nexterror();	}	r->request.type = Twalk;	r->request.fid = c->fid;	r->request.newfid = nc->fid;	r->request.nwname = nname;	memmove(r->request.wname, name, nname*sizeof(char*));	mountrpc(m, r);	if(r->reply.nwqid > nname)		error("too many QIDs returned by walk");	if(r->reply.nwqid < nname){		if(alloc)			cclose(nc);		wq->clone = nil;		if(r->reply.nwqid == 0){			free(wq);			wq = nil;			goto Return;		}	}	/* move new fid onto mnt device and update its qid */	if(wq->clone != nil){		if(wq->clone != c){			wq->clone->type = c->type;			wq->clone->mchan = c->mchan;			incref(&c->mchan->ref);		}		if(r->reply.nwqid > 0)			wq->clone->qid = r->reply.wqid[r->reply.nwqid-1];	}	wq->nqid = r->reply.nwqid;	for(i=0; i<wq->nqid; i++)		wq->qid[i] = r->reply.wqid[i];    Return:	poperror();	mntfree(r);	poperror();	return wq;}static intmntstat(Chan *c, uchar *dp, int n){	Mnt *m;	Mntrpc *r;	if(n < BIT16SZ)		error(Eshortstat);	m = mntchk(c);	r = mntralloc(c, m->msize);	if(waserror()) {		mntfree(r);		nexterror();	}	r->request.type = Tstat;	r->request.fid = c->fid;	mountrpc(m, r);	if(r->reply.nstat > n){		n = BIT16SZ;		PBIT16((uchar*)dp, r->reply.nstat-2);	}else{		n = r->reply.nstat;		memmove(dp, r->reply.stat, n);		validstat(dp, n);		mntdirfix(dp, c);	}	poperror();	mntfree(r);	return n;}static Chan*mntopencreate(int type, Chan *c, char *name, int omode, ulong perm){	Mnt *m;	Mntrpc *r;	m = mntchk(c);	r = mntralloc(c, m->msize);	if(waserror()) {		mntfree(r);		nexterror();	}	r->request.type = type;	r->request.fid = c->fid;	r->request.mode = omode;	if(type == Tcreate){		r->request.perm = perm;		r->request.name = name;	}	mountrpc(m, r);	c->qid = r->reply.qid;	c->offset = 0;	c->mode = openmode(omode);	c->iounit = r->reply.iounit;	if(c->iounit == 0 || c->iounit > m->msize-IOHDRSZ)		c->iounit = m->msize-IOHDRSZ;	c->flag |= COPEN;	poperror();	mntfree(r);	if(c->flag & CCACHE)		copen(c);	return c;}static Chan*mntopen(Chan *c, int omode){	return mntopencreate(Topen, c, nil, omode, 0);}static voidmntcreate(Chan *c, char *name, int omode, ulong perm){	mntopencreate(Tcreate, c, name, omode, perm);}static voidmntclunk(Chan *c, int t){	Mnt *m;	Mntrpc *r;	m = mntchk(c);	r = mntralloc(c, m->msize);	if(waserror()){		mntfree(r);		nexterror();	}	r->request.type = t;	r->request.fid = c->fid;	mountrpc(m, r);	mntfree(r);	poperror();}voidmuxclose(Mnt *m){	Mntrpc *q, *r;	for(q = m->queue; q; q = r) {		r = q->list;		mntfree(q);	}	m->id = 0;	free(m->version);	m->version = nil;	mntpntfree(m);}voidmntpntfree(Mnt *m){	Mnt *f, **l;	Queue *q;	lock(&mntalloc.lk);	l = &mntalloc.list;	for(f = *l; f; f = f->list) {		if(f == m) {			*l = m->list;			break;		}		l = &f->list;	}	m->list = mntalloc.mntfree;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -