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

📄 main.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include "dat.h"#include "fns.h"enum{	Maxfdata	= 8192,	Maxiosize	= IOHDRSZ+Maxfdata,};void io(int);void rversion(void);void	rattach(void);void	rauth(void);void	rclunk(void);void	rcreate(void);void	rflush(void);void	ropen(void);void	rread(void);void	rremove(void);void	rsession(void);void	rstat(void);void	rwalk(void);void	rwrite(void);void	rwstat(void);static int	openflags(int);static void	rmservice(void);static void	usage(void);#define Reqsize (sizeof(Fcall)+Maxfdata)Fcall *req;Fcall *rep;uchar mdata[Maxiosize];char fdata[Maxfdata];uchar statbuf[STATMAX];int errno;static char	srvfile[64];extern Xfsub	*xsublist[];jmp_buf	err_lab[16];int	nerr_lab;char	err_msg[ERRMAX];int	chatty;int	nojoliet;int	noplan9;int norock;void	(*fcalls[])(void) = {	[Tversion]	rversion,	[Tflush]	rflush,	[Tauth]	rauth,	[Tattach]	rattach,	[Twalk]		rwalk,	[Topen]		ropen,	[Tcreate]	rcreate,	[Tread]		rread,	[Twrite]	rwrite,	[Tclunk]	rclunk,	[Tremove]	rremove,	[Tstat]		rstat,	[Twstat]	rwstat,};voidmain(int argc, char **argv){	int srvfd, pipefd[2], stdio;	Xfsub **xs;	stdio = 0;	ARGBEGIN {	case 'v':		chatty = 1;		break;	case 'f':		deffile = ARGF();		break;	case 's':		stdio = 1;		break;	case '9':		noplan9 = 1;		break;	case 'J':		nojoliet = 1;		break;	case 'r':		norock = 1;		break;	default:		usage();	} ARGEND	switch(argc) {	case 0:		break;	case 1:		srvname = argv[0];		break;	default:		usage();	}	iobuf_init();	for(xs=xsublist; *xs; xs++)		(*(*xs)->reset)();	if(stdio) {		pipefd[0] = 0;		pipefd[1] = 1;	} else {		close(0);		close(1);		open("/dev/null", OREAD);		open("/dev/null", OWRITE);		if(pipe(pipefd) < 0)			panic(1, "pipe");		sprint(srvfile, "/srv/%s", srvname);		srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);		if(srvfd < 0)			panic(1, srvfile);		fprint(srvfd, "%d", pipefd[0]);		close(pipefd[0]);		fprint(2, "%s %d: serving %s\n", argv0, getpid(), srvfile);	}	srvfd = pipefd[1];	switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){	case -1:		panic(1, "fork");	default:		_exits(0);	case 0:		break;	}	io(srvfd);	exits(0);}voidio(int srvfd){	int n, pid;	Fcall xreq, xrep;	req = &xreq;	rep = &xrep;	pid = getpid();	fmtinstall('F', fcallfmt);	for(;;){		/*		 * reading from a pipe or a network device		 * will give an error after a few eof reads.		 * however, we cannot tell the difference		 * between a zero-length read and an interrupt		 * on the processes writing to us,		 * so we wait for the error.		 */		n = read9pmsg(srvfd, mdata, sizeof mdata);		if(n < 0)			break;		if(n == 0)			continue;		if(convM2S(mdata, n, req) == 0)			continue;		if(chatty)			fprint(2, "9660srv %d:<-%F\n", pid, req);		errno = 0;		if(!waserror()){			err_msg[0] = 0;			if(req->type >= nelem(fcalls) || !fcalls[req->type])				error("bad fcall type");			(*fcalls[req->type])();			poperror();		}		if(err_msg[0]){			rep->type = Rerror;			rep->ename = err_msg;		}else{			rep->type = req->type + 1;			rep->fid = req->fid;		}		rep->tag = req->tag;		if(chatty)			fprint(2, "9660srv %d:->%F\n", pid, rep);		n = convS2M(rep, mdata, sizeof mdata);		if(n == 0)			panic(1, "convS2M error on write");		if(write(srvfd, mdata, n) != n)			panic(1, "mount write");		if(nerr_lab != 0)			panic(0, "err stack %d: %lux %lux %lux %lux %lux %lux", nerr_lab,			err_lab[0][JMPBUFPC], err_lab[1][JMPBUFPC],			err_lab[2][JMPBUFPC], err_lab[3][JMPBUFPC],			err_lab[4][JMPBUFPC], err_lab[5][JMPBUFPC]);	}	chat("server shut down");}static voidusage(void){	fprint(2, "usage: %s [-v] [-9Jr] [-s] [-f devicefile] [srvname]\n", argv0);	exits("usage");}voiderror(char *p){	strecpy(err_msg, err_msg+sizeof err_msg, p);	nexterror();}voidnexterror(void){	longjmp(err_lab[--nerr_lab], 1);}void*ealloc(long n){	void *p;	p = malloc(n);	if(p == 0)		error("no memory");	return p;}voidsetnames(Dir *d, char *n){	d->name = n;	d->uid = n+Maxname;	d->gid = n+Maxname*2;	d->muid = n+Maxname*3;	d->name[0] = '\0';	d->uid[0] = '\0';	d->gid[0] = '\0';	d->muid[0] = '\0';}voidrversion(void){	if(req->msize > Maxiosize)		rep->msize = Maxiosize;	else		rep->msize = req->msize;	rep->version = "9P2000";}voidrauth(void){	error("9660srv: authentication not required");}voidrflush(void){}voidrattach(void){	Xfs *xf;	Xfile *root;	Xfsub **xs;	chat("attach(fid=%d,uname=\"%s\",aname=\"%s\")...",		req->fid, req->uname, req->aname);	if(waserror()){		xfile(req->fid, Clunk);		nexterror();	}	root = xfile(req->fid, Clean);	root->qid = (Qid){0, 0, QTDIR};	root->xf = xf = ealloc(sizeof(Xfs));	memset(xf, 0, sizeof(Xfs));	xf->ref = 1;	xf->d = getxdata(req->aname);	for(xs=xsublist; *xs; xs++)		if((*(*xs)->attach)(root) >= 0){			poperror();			xf->s = *xs;			xf->rootqid = root->qid;			rep->qid = root->qid;			return;		}	error("unknown format");}Xfile*doclone(Xfile *of, int newfid){	Xfile *nf, *next;	nf = xfile(newfid, Clean);	if(waserror()){		xfile(newfid, Clunk);		nexterror();	}	next = nf->next;	*nf = *of;	nf->next = next;	nf->fid = newfid;	refxfs(nf->xf, 1);	if(nf->len){		nf->ptr = ealloc(nf->len);		memmove(nf->ptr, of->ptr, nf->len);	}else		nf->ptr = of->ptr;	(*of->xf->s->clone)(of, nf);	poperror();	return nf;}voidrwalk(void){	Xfile *f, *nf;	Isofile *oldptr;	int oldlen;	Qid oldqid;	rep->nwqid = 0;	nf = nil;	f = xfile(req->fid, Asis);	if(req->fid != req->newfid)		f = nf = doclone(f, req->newfid);	/* save old state in case of error */	oldqid = f->qid;	oldlen = f->len;	oldptr = f->ptr;	if(oldlen){		oldptr = ealloc(oldlen);		memmove(oldptr, f->ptr, oldlen);	}	if(waserror()){		if(nf != nil)			xfile(req->newfid, Clunk);		if(rep->nwqid == req->nwname){			if(oldlen)				free(oldptr);		}else{			/* restore previous state */			f->qid = oldqid;			if(f->len)				free(f->ptr);			f->ptr = oldptr;			f->len = oldlen;		}		if(rep->nwqid==req->nwname || rep->nwqid > 0){			err_msg[0] = '\0';			return;		}		nexterror();	}	for(rep->nwqid=0; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){		chat("\twalking %s\n", req->wname[rep->nwqid]);		if(!(f->qid.type & QTDIR)){			chat("\tnot dir: type=%#x\n", f->qid.type);			error("walk in non-directory");		}				if(strcmp(req->wname[rep->nwqid], "..")==0){			if(f->qid.path != f->xf->rootqid.path)				(*f->xf->s->walkup)(f);		}else			(*f->xf->s->walk)(f, req->wname[rep->nwqid]);		rep->wqid[rep->nwqid] = f->qid;	}	poperror();	if(oldlen)		free(oldptr);}voidropen(void){	Xfile *f;	f = xfile(req->fid, Asis);	if(f->flags&Omodes)		error("open on open file");	if(req->mode&ORCLOSE)		error("no removes");	(*f->xf->s->open)(f, req->mode);	f->flags = openflags(req->mode);	rep->qid = f->qid;	rep->iounit = 0;}voidrcreate(void){	error("no creates");/*	Xfile *f;	if(strcmp(req->name, ".") == 0 || strcmp(req->name, "..") == 0)		error("create . or ..");	f = xfile(req->fid, Asis);	if(f->flags&Omodes)		error("create on open file");	if(!(f->qid.path&CHDIR))		error("create in non-directory");	(*f->xf->s->create)(f, req->name, req->perm, req->mode);	chat("f->qid=0x%8.8lux...", f->qid.path);	f->flags = openflags(req->mode);	rep->qid = f->qid;*/}voidrread(void){	Xfile *f;	f=xfile(req->fid, Asis);	if (!(f->flags&Oread))		error("file not opened for reading");	if(f->qid.type & QTDIR)		rep->count = (*f->xf->s->readdir)(f, (uchar*)fdata, req->offset, req->count);	else		rep->count = (*f->xf->s->read)(f, fdata, req->offset, req->count);	rep->data = fdata;}voidrwrite(void){	Xfile *f;	f=xfile(req->fid, Asis);	if(!(f->flags&Owrite))		error("file not opened for writing");	rep->count = (*f->xf->s->write)(f, req->data, req->offset, req->count);}voidrclunk(void){	Xfile *f;	if(!waserror()){		f = xfile(req->fid, Asis);		(*f->xf->s->clunk)(f);		poperror();	}	xfile(req->fid, Clunk);}voidrremove(void){	error("no removes");}voidrstat(void){	Xfile *f;	Dir dir;	chat("stat(fid=%d)...", req->fid);	f=xfile(req->fid, Asis);	setnames(&dir, fdata);	(*f->xf->s->stat)(f, &dir);	if(chatty)		showdir(2, &dir);	rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);	rep->stat = statbuf;}voidrwstat(void){	error("no wstat");}static intopenflags(int mode){	int flags = 0;	switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){	case OREAD:	case OEXEC:		flags = Oread; break;	case OWRITE:		flags = Owrite; break;	case ORDWR:		flags = Oread|Owrite; break;	}	if(mode & ORCLOSE)		flags |= Orclose;	return flags;}voidshowdir(int fd, Dir *s){	char a_time[32], m_time[32];	char *p;	strcpy(a_time, ctime(s->atime));	if(p=strchr(a_time, '\n'))	/* assign = */		*p = 0;	strcpy(m_time, ctime(s->mtime));	if(p=strchr(m_time, '\n'))	/* assign = */		*p = 0;	fprint(fd, "name=\"%s\" qid=(0x%llux,%lud) type=%d dev=%d \mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",		s->name, s->qid.path, s->qid.vers, s->type, s->dev,		s->mode, s->mode,		a_time, m_time, s->length, s->uid, s->gid);}#define	SIZE	1024voidchat(char *fmt, ...){	va_list arg;	if(chatty){		va_start(arg, fmt);		vfprint(2, fmt, arg);		va_end(arg);	}}voidpanic(int rflag, char *fmt, ...){	va_list arg;	char buf[SIZE]; int n;	n = sprint(buf, "%s %d: ", argv0, getpid());	va_start(arg, fmt);	vseprint(buf+n, buf+SIZE, fmt, arg);	va_end(arg);	fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);	if(chatty){		fprint(2, "abort\n");		abort();	}	exits("panic");}

⌨️ 快捷键说明

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