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

📄 srv.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	r->fid->qid = r->ofcall.qid;	if(r->ofcall.qid.type&QTDIR)		r->fid->diroffset = 0;}static voidscreate(Srv *srv, Req *r){	if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil)		respond(r, Eunknownfid);	else if(r->fid->omode != -1)		respond(r, Ebotch);	else if(!(r->fid->qid.type&QTDIR))		respond(r, Ecreatenondir);	else if(r->fid->file && !hasperm(r->fid->file, r->fid->uid, AWRITE))		respond(r, Eperm);	else if(srv->create)		srv->create(r);	else		respond(r, Enocreate);}static voidrcreate(Req *r, char *error){	if(error)		return;	r->fid->omode = r->ifcall.mode;	r->fid->qid = r->ofcall.qid;}static voidsread(Srv *srv, Req *r){	int o;	if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){		respond(r, Eunknownfid);		return;	}	if((int)r->ifcall.count < 0){		respond(r, Ebotch);		return;	}	if(r->ifcall.offset < 0	|| ((r->fid->qid.type&QTDIR) && r->ifcall.offset != 0 && r->ifcall.offset != r->fid->diroffset)){		respond(r, Ebadoffset);		return;	}	if(r->ifcall.count > srv->msize - IOHDRSZ)		r->ifcall.count = srv->msize - IOHDRSZ;	r->rbuf = emalloc9p(r->ifcall.count);	r->ofcall.data = r->rbuf;	o = r->fid->omode & 3;	if(o != OREAD && o != ORDWR && o != OEXEC){		respond(r, Ebotch);		return;	}	if((r->fid->qid.type&QTDIR) && r->fid->file){		r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count);		respond(r, nil);		return;	}	if(srv->read)		srv->read(r);	else		respond(r, "no srv->read");}static voidrread(Req *r, char *error){	if(error==nil && (r->fid->qid.type&QTDIR))		r->fid->diroffset += r->ofcall.count;}static voidswrite(Srv *srv, Req *r){	int o;	char e[ERRMAX];	if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){		respond(r, Eunknownfid);		return;	}	if((int)r->ifcall.count < 0){		respond(r, Ebotch);		return;	}	if(r->ifcall.offset < 0){		respond(r, Ebotch);		return;	}	if(r->ifcall.count > srv->msize - IOHDRSZ)		r->ifcall.count = srv->msize - IOHDRSZ;	o = r->fid->omode & 3;	if(o != OWRITE && o != ORDWR){		snprint(e, sizeof e, "write on fid with open mode 0x%ux", r->fid->omode);		respond(r, e);		return;	}	if(srv->write)		srv->write(r);	else		respond(r, "no srv->write");}static voidrwrite(Req *r, char *error){	if(error)		return;	if(r->fid->file)		r->fid->file->qid.vers++;}static voidsclunk(Srv *srv, Req *r){	if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil)		respond(r, Eunknownfid);	else		respond(r, nil);}static voidrclunk(Req*, char*){}static voidsremove(Srv *srv, Req *r){	if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil){		respond(r, Eunknownfid);		return;	}	/* BUG RACE */	if(r->fid->file && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){		respond(r, Eperm);		return;	}	if(srv->remove)		srv->remove(r);	else		respond(r, r->fid->file ? nil : Enoremove);}static voidrremove(Req *r, char *error, char *errbuf){	if(error)		return;	if(r->fid->file){		if(removefile(r->fid->file) < 0){			snprint(errbuf, ERRMAX, "remove %s: %r", 				r->fid->file->name);			r->error = errbuf;		}		r->fid->file = nil;	}}static voidsstat(Srv *srv, Req *r){	if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){		respond(r, Eunknownfid);		return;	}	if(r->fid->file){		/* should we rlock the file? */		r->d = r->fid->file->Dir;		if(r->d.name)			r->d.name = estrdup9p(r->d.name);		if(r->d.uid)			r->d.uid = estrdup9p(r->d.uid);		if(r->d.gid)			r->d.gid = estrdup9p(r->d.gid);		if(r->d.muid)			r->d.muid = estrdup9p(r->d.muid);	}	if(srv->stat)			srv->stat(r);		else if(r->fid->file)		respond(r, nil);	else		respond(r, Enostat);}static voidrstat(Req *r, char *error){	int n;	uchar *statbuf;	uchar tmp[BIT16SZ];	if(error)		return;	if(convD2M(&r->d, tmp, BIT16SZ) != BIT16SZ){		r->error = "convD2M(_,_,BIT16SZ) did not return BIT16SZ";		return;	}	n = GBIT16(tmp)+BIT16SZ;	statbuf = emalloc9p(n);	if(statbuf == nil){		r->error = "out of memory";		return;	}	r->ofcall.nstat = convD2M(&r->d, statbuf, n);	r->ofcall.stat = statbuf;	/* freed in closereq */	if(r->ofcall.nstat <= BIT16SZ){		r->error = "convD2M fails";		free(statbuf);		return;	}}static voidswstat(Srv *srv, Req *r){	if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){		respond(r, Eunknownfid);		return;	}	if(srv->wstat == nil){		respond(r, Enowstat);		return;	}	if(convM2D(r->ifcall.stat, r->ifcall.nstat, &r->d, (char*)r->ifcall.stat) != r->ifcall.nstat){		respond(r, Ebaddir);		return;	}	if((ushort)~r->d.type){		respond(r, "wstat -- attempt to change type");		return;	}	if((uint)~r->d.dev){		respond(r, "wstat -- attempt to change dev");		return;	}	if((uchar)~r->d.qid.type || (ulong)~r->d.qid.vers || (uvlong)~r->d.qid.path){		respond(r, "wstat -- attempt to change qid");		return;	}	if(r->d.muid && r->d.muid[0]){		respond(r, "wstat -- attempt to change muid");		return;	}	if((ulong)~r->d.mode && ((r->d.mode&DMDIR)>>24) != (r->fid->qid.type&QTDIR)){		respond(r, "wstat -- attempt to change DMDIR bit");		return;	}	srv->wstat(r);}static voidrwstat(Req*, char*){}voidsrv(Srv *srv){	Req *r;	fmtinstall('D', dirfmt);	fmtinstall('F', fcallfmt);	if(srv->fpool == nil)		srv->fpool = allocfidpool(srv->destroyfid);	if(srv->rpool == nil)		srv->rpool = allocreqpool(srv->destroyreq);	if(srv->msize == 0)		srv->msize = 8192+IOHDRSZ;	changemsize(srv, srv->msize);	srv->fpool->srv = srv;	srv->rpool->srv = srv;	while(r = getreq(srv)){		if(r->error){			respond(r, r->error);			continue;			}		switch(r->ifcall.type){		default:			respond(r, "unknown message");			break;		case Tversion:	sversion(srv, r);	break;		case Tauth:	sauth(srv, r);	break;		case Tattach:	sattach(srv, r);	break;		case Tflush:	sflush(srv, r);	break;		case Twalk:	swalk(srv, r);	break;		case Topen:	sopen(srv, r);	break;		case Tcreate:	screate(srv, r);	break;		case Tread:	sread(srv, r);	break;		case Twrite:	swrite(srv, r);	break;		case Tclunk:	sclunk(srv, r);	break;		case Tremove:	sremove(srv, r);	break;		case Tstat:	sstat(srv, r);	break;		case Twstat:	swstat(srv, r);	break;		}	}	free(srv->rbuf);	srv->rbuf = nil;	free(srv->wbuf);	srv->wbuf = nil;	srv->msize = 0;	freefidpool(srv->fpool);	srv->fpool = nil;	freereqpool(srv->rpool);	srv->rpool = nil;	if(srv->end)		srv->end(srv);}voidrespond(Req *r, char *error){	int i, m, n;	char errbuf[ERRMAX];	Srv *srv;	srv = r->srv;	assert(srv != nil);	assert(r->responded == 0);	r->error = error;	switch(r->ifcall.type){	default:		assert(0);	/*	 * Flush is special.  If the handler says so, we return	 * without further processing.  Respond will be called	 * again once it is safe.	 */	case Tflush:		if(rflush(r, error)<0)			return;		break;	case Tversion:	rversion(r, error);	break;	case Tauth:	rauth(r, error);	break;	case Tattach:	rattach(r, error);	break;	case Twalk:	rwalk(r, error);	break;	case Topen:	ropen(r, error);	break;	case Tcreate:	rcreate(r, error);	break;	case Tread:	rread(r, error);	break;	case Twrite:	rwrite(r, error);	break;	case Tclunk:	rclunk(r, error);	break;	case Tremove:	rremove(r, error, errbuf);	break;	case Tstat:	rstat(r, error);	break;	case Twstat:	rwstat(r, error);	break;	}	r->ofcall.tag = r->ifcall.tag;	r->ofcall.type = r->ifcall.type+1;	if(r->error)		setfcallerror(&r->ofcall, r->error);if(chatty9p)	fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall);	qlock(&srv->wlock);	n = convS2M(&r->ofcall, srv->wbuf, srv->msize);	if(n <= 0){		fprint(2, "n = %d %F\n", n, &r->ofcall);		abort();	}	assert(n > 2);	if(r->pool)	/* not a fake */		closereq(removereq(r->pool, r->ifcall.tag));	m = write(srv->outfd, srv->wbuf, n);	if(m != n)		sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd);	qunlock(&srv->wlock);	qlock(&r->lk);	/* no one will add flushes now */	r->responded = 1;	qunlock(&r->lk);	for(i=0; i<r->nflush; i++)		respond(r->flush[i], nil);	free(r->flush);	r->flush = nil;	r->nflush = 0;	if(r->pool)		closereq(r);	else		free(r);}voidresponderror(Req *r){	char errbuf[ERRMAX];		rerrstr(errbuf, sizeof errbuf);	respond(r, errbuf);}intpostfd(char *name, int pfd){	int fd;	char buf[80];	snprint(buf, sizeof buf, "/srv/%s", name);	if(chatty9p)		fprint(2, "postfd %s\n", buf);	fd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600);	if(fd < 0){		if(chatty9p)			fprint(2, "create fails: %r\n");		return -1;	}	if(fprint(fd, "%d", pfd) < 0){		if(chatty9p)			fprint(2, "write fails: %r\n");		close(fd);		return -1;	}	if(chatty9p)		fprint(2, "postfd successful\n");	return 0;}

⌨️ 快捷键说明

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