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

📄 fs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <thread.h>#include <fcall.h>#include "pool.h"#include "playlist.h"typedef struct Wmsg Wmsg;enum {	Busy =	0x01,	Open =	0x02,	Trunc =	0x04,	Eof =	0x08,};File files[] = {[Qdir] =	{.dir = {0,0,{Qdir, 0,QTDIR},		0555|DMDIR,	0,0,0,	"."}},[Qplayctl] =	{.dir = {0,0,{Qplayctl, 0,QTFILE},	0666,		0,0,0,	"playctl"}},[Qplaylist] =	{.dir = {0,0,{Qplaylist, 0,QTFILE},	0666|DMAPPEND,	0,0,0,	"playlist"}},[Qplayvol] =	{.dir = {0,0,{Qplayvol, 0,QTFILE},	0666,		0,0,0,	"playvol"}},[Qplaystat] =	{.dir = {0,0,{Qplaystat, 0,QTFILE},	0444,		0,0,0,	"playstat"}},};Channel		*reqs;Channel		*workers;Channel		*volumechan;Channel		*playchan;Channel		*playlistreq;Playlist	playlist;int		volume[8];char *statetxt[] = {	[Nostate] =	"panic!",	[Error] =	"error",	[Stop] =	"stop",	[Pause] =	"pause",	[Play] =	"play",	[Resume] =	"resume",	[Skip] =	"skip",	nil};// low-order bits: position in play list, high-order: play state:Pmsg	playstate = {Stop, 0};char	*rflush(Worker*), *rauth(Worker*),	*rattach(Worker*), *rwalk(Worker*),	*ropen(Worker*), *rcreate(Worker*),	*rread(Worker*), *rwrite(Worker*), *rclunk(Worker*),	*rremove(Worker*), *rstat(Worker*), *rwstat(Worker*),	*rversion(Worker*);char 	*(*fcalls[])(Worker*) = {	[Tflush]	rflush,	[Tversion]	rversion,	[Tauth]		rauth,	[Tattach]	rattach,	[Twalk]		rwalk,	[Topen]		ropen,	[Tcreate]	rcreate,	[Tread]		rread,	[Twrite]	rwrite,	[Tclunk]	rclunk,	[Tremove]	rremove,	[Tstat]		rstat,	[Twstat]	rwstat,};int	messagesize = Messagesize;Fid	*fids;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	Ebadctl[] =	"unknown control message";char	Epast[] =	"reading past eof";Fid	*oldfid(int);Fid	*newfid(int);void	volumeupdater(void*);void	playupdater(void*);char *playerror;static intlookup(char *cmd, char *list[]){	int i;	for (i = 0; list[i] != nil; i++)		if (strcmp(cmd, list[i]) == 0)			return i;	return -1;}char*rversion(Worker *w){	Req *r;	Fid *f;	r = w->r;	if(r->ifcall.msize < 256)		return "max messagesize too small";	if(r->ifcall.msize < messagesize)		messagesize = r->ifcall.msize;	r->ofcall.msize = messagesize;	if(strncmp(r->ifcall.version, "9P2000", 6) != 0)		return "unknown 9P version";	else		r->ofcall.version = "9P2000";	for(f = fids; f; f = f->next)		if(f->flags & Busy)			f->flags &= ~(Open|Busy);	return nil;}char*rauth(Worker*){	return Enoauth;}char*rflush(Worker *w){	Wmsg m;	int i;	Req *r;	r = w->r;	m.cmd = Flush;	m.off = r->ifcall.oldtag;	m.arg = nil;	for(i = 1; i < nelem(files); i++)		bcastmsg(files[i].workers, &m);	if (debug & DbgWorker)		fprint(2, "flush done on tag %d\n", r->ifcall.oldtag);	return 0;}char*rattach(Worker *w){	Fid *f;	Req *r;	r = w->r;	r->fid = newfid(r->ifcall.fid);	f = r->fid;	f->flags |= Busy;	f->file = &files[Qdir];	r->ofcall.qid = f->file->dir.qid;	if(!aflag && strcmp(r->ifcall.uname, user) != 0)		return Eperm;	return 0;}static Fid*doclone(Fid *f, int nfid){	Fid *nf;	nf = newfid(nfid);	if(nf->flags & Busy)		return nil;	nf->flags |= Busy;	nf->flags &= ~(Open);	nf->file = f->file;	return nf;}char*dowalk(Fid *f, char *name){	int t;	if (strcmp(name, ".") == 0)		return nil;	if (strcmp(name, "..") == 0){		f->file = &files[Qdir];		return nil;	}	if(f->file != &files[Qdir])		return Enotexist;	for (t = 1; t < Nqid; t++){		if(strcmp(name, files[t].dir.name) == 0){			f->file = &files[t];			return nil;		}	}	return Enotexist;}char*rwalk(Worker *w){	Fid *f, *nf;	char *rv;	int i;	File *savefile;	Req *r;	r = w->r;	r->fid = oldfid(r->ifcall.fid);	if((f = r->fid) == nil)		return Enotexist;	if(f->flags & Open)		return Eisopen;	r->ofcall.nwqid = 0;	nf = nil;	savefile = f->file;	/* clone if requested */	if(r->ifcall.newfid != r->ifcall.fid){		nf = doclone(f, r->ifcall.newfid);		if(nf == nil)			return "new fid in use";		f = nf;	}	/* if it's just a clone, return */	if(r->ifcall.nwname == 0 && nf != nil)		return nil;	/* walk each element */	rv = nil;	for(i = 0; i < r->ifcall.nwname; i++){		rv = dowalk(f, r->ifcall.wname[i]);		if(rv != nil){			if(nf != nil)					nf->flags &= ~(Open|Busy);			else				f->file = savefile;			break;		}		r->ofcall.wqid[i] = f->file->dir.qid;	}	r->ofcall.nwqid = i;	/* we only error out if no walk  */	if(i > 0)		rv = nil;	return rv;}char *ropen(Worker *w){	Fid *f, *ff;	Wmsg m;	Req *r;	r = w->r;	r->fid = oldfid(r->ifcall.fid);	if((f = r->fid) == nil)		return Enotexist;	if(f->flags & Open)		return Eisopen;	if(r->ifcall.mode != OREAD)		if((f->file->dir.mode & 0x2) == 0)			return Eperm;	if((r->ifcall.mode & OTRUNC) && f->file == &files[Qplaylist]){		playlist.nlines = 0;		playlist.ndata = 0;		free(playlist.lines);		free(playlist.data);		playlist.lines = nil;		playlist.data = nil;		f->file->dir.length = 0;		f->file->dir.qid.vers++;		/* Mark all fids for this file `Trunc'ed */		for(ff = fids; ff; ff = ff->next)			if(ff->file == &files[Qplaylist] && (ff->flags & Open))				ff->flags |= Trunc;		m.cmd = Check;		m.off = 0;		m.arg = nil;		bcastmsg(f->file->workers, &m);	}	r->ofcall.iounit = 0;	r->ofcall.qid = f->file->dir.qid;	f->flags |= Open;	return nil;}char *rcreate(Worker*){	return Eperm;}intreadtopdir(Fid*, uchar *buf, long off, int cnt, int blen){	int i, m, n;	long pos;	n = 0;	pos = 0;	for (i = 1; i < Nqid; i++){		m = convD2M(&files[i].dir, &buf[n], blen-n);		if(off <= pos){			if(m <= BIT16SZ || m > cnt)				break;			n += m;			cnt -= m;		}		pos += m;	}	return n;}char*rread(Worker *w){	Fid *f;	Req *r;	long off, cnt;	int n, i;	Wmsg m;	char *p;	r = w->r;	r->fid = oldfid(r->ifcall.fid);	if((f = r->fid) == nil)		return Enotexist;	r->ofcall.count = 0;	off = r->ifcall.offset;	cnt = r->ifcall.count;	if(cnt > messagesize - IOHDRSZ)		cnt = messagesize - IOHDRSZ;	if(f->file == &files[Qdir]){		n = readtopdir(f, r->indata, off, cnt, messagesize - IOHDRSZ);		r->ofcall.count = n;		return nil;	}	if(f->file == files + Qplaystat){		p = getplaystat(r->ofcall.data, r->ofcall.data + sizeof r->indata);		readbuf(r, r->ofcall.data, p - r->ofcall.data);		return nil;	}	m.cmd = 0;	while(f->vers == f->file->dir.qid.vers && (f->flags & Eof)){		/* Wait until file state changes (f->file->dir.qid.vers is incremented) */		m = waitmsg(w, f->file->workers);		if(m.cmd == Flush && m.off == r->ifcall.tag)			return (char*)~0;	/* no answer needed */		assert(m.cmd != Work);		yield();	}	if(f->file == files + Qplaylist){		f->flags &= ~Eof;		if((f->flags & Trunc) && r->ifcall.offset != 0){			f->flags &= ~Trunc;			return Epast;		}		f->flags &= ~Trunc;		if(r->ifcall.offset < playlist.ndata)			readbuf(r, playlist.data, playlist.ndata);		else if(r->ifcall.offset == playlist.ndata){			r->ofcall.count = 0;			/* Arrange for this fid to wait next time: */			f->vers = f->file->dir.qid.vers;			f->flags |= Eof;		}else{			/* Beyond eof, bad seek? */			return Epast;		}	}else if(f->file == files + Qplayctl){		f->flags &= ~Eof;		if(m.cmd == Error){			snprint(r->ofcall.data, sizeof r->indata, "%s %ud %q",				statetxt[m.cmd], m.off, m.arg);			free(m.arg);		}else if(f->vers == f->file->dir.qid.vers){			r->ofcall.count = 0;			/* Arrange for this fid to wait next time: */			f->flags |= Eof;			return nil;		}else{			snprint(r->ofcall.data, sizeof r->indata, "%s %ud",				statetxt[playstate.cmd], playstate.off);			f->vers = f->file->dir.qid.vers;		}		r->ofcall.count = strlen(r->ofcall.data);		if(r->ofcall.count > r->ifcall.count)			r->ofcall.count = r->ifcall.count;	}else if(f->file == files + Qplayvol){		f->flags &= ~Eof;		if(f->vers == f->file->dir.qid.vers){			r->ofcall.count = 0;			/* Arrange for this fid to wait next time: */			f->flags |= Eof;		}else{			p = seprint(r->ofcall.data, r->ofcall.data + sizeof r->indata, "volume	'");			for(i = 0; i < nelem(volume); i++){				if(volume[i] == Undef)					break;				p = seprint(p, r->ofcall.data + sizeof r->indata, "%d ", volume[i]);			}			p = seprint(p, r->ofcall.data + sizeof r->indata, "'");			r->ofcall.count = p - r->ofcall.data;			if(r->ofcall.count > r->ifcall.count)				r->ofcall.count = r->ifcall.count;			f->vers = f->file->dir.qid.vers;		}	}else		abort();	return nil;}char*rwrite(Worker *w){	long cnt, i, nf, cmd;	Pmsg newstate;	char *fields[3], *p, *q;	Wmsg m;	Fid *f;	Req *r;	r = w->r;	r->fid = oldfid(r->ifcall.fid);	if((f = r->fid) == nil)		return Enotexist;	r->ofcall.count = 0;	cnt = r->ifcall.count;	if(cnt > messagesize - IOHDRSZ)		cnt = messagesize - IOHDRSZ;

⌨️ 快捷键说明

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