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

📄 ramfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>/* * Rather than reading /adm/users, which is a lot of work for * a toy program, we assume all groups have the form *	NNN:user:user: * meaning that each user is the leader of his own group. */enum{	OPERM	= 0x3,		/* mask of all permission types in open mode */	Nram	= 2048,	Maxsize	= 768*1024*1024,	Maxfdata	= 8192,};typedef struct Fid Fid;typedef struct Ram Ram;struct Fid{	short	busy;	short	open;	short	rclose;	int	fid;	Fid	*next;	char	*user;	Ram	*ram;};struct Ram{	short	busy;	short	open;	long	parent;		/* index in Ram array */	Qid	qid;	long	perm;	char	*name;	ulong	atime;	ulong	mtime;	char	*user;	char	*group;	char	*muid;	char	*data;	long	ndata;};enum{	Pexec =		1,	Pwrite = 	2,	Pread = 	4,	Pother = 	1,	Pgroup = 	8,	Powner =	64,};ulong	path;		/* incremented for each new file */Fid	*fids;Ram	ram[Nram];int	nram;int	mfd[2];char	*user;uchar	mdata[IOHDRSZ+Maxfdata];uchar	rdata[Maxfdata];	/* buffer for data in reply */uchar statbuf[STATMAX];Fcall thdr;Fcall	rhdr;int	messagesize = sizeof mdata;Fid *	newfid(int);uint	ramstat(Ram*, uchar*, uint);void	error(char*);void	io(void);void	*erealloc(void*, ulong);void	*emalloc(ulong);char	*estrdup(char*);void	usage(void);int	perm(Fid*, Ram*, int);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*);int needfid[] = {	[Tversion] 0,	[Tflush] 0,	[Tauth] 0,	[Tattach] 0,	[Twalk] 1,	[Topen] 1,	[Tcreate] 1,	[Tread] 1,	[Twrite] 1,	[Tclunk] 1,	[Tremove] 1,	[Tstat] 1,	[Twstat] 1,};char 	*(*fcalls[])(Fid*) = {	[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	Eperm[] =	"permission denied";char	Enotdir[] =	"not a directory";char	Enoauth[] =	"ramfs: authentication not required";char	Enotexist[] =	"file does not exist";char	Einuse[] =	"file in use";char	Eexist[] =	"file exists";char	Eisdir[] =	"file is a directory";char	Enotowner[] =	"not owner";char	Eisopen[] = 	"file already open for I/O";char	Excl[] = 	"exclusive use file already open";char	Ename[] = 	"illegal name";char	Eversion[] =	"unknown 9P version";char	Enotempty[] =	"directory not empty";int debug;int private;voidnotifyf(void *a, char *s){	USED(a);	if(strncmp(s, "interrupt", 9) == 0)		noted(NCONT);	noted(NDFLT);}voidmain(int argc, char *argv[]){	Ram *r;	char *defmnt;	int p[2];	int fd;	int stdio = 0;	char *service;	service = "ramfs";	defmnt = "/tmp";	ARGBEGIN{	case 'D':		debug = 1;		break;	case 'i':		defmnt = 0;		stdio = 1;		mfd[0] = 0;		mfd[1] = 1;		break;	case 's':		defmnt = 0;		break;	case 'm':		defmnt = EARGF(usage());		break;	case 'p':		private++;		break;	case 'S':		defmnt = 0;		service = EARGF(usage());		break;	default:		usage();	}ARGEND	if(pipe(p) < 0)		error("pipe failed");	if(!stdio){		mfd[0] = p[0];		mfd[1] = p[0];		if(defmnt == 0){			char buf[64];			snprint(buf, sizeof buf, "#s/%s", service);			fd = create(buf, OWRITE|ORCLOSE, 0666);			if(fd < 0)				error("create failed");			sprint(buf, "%d", p[1]);			if(write(fd, buf, strlen(buf)) < 0)				error("writing service file");		}	}	user = getuser();	notify(notifyf);	nram = 1;	r = &ram[0];	r->busy = 1;	r->data = 0;	r->ndata = 0;	r->perm = DMDIR | 0775;	r->qid.type = QTDIR;	r->qid.path = 0LL;	r->qid.vers = 0;	r->parent = 0;	r->user = user;	r->group = user;	r->muid = user;	r->atime = time(0);	r->mtime = r->atime;	r->name = estrdup(".");	if(debug)		fmtinstall('F', fcallfmt);	switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){	case -1:		error("fork");	case 0:		close(p[1]);		io();		break;	default:		close(p[0]);	/* don't deadlock if child fails */		if(defmnt && mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0)			error("mount failed");	}	exits(0);}char*rversion(Fid*){	Fid *f;	for(f = fids; f; f = f->next)		if(f->busy)			rclunk(f);	if(thdr.msize > sizeof mdata)		rhdr.msize = sizeof mdata;	else		rhdr.msize = thdr.msize;	messagesize = rhdr.msize;	if(strncmp(thdr.version, "9P2000", 6) != 0)		return Eversion;	rhdr.version = "9P2000";	return 0;}char*rauth(Fid*){	return "ramfs: no authentication required";}char*rflush(Fid *f){	USED(f);	return 0;}char*rattach(Fid *f){	/* no authentication! */	f->busy = 1;	f->rclose = 0;	f->ram = &ram[0];	rhdr.qid = f->ram->qid;	if(thdr.uname[0])		f->user = estrdup(thdr.uname);	else		f->user = "none";	if(strcmp(user, "none") == 0)		user = f->user;	return 0;}char*clone(Fid *f, Fid **nf){	if(f->open)		return Eisopen;	if(f->ram->busy == 0)		return Enotexist;	*nf = newfid(thdr.newfid);	(*nf)->busy = 1;	(*nf)->open = 0;	(*nf)->rclose = 0;	(*nf)->ram = f->ram;	(*nf)->user = f->user;	/* no ref count; the leakage is minor */	return 0;}char*rwalk(Fid *f){	Ram *r, *fram;	char *name;	Ram *parent;	Fid *nf;	char *err;	ulong t;	int i;	err = nil;	nf = nil;	rhdr.nwqid = 0;	if(thdr.newfid != thdr.fid){		err = clone(f, &nf);		if(err)			return err;		f = nf;	/* walk the new fid */	}	fram = f->ram;	if(thdr.nwname > 0){		t = time(0);		for(i=0; i<thdr.nwname && i<MAXWELEM; i++){			if((fram->qid.type & QTDIR) == 0){				err = Enotdir; 				break;			}			if(fram->busy == 0){				err = Enotexist;				break;			}			fram->atime = t;			name = thdr.wname[i];			if(strcmp(name, ".") == 0){    Found:				rhdr.nwqid++;				rhdr.wqid[i] = fram->qid;				continue;			}			parent = &ram[fram->parent];			if(!perm(f, parent, Pexec)){				err = Eperm;				break;			}			if(strcmp(name, "..") == 0){				fram = parent;				goto Found;			}			for(r=ram; r < &ram[nram]; r++)				if(r->busy && r->parent==fram-ram && strcmp(name, r->name)==0){					fram = r;					goto Found;				}			break;		}		if(i==0 && err == nil)			err = Enotexist;	}	if(nf != nil && (err!=nil || rhdr.nwqid<thdr.nwname)){		/* clunk the new fid, which is the one we walked */		f->busy = 0;		f->ram = nil;	}	if(rhdr.nwqid > 0)		err = nil;	/* didn't get everything in 9P2000 right! */	if(rhdr.nwqid == thdr.nwname)	/* update the fid after a successful walk */		f->ram = fram;	return err;}char *ropen(Fid *f){	Ram *r;	int mode, trunc;	if(f->open)		return Eisopen;	r = f->ram;	if(r->busy == 0)		return Enotexist;	if(r->perm & DMEXCL)		if(r->open)			return Excl;	mode = thdr.mode;	if(r->qid.type & QTDIR){		if(mode != OREAD)			return Eperm;		rhdr.qid = r->qid;		return 0;	}	if(mode & ORCLOSE){		/* can't remove root; must be able to write parent */		if(r->qid.path==0 || !perm(f, &ram[r->parent], Pwrite))			return Eperm;		f->rclose = 1;	}	trunc = mode & OTRUNC;	mode &= OPERM;	if(mode==OWRITE || mode==ORDWR || trunc)		if(!perm(f, r, Pwrite))			return Eperm;	if(mode==OREAD || mode==ORDWR)		if(!perm(f, r, Pread))			return Eperm;	if(mode==OEXEC)		if(!perm(f, r, Pexec))			return Eperm;	if(trunc && (r->perm&DMAPPEND)==0){		r->ndata = 0;		if(r->data)			free(r->data);		r->data = 0;		r->qid.vers++;	}	rhdr.qid = r->qid;	rhdr.iounit = messagesize-IOHDRSZ;	f->open = 1;	r->open++;	return 0;}char *rcreate(Fid *f){	Ram *r;	char *name;	long parent, prm;	if(f->open)		return Eisopen;	if(f->ram->busy == 0)		return Enotexist;	parent = f->ram - ram;	if((f->ram->qid.type&QTDIR) == 0)		return Enotdir;	/* must be able to write parent */	if(!perm(f, f->ram, Pwrite))		return Eperm;	prm = thdr.perm;

⌨️ 快捷键说明

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