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

📄 paqfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <bio.h>#include <mp.h>#include <libsec.h>#include <flate.h>#include "paqfs.h"enum{	OPERM	= 0x3,		/* mask of all permission types in open mode */	OffsetSize = 4,		/* size in bytes of an offset */};typedef struct Fid Fid;typedef struct Paq Paq;typedef struct Block Block;struct Fid{	short	busy;	short	open;	int	fid;	char	*user;	ulong	offset;		/* for directory reading */	Paq	*paq;	Fid	*next;};struct Paq{		int ref;	Paq *up;	PaqDir *dir;	Qid qid;};struct Block{	int ref;	ulong addr;	/* block byte address */	ulong age;	uchar *data;};enum{	Pexec =		1,	Pwrite = 	2,	Pread = 	4,	Pother = 	1,	Pgroup = 	8,	Powner =	64,};int	noauth;Fid	*fids;Fcall	rhdr, thdr;int 	blocksize;int 	cachesize = 20;int	mesgsize = 8*1024 + IOHDRSZ;Paq 	*root, *rootfile;Block 	*cache;ulong 	cacheage;Biobuf	*bin;Fid *	newfid(int);void	paqstat(PaqDir*, char*);void	io(int fd);void	*erealloc(void*, ulong);void	*emalloc(ulong);void 	*emallocz(ulong n);char 	*estrdup(char*);void	usage(void);ulong	getl(uchar *p);int	gets(uchar *p);char 	*getstr(uchar *p);PaqDir	*getDir(uchar*);void	getHeader(uchar *p, PaqHeader *b);void	getBlock(uchar *p, PaqBlock *b);void	getTrailer(uchar *p, PaqTrailer *b);void	init(char*, int);void	paqDirFree(PaqDir*);Qid	paqDirQid(PaqDir *d);Paq	*paqCpy(Paq *s);Paq	*paqLookup(Paq *s, char *name);void	paqFree(Paq*);Paq	*paqWalk(Paq *s, char *name);int	perm(PaqDir *s, char *user, int p);int	dirRead(Fid*, uchar*, int);Block	*blockLoad(ulong addr, int type);void	blockFree(Block*);int	checkDirSize(uchar *p, uchar *ep);int	packDir(PaqDir*, uchar*, int);int	blockRead(uchar *data, ulong addr, int type);void	readHeader(PaqHeader *hdr, char *name, DigestState *ds);void	readBlocks(char *name, DigestState *ds);void	readTrailer(PaqTrailer *tlr, char *name, DigestState *ds);char	*rflush(Fid*), *rversion(Fid*),	*rauth(Fid*), *rattach(Fid*), *rwalk(Fid*),	*ropen(Fid*), *rcreate(Fid*),	*rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),	*rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);char 	*(*fcalls[])(Fid*) = {	[Tflush]	rflush,	[Tversion]	rversion,	[Tattach]	rattach,	[Tauth]		rauth,	[Twalk]		rwalk,	[Topen]		ropen,	[Tcreate]	rcreate,	[Tread]		rread,	[Twrite]	rwrite,	[Tclunk]	rclunk,	[Tremove]	rremove,	[Tstat]		rstat,	[Twstat]	rwstat,};char	Eperm[] =	"permission denied";char	Enotdir[] =	"not a directory";char	Enoauth[] =	"authentication not required";char	Enotexist[] =	"file does not exist";char	Einuse[] =	"file in use";char	Eexist[] =	"file exists";char	Enotowner[] =	"not owner";char	Eisopen[] = 	"file already open for I/O";char	Excl[] = 	"exclusive use file already open";char	Ename[] = 	"illegal name";char	Erdonly[] = 	"read only file system";char	Ebadblock[] = 	"bad block";char	Eversion[] = 	"bad version of P9";char	Edirtoobig[] = 	"directory entry too big";int debug;voidmain(int argc, char *argv[]){	char *defmnt, *p;	int pfd[2];	int fd;	int stdio = 0;	int verify = 0;	defmnt = "/n/paq";	ARGBEGIN{	case 'c':		p = ARGF();		if(p == nil)			usage();		cachesize = atoi(p);		break;	case 'a':		noauth = 1;		break;	case 'v':		verify = 1;		break;	case 'd':		debug = 1;		break;	case 'i':		defmnt = nil;		stdio = 1;		pfd[0] = 0;		pfd[1] = 1;		break;	case 's':		defmnt = nil;		break;	case 'm':		defmnt = ARGF();		if(defmnt == nil)			usage();		break;	case 'M':		p = ARGF();		if(p == nil)			usage();		mesgsize = atoi(p);		if(mesgsize < 512)			mesgsize = 512;		if(mesgsize > 128*1024)			mesgsize = 128*1024;		break;	default:		usage();	}ARGEND	if(argc != 1)		usage();	init(argv[0], verify);		if(!stdio){		if(pipe(pfd) < 0)			sysfatal("pipe failed");		if(defmnt == 0){			fd = create("#s/paqfs", OWRITE, 0666);			if(fd < 0)				sysfatal("create of /srv/paqfs failed");			if(fprint(fd, "%d", pfd[0]) < 0)				sysfatal("writing /srv/paqfs");		}	}	if(debug)		fmtinstall('F', fcallfmt);	switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){	case -1:		sysfatal("fork");	case 0:		close(pfd[0]);		io(pfd[1]);		break;	default:		close(pfd[1]);	/* don't deadlock if child fails */		if(defmnt && mount(pfd[0], -1, defmnt, MREPL|MCREATE, "") < 0)			sysfatal("mount failed");	}	exits(0);}char*rversion(Fid*){	Fid *f;	for(f = fids; f; f = f->next)		if(f->busy)			rclunk(f);	if(rhdr.msize > mesgsize)		thdr.msize = mesgsize;	else		thdr.msize = rhdr.msize;	if(strcmp(rhdr.version, "9P2000") != 0)		return Eversion;	thdr.version = "9P2000";	return 0;}char*rauth(Fid*){	return Enoauth;}char*rflush(Fid *f){	USED(f);	return 0;}char*rattach(Fid *f){	/* no authentication! */	f->busy = 1;	f->paq = paqCpy(root);	thdr.qid = f->paq->qid;	if(rhdr.uname[0])		f->user = estrdup(rhdr.uname);	else		f->user = "none";	return 0;}char*clone(Fid *f, Fid **res){	Fid *nf;	if(f->open)		return Eisopen;	if(f->busy == 0)		return Enotexist;	nf = newfid(rhdr.newfid);	nf->busy = 1;	nf->open = 0;	nf->paq = paqCpy(f->paq);	nf->user = strdup(f->user);	*res = nf;	return 0;}char*rwalk(Fid *f){	Paq *paq, *npaq;	Fid *nf;	int nqid, nwname;	Qid qid;	char *err;	if(f->busy == 0)		return Enotexist;	nf = nil;	if(rhdr.fid != rhdr.newfid){		err = clone(f, &nf);		if(err)			return err;		f = nf;	/* walk the new fid */	}	nwname = rhdr.nwname;	/* easy case */	if(nwname == 0) {		thdr.nwqid = 0;		return 0;	}	paq = paqCpy(f->paq);	qid = paq->qid;	err = nil;	for(nqid = 0; nqid < nwname; nqid++){		if((qid.type & QTDIR) == 0){			err = Enotdir;			break;		}		if(!perm(paq->dir, f->user, Pexec)) {			err = Eperm;			break;		}		npaq = paqWalk(paq, rhdr.wname[nqid]);		if(npaq == nil) {			err = Enotexist;			break;		}		paqFree(paq);		paq = npaq;		qid = paq->qid;		thdr.wqid[nqid] = qid;	}	thdr.nwqid = nqid;	if(nqid == nwname){		/* success */		paqFree(f->paq);		f->paq = paq;		return 0;	}	paqFree(paq);	if(nf != nil)		rclunk(nf);	/* only error on the first element */	if(nqid == 0)		return err;	return 0;}char *ropen(Fid *f){	int mode, trunc;	if(f->open)		return Eisopen;	if(f->busy == 0)		return Enotexist;	mode = rhdr.mode;	if(f->paq->qid.type & QTDIR){		if(mode != OREAD)			return Eperm;		thdr.qid = f->paq->qid;		return 0;	}	if(mode & ORCLOSE)		return Erdonly;	trunc = mode & OTRUNC;	mode &= OPERM;	if(mode==OWRITE || mode==ORDWR || trunc)		return Erdonly;	if(mode==OREAD)		if(!perm(f->paq->dir, f->user, Pread))			return Eperm;	if(mode==OEXEC)		if(!perm(f->paq->dir, f->user, Pexec))			return Eperm;	thdr.qid = f->paq->qid;	f->open = 1;	return 0;}char *rcreate(Fid *f){	if(f->open)		return Eisopen;	if(f->busy == 0)		return Enotexist;	return Erdonly;}char *readdir(Fid *f){	PaqDir *pd;	uchar *p, *ep;	ulong off;	int n, cnt, i;	uchar *buf;	Block *ptr, *b;	buf = (uchar*)thdr.data;	cnt = rhdr.count;	if(rhdr.offset == 0)		f->offset = 0;	off = f->offset;	if(rootfile && f->paq == root){		if(off != 0){			rhdr.count = 0;			return nil;		}		n = packDir(rootfile->dir, buf, cnt);		rhdr.count = n;		return nil;	}	ptr = blockLoad(f->paq->dir->offset, PointerBlock);	if(ptr == nil)		return Ebadblock;	i = off/blocksize;	off -= i*blocksize;	thdr.count = 0;	b = blockLoad(getl(ptr->data + i*4), DirBlock);	while(b != nil) {		p = b->data + off;		ep = b->data + blocksize;		if(checkDirSize(p, ep)) {			pd = getDir(p);			n = packDir(pd, buf, cnt);			paqDirFree(pd);			if(n == 0) {				blockFree(b);				if(thdr.count == 0) {					blockFree(ptr);					return Edirtoobig;				}				break;			}			off += gets(p);			cnt -= n;			buf += n;			thdr.count += n;		} else {			off = 0;			i++;			blockFree(b);			b = blockLoad(getl(ptr->data + i*4), DataBlock);		}	}	f->offset = i*blocksize + off;	blockFree(ptr);	return 0;}char*rread(Fid *f){	PaqDir *pd;	uchar *buf;	vlong off;	ulong uoff;	int n, cnt, i;	Block *ptr, *b;	if(f->busy == 0)		return Enotexist;	if(f->paq->qid.type & QTDIR)		return readdir(f);	pd = f->paq->dir;	off = rhdr.offset;	buf = (uchar*)thdr.data;	cnt = rhdr.count;	thdr.count = 0;	if(off >= pd->length || cnt == 0)		return 0;	if(cnt > pd->length - off)		cnt = pd->length - off;	ptr = blockLoad(pd->offset, PointerBlock);	if(ptr == nil)		return Ebadblock;	i = off/blocksize;	uoff = off-i*blocksize;	while(cnt > 0) {		b = blockLoad(getl(ptr->data + i*4), DataBlock);		if(b == nil) {			blockFree(ptr);			return Ebadblock;		}		n = blocksize - uoff;		if(n > cnt)			n = cnt;		memmove(buf, b->data + uoff, n);		cnt -= n;		thdr.count += n;		buf += n;		uoff = 0;		i++;		blockFree(b);	}	blockFree(ptr);	return 0;}char*rwrite(Fid *f){	if(f->busy == 0)		return Enotexist;	return Erdonly;}char *rclunk(Fid *f){	f->busy = 0;	f->open = 0;	free(f->user);	paqFree(f->paq);	return 0;}char *rremove(Fid *f){	rclunk(f);	return Erdonly;}char *rstat(Fid *f){	if(f->busy == 0)		return Enotexist;	thdr.stat = (uchar*)thdr.data;	thdr.nstat = packDir(f->paq->dir, thdr.stat, mesgsize);	if(thdr.nstat == 0)		return Edirtoobig;	return 0;}char *rwstat(Fid *f){	if(f->busy == 0)		return Enotexist;	return Erdonly;}Paq*paqCpy(Paq *s){	s->ref++;	return s;}voidpaqFree(Paq *p){	if(p == nil)		return;	p->ref--;	if(p->ref > 0)		return;assert(p != root);	paqFree(p->up);	paqDirFree(p->dir);	free(p);}void

⌨️ 快捷键说明

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