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

📄 srv.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <thread.h>#include <9p.h>void (*_forker)(void(*)(void*), void*, int);static char Ebadattach[] = "unknown specifier in attach";static char Ebadoffset[] = "bad offset";static char Ebadcount[] = "bad count";static char Ebotch[] = "9P protocol botch";static char Ecreatenondir[] = "create in non-directory";static char Edupfid[] = "duplicate fid";static char Eduptag[] = "duplicate tag";static char Eisdir[] = "is a directory";static char Enocreate[] = "create prohibited";static char Enomem[] = "out of memory";static char Enoremove[] = "remove prohibited";static char Enostat[] = "stat prohibited";static char Enotfound[] = "file not found";static char Enowrite[] = "write prohibited";static char Enowstat[] = "wstat prohibited";static char Eperm[] = "permission denied";static char Eunknownfid[] = "unknown fid";static char Ebaddir[] = "bad directory in wstat";static char Ewalknodir[] = "walk in non-directory";static voidsetfcallerror(Fcall *f, char *err){	f->ename = err;	f->type = Rerror;}static voidchangemsize(Srv *srv, int msize){	if(srv->rbuf && srv->wbuf && srv->msize == msize)		return;	qlock(&srv->rlock);	qlock(&srv->wlock);	srv->msize = msize;	free(srv->rbuf);	free(srv->wbuf);	srv->rbuf = emalloc9p(msize);	srv->wbuf = emalloc9p(msize);	qunlock(&srv->rlock);	qunlock(&srv->wlock);}static Req*getreq(Srv *s){	long n;	uchar *buf;	Fcall f;	Req *r;	qlock(&s->rlock);	if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){		qunlock(&s->rlock);		return nil;	}	buf = emalloc9p(n);	memmove(buf, s->rbuf, n);	qunlock(&s->rlock);	if(convM2S(buf, n, &f) != n){		free(buf);		return nil;	}	if((r=allocreq(s->rpool, f.tag)) == nil){	/* duplicate tag: cons up a fake Req */		r = emalloc9p(sizeof *r);		incref(&r->ref);		r->tag = f.tag;		r->ifcall = f;		r->error = Eduptag;		r->buf = buf;		r->responded = 0;		r->type = 0;		r->srv = s;		r->pool = nil;if(chatty9p)	fprint(2, "<-%d- %F: dup tag\n", s->infd, &f);		return r;	}	r->srv = s;	r->responded = 0;	r->buf = buf;	r->ifcall = f;	memset(&r->ofcall, 0, sizeof r->ofcall);	r->type = r->ifcall.type;if(chatty9p)	if(r->error)		fprint(2, "<-%d- %F: %s\n", s->infd, &r->ifcall, r->error);	else			fprint(2, "<-%d- %F\n", s->infd, &r->ifcall);	return r;}static voidfilewalk(Req *r){	int i;	File *f;	f = r->fid->file;	assert(f != nil);	incref(f);	for(i=0; i<r->ifcall.nwname; i++)		if(f = walkfile(f, r->ifcall.wname[i]))			r->ofcall.wqid[i] = f->qid;		else			break;	r->ofcall.nwqid = i;	if(f){		r->newfid->file = f;		r->newfid->qid = r->newfid->file->qid;	}	respond(r, nil);}voidwalkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fid*, void*), void *arg){	int i;	char *e;	if(r->fid == r->newfid && r->ifcall.nwname > 1){		respond(r, "lib9p: unused documented feature not implemented");		return;	}	if(r->fid != r->newfid){		r->newfid->qid = r->fid->qid;		if(clone && (e = clone(r->fid, r->newfid, arg))){			respond(r, e);			return;		}	}	e = nil;	for(i=0; i<r->ifcall.nwname; i++){		if(e = walk1(r->newfid, r->ifcall.wname[i], arg))			break;		r->ofcall.wqid[i] = r->newfid->qid;	}	r->ofcall.nwqid = i;	if(e && i==0)		respond(r, e);	else		respond(r, nil);}static voidsversion(Srv*, Req *r){	if(strncmp(r->ifcall.version, "9P", 2) != 0){		r->ofcall.version = "unknown";		respond(r, nil);		return;	}	r->ofcall.version = "9P2000";	r->ofcall.msize = r->ifcall.msize;	respond(r, nil);}static voidrversion(Req *r, char *error){	assert(error == nil);	changemsize(r->srv, r->ofcall.msize);}static voidsauth(Srv *srv, Req *r){	char e[ERRMAX];	if((r->afid = allocfid(srv->fpool, r->ifcall.afid)) == nil){		respond(r, Edupfid);		return;	}	if(srv->auth)		srv->auth(r);	else{		snprint(e, sizeof e, "%s: authentication not required", argv0);		respond(r, e);	}}static voidrauth(Req *r, char *error){	if(error && r->afid)		closefid(removefid(r->srv->fpool, r->afid->fid));}static voidsattach(Srv *srv, Req *r){	if((r->fid = allocfid(srv->fpool, r->ifcall.fid)) == nil){		respond(r, Edupfid);		return;	}	r->afid = nil;	if(r->ifcall.afid != NOFID && (r->afid = lookupfid(srv->fpool, r->ifcall.afid)) == nil){		respond(r, Eunknownfid);		return;	}	r->fid->uid = estrdup9p(r->ifcall.uname);	if(srv->tree){		r->fid->file = srv->tree->root;		incref(r->fid->file);		r->ofcall.qid = r->fid->file->qid;		r->fid->qid = r->ofcall.qid;	}	if(srv->attach)		srv->attach(r);	else		respond(r, nil);	return;}static voidrattach(Req *r, char *error){	if(error && r->fid)		closefid(removefid(r->srv->fpool, r->fid->fid));}static voidsflush(Srv *srv, Req *r){	r->oldreq = lookupreq(srv->rpool, r->ifcall.oldtag);	if(r->oldreq == nil || r->oldreq == r)		respond(r, nil);	else if(srv->flush)		srv->flush(r);	else		respond(r, nil);}static intrflush(Req *r, char *error){	Req *or;	assert(error == nil);	or = r->oldreq;	if(or){		qlock(&or->lk);		if(or->responded == 0){			or->flush = erealloc9p(or->flush, (or->nflush+1)*sizeof(or->flush[0]));			or->flush[or->nflush++] = r;			qunlock(&or->lk);			return -1;		/* delay response until or is responded */		}		qunlock(&or->lk);		closereq(or);	}	r->oldreq = nil;	return 0;}static char*oldwalk1(Fid *fid, char *name, void *arg){	char *e;	Qid qid;	Srv *srv;	srv = arg;	e = srv->walk1(fid, name, &qid);	if(e)		return e;	fid->qid = qid;	return nil;}static char*oldclone(Fid *fid, Fid *newfid, void *arg){	Srv *srv;	srv = arg;	if(srv->clone == nil)		return nil;	return srv->clone(fid, newfid);}static voidswalk(Srv *srv, Req *r){	if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){		respond(r, Eunknownfid);		return;	}	if(r->fid->omode != -1){		respond(r, "cannot clone open fid");		return;	}	if(r->ifcall.nwname && !(r->fid->qid.type&QTDIR)){		respond(r, Ewalknodir);		return;	}	if(r->ifcall.fid != r->ifcall.newfid){		if((r->newfid = allocfid(srv->fpool, r->ifcall.newfid)) == nil){			respond(r, Edupfid);			return;		}		r->newfid->uid = estrdup9p(r->fid->uid);	}else{		incref(&r->fid->ref);		r->newfid = r->fid;	}	if(r->fid->file){		filewalk(r);	}else if(srv->walk1)		walkandclone(r, oldwalk1, oldclone, srv);	else if(srv->walk)		srv->walk(r);	else		sysfatal("no walk function, no file trees");}static voidrwalk(Req *r, char *error){	if(error || r->ofcall.nwqid < r->ifcall.nwname){		if(r->ifcall.fid != r->ifcall.newfid && r->newfid)			closefid(removefid(r->srv->fpool, r->newfid->fid));		if (r->ofcall.nwqid==0){			if(error==nil && r->ifcall.nwname!=0)				r->error = Enotfound;		}else			r->error = nil;	// No error on partial walks	}else{		if(r->ofcall.nwqid == 0){			/* Just a clone */			r->newfid->qid = r->fid->qid;		}else{			/* if file trees are in use, filewalk took care of the rest */			r->newfid->qid = r->ofcall.wqid[r->ofcall.nwqid-1];		}	}}static voidsopen(Srv *srv, Req *r){	int p;	if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){		respond(r, Eunknownfid);		return;	}	if(r->fid->omode != -1){		respond(r, Ebotch);		return;	}	if((r->fid->qid.type&QTDIR) && (r->ifcall.mode&~ORCLOSE) != OREAD){		respond(r, Eisdir);		return;	}	r->ofcall.qid = r->fid->qid;	switch(r->ifcall.mode&3){	default:		assert(0);	case OREAD:		p = AREAD;			break;	case OWRITE:		p = AWRITE;		break;	case ORDWR:		p = AREAD|AWRITE;		break;	case OEXEC:		p = AEXEC;			break;	}	if(r->ifcall.mode&OTRUNC)		p |= AWRITE;	if((r->fid->qid.type&QTDIR) && p!=AREAD){		respond(r, Eperm);		return;	}	if(r->fid->file){		if(!hasperm(r->fid->file, r->fid->uid, p)){			respond(r, Eperm);			return;		}	/* BUG RACE */		if((r->ifcall.mode&ORCLOSE)		&& !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){			respond(r, Eperm);			return;		}		r->ofcall.qid = r->fid->file->qid;		if((r->ofcall.qid.type&QTDIR)		&& (r->fid->rdir = opendirfile(r->fid->file)) == nil){			respond(r, "opendirfile failed");			return;		}	}	if(srv->open)		srv->open(r);	else		respond(r, nil);}static voidropen(Req *r, char *error){	char errbuf[ERRMAX];	if(error)		return;	if(chatty9p){		snprint(errbuf, sizeof errbuf, "fid mode is 0x%ux\n", r->ifcall.mode);		write(2, errbuf, strlen(errbuf));	}	r->fid->omode = r->ifcall.mode;

⌨️ 快捷键说明

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