593 lines · 10.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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[];extern int	nclust; 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 '9':		noplan9 = 1;		break;	case 'c':		nclust = atoi(EARGF(usage()));		if (nclust <= 0)			sysfatal("nclust %d non-positive", nclust);		break;	case 'f':		deffile = EARGF(usage());		break;	case 'r':		norock = 1;		break;	case 's':		stdio = 1;		break;	case 'v':		chatty = 1;		break;	case 'J':		nojoliet = 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, nf == f, which is derived from req->newfid,		 * so we can't clunk req->newfid with xfile, which would put		 * f back on the free list, until we're done with f below.		 */		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(nf != nil)			xfile(req->newfid, Clunk);		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");

Lines 1–500 of 593.