henesyinit from p9f47575dc5 years agoHistory
940 lines · 14.9 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <fcall.h>#include <libg.h>#include <frame.h>#include "dat.h"#include "fns.h" #define	NFID	5000#define	NFILE	1000 typedef struct Rfile	Rfile;typedef struct File	File;typedef struct Dirtab	Dirtab; struct Rfile			/* indexed by fid to find file */{	int	busy;	int	open;	int	eof;	File	*file;}; struct File{	int	busy;	ulong	path;		/* == qid.path */	ulong	slot;		/* == qid.vers */	Dirtab	*dir;}; struct Dirtab{	char	*name;	ulong	qid;	ulong	perm;}; char	*errname[]={	[Ebadaddr]	"bad address in control message",	[Ebadctl]	"bad control message",	[Eclosed]	"page is closed",	[Eio]		"i/o error",	[Eisdir]	"file is a directory",	[Enonexist]	"file does not exist",	[Enopage]	"no context to create page",	[Enotdir]	"not a directory",	[Eperm]		"permission denied",	[Eslot]		"slot out of range",	[Egreg]		"it's all greg's fault",}; Rfile	rfile[NFID];File	file[NFILE];char	rdata[MAXMSG+MAXFDATA+1];char	tdata[MAXMSG+MAXFDATA+1];Fcall	rhdr;Fcall	thdr;int	sfd;		/* server end of pipe */char	user[NAMELEN];Client	client[NSLOT];char	*tmpstr; void	rflush(void);void	rattach(Rfile*);void	rclone(Rfile*, int);int	rwalk(Rfile*);void	ropen(Rfile*);void	rcreate(Rfile*);void	rread(Rfile*);void	rwrite(Rfile*);void	rclunk(Rfile*, int);void	rstat(Rfile*);void	rwstat(Rfile*);void	rerrstr(Rfile*);void	ruserstr(Rfile*); void	sendmsg(int);long	getclock(void); char *mname[]={	[Tnop]		"Tnop",	[Rnop]		"Rnop",	[Tflush]	"Tflush",	[Rflush]	"Rflush",	[Terror]	"Terror",	[Rerror]	"Rerror",	[Tsession]	"Tsession",	[Rsession]	"Rsession",	[Tattach]	"Tattach",	[Rattach]	"Rattach",	[Tclone]	"Tclone",	[Rclone]	"Rclone",	[Twalk]		"Twalk",	[Rwalk]		"Rwalk",	[Topen]		"Topen",	[Ropen]		"Ropen",	[Tcreate]	"Tcreate",	[Rcreate]	"Rcreate",	[Tclunk]	"Tclunk",	[Rclunk]	"Rclunk",	[Tread]		"Tread",	[Rread]		"Rread",	[Twrite]	"Twrite",	[Rwrite]	"Rwrite",	[Tremove]	"Tremove",	[Rremove]	"Rremove",	[Tstat]		"Tstat",	[Rstat]		"Rstat",	[Twstat]	"Twstat",	[Rwstat]	"Rwstat",	0, 0, 0}; /* * Layout of qid: * 	path bits 0-3	type of file (cons, index, etc.) *	path bits 4-31	page id *	vers		slot number */ enum{	Qdir,	Qcons,	Qindex,	Qconsctl,	Qmouse,	Qnew,	Qdir1,	Qctl,	Qtag,	Qbody,	Qtagpos,	Qtagsel,	Qbodypos,	Qbodysel,	Qbodyapp,}; #define	NQID		16#define	QPAGESHIFT	4#define	QID(qid)	((qid)&(NQID-1))#define	QPAGE(qid)	(((qid)&~(CHDIR|(NQID-1)))>>QPAGESHIFT) Dirtab dirtab0[] ={	".",		{CHDIR+Qdir},	CHDIR|0500,	"cons",		{Qcons},	0200,	"index",	{Qindex},	0400,	"consctl",	{Qconsctl},	0200,	"mouse",	{Qmouse},	0200,	"new",		{CHDIR+Qnew},	CHDIR|0500,	".",		{CHDIR+Qdir1},	CHDIR|0500,	0,		0,	0,}; Dirtab dirtab1[] ={	".",		{CHDIR+Qdir1},	CHDIR|0500,	"ctl",		{Qctl},		0600,	"tag",		{Qtag},		0400,	"body",		{Qbody},		0400,	"tagpos",	{Qtagpos},	0400,	"tagsel",	{Qtagsel},	0400,	"bodypos",	{Qbodypos},	0400,	"bodysel",	{Qbodysel},	0400,	"bodyapp",	{Qbodyapp},	0200,	0,		0,		0,}; voidio(void){	long n;	Rfile *rf; 	bflush();	n = read(sfd, rdata, sizeof rdata);	if(n <= 0)		error("mount read");	if(convM2S(rdata, &rhdr, n) == 0)		error("format error");	if(rhdr.fid<0 || NFID<=rhdr.fid)		error("fid out of range");	/*BUG: check busy */	rf = &rfile[rhdr.fid];/*	fprint(2, "msg: %d %s on %d\n", rhdr.type,		mname[rhdr.type]? mname[rhdr.type] : "mystery", rhdr.fid); /**/	switch(rhdr.type){	default:		error("type");		break;	case Tflush:		rflush();		break;	case Tattach:		rattach(rf);		break;	case Tclone:		rclone(rf, 0);		break;	case Twalk:		rwalk(rf);		break;	case Tclwalk:		rclone(rf, 1);		break;	case Topen:		ropen(rf);		break;	case Tcreate:		rcreate(rf);		break;	case Tread:		rread(rf);		break;	case Twrite:		rwrite(rf);		break;	case Tclunk:		rclunk(rf, 0);		break;	case Tremove:		rclunk(rf, Eperm);		break;	case Tstat:		rstat(rf);		break;	case Twstat:		rwstat(rf);		break;	}} intnewfile(void){	int i; 	for(i=0; i<NFILE; i++)		if(file[i].busy == 0)			return i;	error("no free files");	return -1;} voidrflush(void)		/* program is synchronous so flush is easy */{	sendmsg(0);} voidrattach(Rfile *rf){	int f, s, err; 	err = 0;	if(strcmp(rhdr.aname, "slave") == 0){		f = 0;		file[0].slot = 0;	}else{		s = atoi(rhdr.aname);		if(s<=0 || s>=NSLOT){			print("slot %d out of range\n", s);			err = Eslot;			goto send;		}		f = newfile();		file[f].slot = s;	}	rf->busy = 1;	rf->open = 0;	rf->eof = 0;	file[f].busy = 1;	file[f].path = CHDIR;	file[f].dir = &dirtab0[0];	rf->file = &file[f];	thdr.qid.path = rf->file->path;	thdr.qid.vers = rf->file->slot;	strcpy(user, rhdr.uname);	client[rf->file->slot].ref++;    send:	sendmsg(err);} voidrclone(Rfile *rf, int dowalk){	Rfile *nrf;	int err=0; 	nrf = &rfile[rhdr.newfid];	if(rhdr.newfid<0 || NFID<=rhdr.newfid)		error("clone nfid out of range");	if(nrf->busy)		error("clone to used channel");	nrf->busy = 1;	nrf->open = 0;	nrf->eof = 0;	nrf->file = rf->file;	client[nrf->file->slot].ref++;	if(dowalk){		rhdr.fid = rhdr.newfid;		if(rwalk(nrf)){			client[nrf->file->slot].ref--;			nrf->busy = 0;		}		return;	}    send:	sendmsg(err);} intrwalk(Rfile *rf){	int err, slot;	long dqid, qid, pno;	char *name;	File *fp;	Dirtab *tab;	Page *p;	int i, j, q; 	err = 0;	qid = 0;	slot = rf->file->slot;	dqid = rf->file->path;	pno = QPAGE(dqid)<<QPAGESHIFT;	name = rhdr.name;	if((dqid&CHDIR) == 0){		err = Enotdir;		goto send;	}	if(QID(dqid) == Qdir1){		tab = dirtab1;		goto Tablookup;	}	/* first, is it a directory-by-number? */	q = atoi(name);	if(q > 0){		if(pagelookup(q)){			qid = CHDIR|(q<<QPAGESHIFT)|Qdir1;			tab = dirtab0;			j = Qdir1;	/* distasteful! */			goto Found;		}		err = Enonexist;		goto send;	} 	/* no: table lookup */	tab = dirtab0;     Tablookup:	for(j=0; tab[j].name; j++){		if(strcmp(name, tab[j].name) == 0){			if(tab[j].qid == CHDIR+Qnew){				/* make new page */				if(curt)					p = curt->page;				else{					p = page;					if(p == 0){						err = Enopage;						goto send;					}				}				if(p->parent == 0)					while(p->down)						p = p->down;				q = pageadd(p->parent, 1)->id;				qid = CHDIR|(q<<QPAGESHIFT)|Qdir1;				tab = dirtab0;				j = Qdir1;	/* distasteful! */			}else				qid = pno|tab[j].qid;    Found:			for(i=0,fp=file; i<NFILE; i++,fp++)				if(fp->busy && fp->path==qid && fp->slot==rf->file->slot){					rf->file = fp;					goto send;				}			i = newfile();			fp = &file[i];			fp->busy = 1;			fp->slot = rf->file->slot;			fp->path = qid;			fp->dir = &tab[j];			rf->file = fp;			goto send;		}	}	err = Enonexist;     send:	thdr.qid.path = qid;	thdr.qid.vers = slot;	sendmsg(err);	return err;} voidropen(Rfile *rf){	int err, mode, trunc;	File *fp;	long perm; 	err = 0;	fp = rf->file;	perm = fp->dir->perm;	mode = rhdr.mode;	if(fp->path & CHDIR){		if(mode){			err = Eperm;			goto send;		}	}else{		trunc = mode & OTRUNC;		mode &= ~OTRUNC;		if(mode<0 || mode>OEXEC){			err = Eperm;			goto send;		}		if(((mode==OREAD  || mode==ORDWR) && !(perm&0400))		|| ((mode==OWRITE || mode==ORDWR) && !(perm&0200))		|| ((mode==OEXEC) && !(perm&0100))		|| (trunc && !(perm&0200))){			err = Eperm;			goto send;		}	} 	if(fp->slot > 0) switch(QID(fp->path)){	case Qdir:	case Qdir1:	case Qcons:	case Qindex:		break; 	case Qconsctl:	case Qmouse:		err = Egreg;		goto send; 	case Qctl:	case Qtag:	case Qbody:	case Qtagpos:	case Qtagsel:	case Qbodypos:	case Qbodysel:	case Qbodyapp:		break; 	default:		err = Enonexist;		goto send;	}	rf->open = 1;     send:	thdr.qid.path = fp->path;	thdr.qid.vers = fp->slot;	sendmsg(err);} voidrcreate(Rfile *rf){	USED(rf);	sendmsg(Eperm);} #define	NUMLEN	12 voidrread(Rfile *rf){	int j, n, err, cnt;	long off, clock, slot, qid, cn;	Rune *r;	ulong c0, c1, q0;	Dir dir;	File *fp;	Dirtab *tab;	Dirtab *dp;	Client *c;	String *s;	Text *t;	Page *p;	static char buf[NQID*DIRLEN]; 	n = 0;	err = 0;	off = rhdr.offset;	cnt = rhdr.count;

Lines 1–500 of 940.