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

📄 srvold9p.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <libsec.h>#include "9p1.h"char	*user;int	newfd;int	roldfd;int	woldfd;int	debug;int	dofcall;QLock	servelock;QLock	fidlock;QLock	taglock;int	mainpid;int	ntag;int	nfork;char FLUSHED[] = "FLUSHED";enum{	Maxfdata = 8192};enum{	Command,	Network,	File,	Stdio,};typedef struct Tag Tag;struct Tag{	int	tag;	int	flushed;	int	received;	int	ref;	Tag	*next;};typedef struct Message Message;struct Message{	char	*data;	int	n;};typedef struct Fid Fid;struct Fid{	short	busy;	short	allocated;	int	fid;	Qid	qid;	ulong	newoffset;	ulong	oldoffset;	Fid	*next;};Fid	*fids;Tag	*tags;char	*rflush(Fcall*, Fcall*, char*),	*rversion(Fcall*, Fcall*, char*),	*rauth(Fcall*, Fcall*, char*),	*rattach(Fcall*, Fcall*, char*),	*rwalk(Fcall*, Fcall*, char*),	*ropen(Fcall*, Fcall*, char*),	*rcreate(Fcall*, Fcall*, char*),	*rread(Fcall*, Fcall*, char*),	*rwrite(Fcall*, Fcall*, char*),	*rclunk(Fcall*, Fcall*, char*),	*rremove(Fcall*, Fcall*, char*),	*rstat(Fcall*, Fcall*, char*),	*rwstat(Fcall*, Fcall*, char*);char 	*(*fcalls[])(Fcall*, Fcall*, char*) = {	[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,};char Etoolong[] = "name too long";void	connect(int, char*);void	post(int, char*);void	serve(void);void	demux(void);void*	emalloc(ulong);char*	transact9p1(Fcall9p1*, Fcall9p1*, char*);Fid*	newfid(int);struct{	char	chal[CHALLEN];		/* my challenge */	char	rchal[CHALLEN];		/* his challenge */	char	authid[NAMEREC];	char	authdom[DOMLEN];	int	id;} ai;voidusage(void){	fprint(2, "usage: srvold9p [-abcCd] [-u user] [-s | [-m mountpoint]] [-x 'command' | -n network-addr | -f file] [-F] [-p servicename]\n");	exits("usage");}voidmain(int argc, char *argv[]){	int method;	char *oldstring;	char *mountpoint, *postname;	int mountflag, mountfd;	int p[2];int i;	fmtinstall('F', fcallfmt);	fmtinstall('G', fcallfmt9p1);	fmtinstall('D', dirfmt);	user = getuser();	mountpoint = nil;	mountflag = 0;	postname = nil;	oldstring = nil;	method = -1;	mountfd = -1;	ARGBEGIN{	case 'a':		mountflag |= MAFTER;		break;	case 'b':		mountflag |= MBEFORE;		break;	case 'c':		mountflag |= MCREATE;		break;	case 'C':		mountflag |= MCACHE;		break;	case 'd':		debug++;		break;	case 'f':		method = File;		oldstring = ARGF();		break;	case 'F':		dofcall++;		break;	case 'm':		mountpoint = EARGF(usage());		break;	case 'n':		method = Network;		oldstring = ARGF();		break;	case 'p':		postname = ARGF();		if(postname == nil)			usage();		break;	case 's':		method = Stdio;		break;	case 'u':		user = EARGF(usage());		break;	case 'x':		method = Command;		oldstring = ARGF();		break;	default:		usage();	}ARGEND;	if(method == Stdio){		if(mountpoint!=nil || argc!=0)			usage();	}else{		if(oldstring == nil || argc != 0 || (mountflag!=0 && mountpoint==nil))			usage();	}	rfork(RFNOTEG|RFREND);	connect(method, oldstring);	if(method == Stdio)		newfd = 0;	else{		if(pipe(p) < 0)			fatal("pipe: %r");		if(postname != nil)			post(p[0], postname);		mountfd = p[0];		newfd = p[1];	}	if(debug)		fprint(2, "connected and posted\n");	switch(rfork(RFPROC|RFMEM|RFNAMEG|RFFDG)){	case 0:		mainpid = getpid();		/* child does all the work */		if(mountfd >= 0)			close(mountfd);		switch(rfork(RFPROC|RFMEM|RFFDG)){		case 0:			for(i = 0; i < 20; i++)				if (i != roldfd) close(i);			demux();			return;		case -1:			fatal("fork error: %r");			break;		}		for(i = 0; i < 20; i++)			if (i != newfd && i != woldfd && (debug == 0 || i != 2)) close(i);		serve();		break;	case -1:		fatal("fork error: %r");		break;	default:		/* parent mounts if required, then exits */		if(mountpoint){			if(mount(mountfd, -1, mountpoint, mountflag, "") < 0)				fatal("can't mount: %r");		}		break;	}	exits(nil);}voidconnect(int method, char *oldstring){	char *s;	char dir[256];	switch(method){	default:		roldfd = -1;		woldfd = -1;		fatal("can't handle method type %d", method);		break;	case Network:		s = netmkaddr(oldstring, 0, "9fs");		roldfd = dial(s, 0, dir, 0);		if(roldfd < 0)			fatal("dial %s: %r", s);		woldfd = roldfd;		if(dofcall)			roldfd = fcall(woldfd);		break;	case File:		roldfd = open(oldstring, ORDWR);		if(roldfd < 0)			fatal("can't open %s: %r", oldstring);		woldfd = roldfd;		if(dofcall)			roldfd = fcall(woldfd);		break;	case Stdio:		roldfd = fcall(1);		woldfd = 1;		break;	}}voidpost(int fd, char *srv){	int f;	char buf[128];	snprint(buf, sizeof buf, "/srv/%s", srv);	f = create(buf, OWRITE, 0666);	if(f < 0)		fatal("can't create %s: %r", buf);	sprint(buf, "%d", fd);	if(write(f, buf, strlen(buf)) != strlen(buf))		fatal("post write: %r");	close(f);}Fid *newfid(int fid){	Fid *f, *ff;	ff = 0;	qlock(&fidlock);	for(f = fids; f; f = f->next)		if(f->fid == fid){			f->allocated = 1;			qunlock(&fidlock);			return f;		}		else if(!ff && !f->allocated)			ff = f;	if(ff){		ff->fid = fid;		ff->allocated = 1;		qunlock(&fidlock);		return ff;	}	f = emalloc(sizeof *f);	f->fid = fid;	f->next = fids;	f->allocated = 1;	fids = f;	qunlock(&fidlock);	return f;}/* * Reads returning 9P1 messages and demultiplexes them. * BUG: assumes one read per message. */voiddemux(void){	int m, n;	char *data;	Fcall9p1 r;	Message *msg;	Tag *t;	for(;;){		data = malloc(IOHDRSZ+Maxfdata);	/* no need to clear memory */		if(data == nil)			fatal("demux malloc: %r");		m = read(roldfd, data, IOHDRSZ+Maxfdata);		if(m <= 0)			fatal("read error talking to old system: %r");		n = convM2S9p1(data, &r, m);		if(n == 0)			fatal("bad conversion receiving from old system");		if(debug)			fprint(2, "srvold9p:<=%G\n", &r);		qlock(&taglock);		for(t=tags; t!=nil; t=t->next)			if(t->tag == r.tag){				t->received = 1;				break;			}		qunlock(&taglock);		/*		 * Fcall9p1 tag is used to rendezvous.		 * Recipient converts message a second time, but that's OK.		 */		msg = emalloc(sizeof(Message));		msg->data = data;		msg->n = n;		rendezvous((void*)r.tag, msg);	}}Tag*newtag(int tag){	Tag *t;	t = emalloc(sizeof(Tag));	t->tag = tag;	t->flushed = 0;	t->received = 0;	t->ref = 1;	qlock(&taglock);	t->next = tags;	tags = t;	qunlock(&taglock);	return t;}voidfreetag(Tag *tag)	/* called with taglock set */{	Tag *t, *prev;	if(tag->ref-- == 1){		prev = nil;		for(t=tags; t!=nil; t=t->next){			if(t == tag){				if(prev == nil)					tags = t->next;				else					prev->next = t->next;				break;			}			prev = t;		}		if(t == nil)			sysfatal("freetag");		free(tag);	}}voidserve(void){	char *err;	int n;	Fcall thdr;	Fcall	rhdr;	uchar mdata[IOHDRSZ+Maxfdata];	char mdata9p1[IOHDRSZ+Maxfdata];	Tag *tag;	for(;;){		qlock(&servelock);		for(;;){			n = read9pmsg(newfd, mdata, sizeof mdata);			if(n == 0)				continue;			if(n < 0)				break;			if(n > 0 && convM2S(mdata, n, &thdr) > 0)				break;		}		if(n>0 && servelock.head==nil)	/* no other processes waiting to read */			switch(rfork(RFPROC|RFMEM)){			case 0:				/* child starts serving */				continue;				break;			case -1:				fatal("fork error: %r");				break;			default:				break;			}		qunlock(&servelock);		if(n < 0)			fatal(nil);	/* exit quietly; remote end has just hung up */		if(debug)			fprint(2, "srvold9p:<-%F\n", &thdr);		tag = newtag(thdr.tag);		if(!fcalls[thdr.type])			err = "bad fcall type";		else			err = (*fcalls[thdr.type])(&thdr, &rhdr, mdata9p1);		qlock(&taglock);		if(tag->flushed){			freetag(tag);			qunlock(&taglock);			continue;		}		qunlock(&taglock);		if(err){			rhdr.type = Rerror;			rhdr.ename = err;		}else{			rhdr.type = thdr.type + 1;			rhdr.fid = thdr.fid;		}		rhdr.tag = thdr.tag;		if(debug)			fprint(2, "srvold9p:->%F\n", &rhdr);/**/		n = convS2M(&rhdr, mdata, sizeof mdata);		if(n == 0)			fatal("convS2M error on write");		if(write(newfd, mdata, n) != n)			fatal("mount write");		qlock(&taglock);		freetag(tag);		qunlock(&taglock);	}}voidsend9p1(Fcall9p1 *t, char *data){	int m, n;	if(debug)		fprint(2, "srvold9p:=>%G\n", t);	n = convS2M9p1(t, data);	if(n == 0)		fatal("bad conversion sending to old system");	m = write(woldfd, data, n);	if(m != n)		fatal("wrote %d to old system; should be %d", m, n);}intrecv9p1(Fcall9p1 *r, int tag, char *data){	int n;	Message *msg;	msg = rendezvous((void*)tag, 0);	if(msg == (void*)~0)		fatal("rendezvous: %r");	if(msg == nil){		if(debug)			fprint(2, "recv flushed\n");		return -1;	}	/* copy data to local buffer */	memmove(data, msg->data, msg->n);	n = convM2S9p1(data, r, msg->n);	if(n == 0)		fatal("bad conversion receiving from old system");	free(msg->data);	free(msg);	return 1;}char*transact9p1(Fcall9p1 *t, Fcall9p1 *r, char *mdata9p1){	send9p1(t, mdata9p1);	if(recv9p1(r, t->tag, mdata9p1) < 0)		return FLUSHED;	if(r->type == Rerror9p1)		return r->ename;	if(r->type != t->type+1)		fatal("bad message type; expected %d got %d", t->type+1, r->type);	return nil;}char*rflush(Fcall *t, Fcall *, char *mdata9p1){	Fcall9p1 t9, r9;	Tag *oldt;	t9.type = Tflush9p1;	t9.tag = t->tag;	t9.oldtag = t->oldtag;	qlock(&taglock);	for(oldt=tags; oldt!=nil; oldt=oldt->next)		if(oldt->tag == t->oldtag){			oldt->flushed = 1;			oldt->ref++;

⌨️ 快捷键说明

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