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

📄 fsys.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	}}static voidhold(Plumbmsg *m, Dirtab *d){	Holdq *h, *q;	h = emalloc(sizeof(Holdq));	h->msg = m;	/* add to end of queue */	if(d->holdq == nil)		d->holdq = h;	else{		for(q=d->holdq; q->next!=nil; q=q->next)			;		q->next = h;	}}static voidqueueheld(Dirtab *d){	Holdq *h;	while(d->holdq != nil){		h = d->holdq;		d->holdq = h->next;		queuesend(d, h->msg);		/* no need to drain queue because we know no-one is reading yet */		free(h);	}}static voiddispose(Fcall *t, uchar *buf, Plumbmsg *m, Ruleset *rs, Exec *e){	int i;	char *err;	qlock(&queue);	err = nil;	if(m->dst==nil || m->dst[0]=='\0'){		err = Enoport;		if(rs != nil)			err = startup(rs, e);		plumbfree(m);	}else		for(i=NQID; i<ndir; i++)			if(strcmp(m->dst, dir[i].name) == 0){				if(dir[i].nopen == 0){					err = startup(rs, e);					if(e!=nil && e->holdforclient)						hold(m, &dir[i]);					else						plumbfree(m);				}else{					queuesend(&dir[i], m);					drainqueue(&dir[i]);				}				break;			}	freeexec(e);	qunlock(&queue);	fsysrespond(t, buf, err);	free(t);}static Fcall*fsysversion(Fcall *t, uchar *buf, Fid*){	if(t->msize < 256){		fsysrespond(t, buf, "version: message size too small");		return t;	}	if(t->msize < messagesize)		messagesize = t->msize;	t->msize = messagesize;	if(strncmp(t->version, "9P2000", 6) != 0){		fsysrespond(t, buf, "unrecognized 9P version");		return t;	}	t->version = "9P2000";	fsysrespond(t, buf, nil);	return t;}static Fcall*fsysauth(Fcall *t, uchar *buf, Fid*){	fsysrespond(t, buf, "plumber: authentication not required");	return t;}static Fcall*fsysattach(Fcall *t, uchar *buf, Fid *f){	Fcall out;	if(strcmp(t->uname, user) != 0){		fsysrespond(&out, buf, Eperm);		return t;	}	f->busy = 1;	f->open = 0;	f->qid.type = QTDIR;	f->qid.path = Qdir;	f->qid.vers = 0;	f->dir = dir;	memset(&out, 0, sizeof(Fcall));	out.type = t->type;	out.tag = t->tag;	out.fid = f->fid;	out.qid = f->qid;	fsysrespond(&out, buf, nil);	return t;}static Fcall*fsysflush(Fcall *t, uchar *buf, Fid*){	int i;	qlock(&queue);	for(i=NQID; i<ndir; i++)		flushqueue(&dir[i], t->oldtag);	qunlock(&queue);	fsysrespond(t, buf, nil);	return t;}static Fcall*fsyswalk(Fcall *t, uchar *buf, Fid *f){	Fcall out;	Fid *nf;	ulong path;	Dirtab *d, *dir;	Qid q;	int i;	uchar type;	char *err;	if(f->open){		fsysrespond(t, buf, "clone of an open fid");		return t;	}	nf = nil;	if(t->fid  != t->newfid){		nf = newfid(t->newfid);		if(nf->busy){			fsysrespond(t, buf, "clone to a busy fid");			return t;		}		nf->busy = 1;		nf->open = 0;		nf->dir = f->dir;		nf->qid = f->qid;		f = nf;	/* walk f */	}	out.nwqid = 0;	err = nil;	dir = f->dir;	q = f->qid;	if(t->nwname > 0){		for(i=0; i<t->nwname; i++){			if((q.type & QTDIR) == 0){				err = Enotdir;				break;			}			if(strcmp(t->wname[i], "..") == 0){				type = QTDIR;				path = Qdir;	Accept:				q.type = type;				q.vers = 0;				q.path = path;				out.wqid[out.nwqid++] = q;				continue;			}			d = dir;			d++;	/* skip '.' */			for(; d->name; d++)				if(strcmp(t->wname[i], d->name) == 0){					type = d->type;					path = d->qid;					dir = d;					goto Accept;				}			err = Enoexist;			break;		}	}	out.type = t->type;	out.tag = t->tag;	if(err!=nil || out.nwqid<t->nwname){		if(nf)			nf->busy = 0;	}else if(out.nwqid == t->nwname){		f->qid = q;		f->dir = dir;	}	fsysrespond(&out, buf, err);	return t;}static Fcall*fsysopen(Fcall *t, uchar *buf, Fid *f){	int m, clearrules, mode;	clearrules = 0;	if(t->mode & OTRUNC){		if(f->qid.path != Qrules)			goto Deny;		clearrules = 1;	}	/* can't truncate anything, so just disregard */	mode = t->mode & ~(OTRUNC|OCEXEC);	/* can't execute or remove anything */	if(mode==OEXEC || (mode&ORCLOSE))		goto Deny;	switch(mode){	default:		goto Deny;	case OREAD:		m = 0400;		break;	case OWRITE:		m = 0200;		break;	case ORDWR:		m = 0600;		break;	}	if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)		goto Deny;	if(f->qid.path==Qrules && (mode==OWRITE || mode==ORDWR)){		lock(&rulesref);		if(rulesref.ref++ != 0){			rulesref.ref--;			unlock(&rulesref);			fsysrespond(t, buf, Einuse);			return t;		}		unlock(&rulesref);	}	if(clearrules){		writerules(nil, 0);		rules[0] = nil;	}	t->qid = f->qid;	t->iounit = 0;	qlock(&queue);	f->mode = mode;	f->open = 1;	f->dir->nopen++;	f->nextopen = f->dir->fopen;	f->dir->fopen = f;	queueheld(f->dir);	qunlock(&queue);	fsysrespond(t, buf, nil);	return t;    Deny:	fsysrespond(t, buf, Eperm);	return t;}static Fcall*fsyscreate(Fcall *t, uchar *buf, Fid*){	fsysrespond(t, buf, Eperm);	return t;}static Fcall*fsysreadrules(Fcall *t, uchar *buf){	char *p;	int n;	p = printrules();	n = strlen(p);	t->data = p;	if(t->offset >= n)		t->count = 0;	else{		t->data = p+t->offset;		if(t->offset+t->count > n)			t->count = n-t->offset;	}	fsysrespond(t, buf, nil);	free(p);	return t;}static Fcall*fsysread(Fcall *t, uchar *buf, Fid *f){	uchar *b;	int i, n, o, e;	uint len;	Dirtab *d;	uint clock;	if(f->qid.path != Qdir){		if(f->qid.path == Qrules)			return fsysreadrules(t, buf);		/* read from port */		if(f->qid.path < NQID){			fsysrespond(t, buf, "internal error: unknown read port");			return t;		}		qlock(&queue);		queueread(f->dir, t, buf, f);		drainqueue(f->dir);		qunlock(&queue);		return nil;	}	o = t->offset;	e = t->offset+t->count;	clock = getclock();	b = malloc(messagesize-IOHDRSZ);	if(b == nil){		fsysrespond(t, buf, Enomem);		return t;	}	n = 0;	d = dir;	d++;	/* first entry is '.' */	for(i=0; d->name!=nil && i<e; i+=len){		len = dostat(d, b+n, messagesize-IOHDRSZ-n, clock);		if(len <= BIT16SZ)			break;		if(i >= o)			n += len;		d++;	}	t->data = (char*)b;	t->count = n;	fsysrespond(t, buf, nil);	free(b);	return t;}static Fcall*fsyswrite(Fcall *t, uchar *buf, Fid *f){	Plumbmsg *m;	int i, n;	long count;	char *data;	Exec *e;	switch((int)f->qid.path){	case Qdir:		fsysrespond(t, buf, Eisdir);		return t;	case Qrules:		clock = getclock();		fsysrespond(t, buf, writerules(t->data, t->count));		return t;	case Qsend:		if(f->offset == 0){			data = t->data;			count = t->count;		}else{			/* partial message already assembled */			f->writebuf = erealloc(f->writebuf, f->offset + t->count);			memmove(f->writebuf+f->offset, t->data, t->count);			data = f->writebuf;			count = f->offset+t->count;		}		m = plumbunpackpartial(data, count, &n);		if(m == nil){			if(n == 0){				f->offset = 0;				free(f->writebuf);				f->writebuf = nil;				fsysrespond(t, buf, Ebadmsg);				return t;			}			/* can read more... */			if(f->offset == 0){				f->writebuf = emalloc(t->count);				memmove(f->writebuf, t->data, t->count);			}			/* else buffer has already been grown */			f->offset += t->count;			fsysrespond(t, buf, nil);			return t;		}		/* release partial buffer */		f->offset = 0;		free(f->writebuf);		f->writebuf = nil;		for(i=0; rules[i]; i++)			if((e=matchruleset(m, rules[i])) != nil){				dispose(t, buf, m, rules[i], e);				return nil;			}		if(m->dst != nil){			dispose(t, buf, m, nil, nil);			return nil;		}		fsysrespond(t, buf, "no matching plumb rule");		return t;	}	fsysrespond(t, buf, "internal error: write to unknown file");	return t;}static Fcall*fsysstat(Fcall *t, uchar *buf, Fid *f){	t->stat = emalloc(messagesize-IOHDRSZ);	t->nstat = dostat(f->dir, t->stat, messagesize-IOHDRSZ, clock);	fsysrespond(t, buf, nil);	free(t->stat);	t->stat = nil;	return t;}static Fcall*fsyswstat(Fcall *t, uchar *buf, Fid*){	fsysrespond(t, buf, Eperm);	return t;}static Fcall*fsysremove(Fcall *t, uchar *buf, Fid*){	fsysrespond(t, buf, Eperm);	return t;}static Fcall*fsysclunk(Fcall *t, uchar *buf, Fid *f){	Fid *prev, *p;	Dirtab *d;	qlock(&queue);	if(f->open){		d = f->dir;		d->nopen--;		if(d->qid==Qrules && (f->mode==OWRITE || f->mode==ORDWR)){			/*			 * just to be sure last rule is parsed; error messages will be lost, though,			 * unless last write ended with a blank line			 */			writerules(nil, 0);			lock(&rulesref);			rulesref.ref--;			unlock(&rulesref);		}		prev = nil;		for(p=d->fopen; p; p=p->nextopen){			if(p == f){				if(prev)					prev->nextopen = f->nextopen;				else					d->fopen = f->nextopen;				removesenders(d, f);				break;			}			prev = p;		}	}	f->busy = 0;	f->open = 0;	f->offset = 0;	if(f->writebuf != nil){		free(f->writebuf);		f->writebuf = nil;	}	qunlock(&queue);	fsysrespond(t, buf, nil);	return t;}

⌨️ 快捷键说明

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