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

📄 consolefs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	}}int dbmtime;/* *  a request processor (one per Fs) */voidfsrun(void *v){	int n, t;	Request *r;	Fid *f;	Dir *d;	void **a = v;	Fs* fs;	int *pfd;	fs = a[0];	pfd = a[1];	fs->fd = pfd[0];	for(;;){		d = dirstat(consoledb);		if(d != nil && d->mtime != dbmtime){			dbmtime = d->mtime;			readdb(fs);		}		free(d);		r = allocreq(fs, messagesize);		n = read9pmsg(fs->fd, r->buf, messagesize);		if(n <= 0)			fatal("unmounted");		if(convM2S(r->buf, n, &r->f) == 0){			fprint(2, "can't convert %ux %ux %ux\n", r->buf[0],				r->buf[1], r->buf[2]);			free(r);			continue;		}		f = fsgetfid(fs, r->f.fid);		r->fid = f;		if(debug)			fprint(2, "%F path %llux\n", &r->f, f->qid.path);		t = r->f.type;		r->f.type++;		(*fcall[t])(fs, r, f);	}}Fid*fsgetfid(Fs *fs, int fid){	Fid *f, *nf;	lock(fs);	for(f = fs->hash[fid%Nhash]; f; f = f->next){		if(f->fid == fid){			f->ref++;			unlock(fs);			return f;		}	}	nf = emalloc(sizeof(Fid));	nf->next = fs->hash[fid%Nhash];	fs->hash[fid%Nhash] = nf;	nf->fid = fid;	nf->ref = 1;	nf->wp = nf->buf;	nf->rp = nf->wp;	unlock(fs);	return nf;}voidfsputfid(Fs *fs, Fid *f){	Fid **l, *nf;	lock(fs);	if(--f->ref > 0){		unlock(fs);		return;	}	for(l = &fs->hash[f->fid%Nhash]; nf = *l; l = &nf->next)		if(nf == f){			*l = f->next;			break;		}	unlock(fs);	free(f->user);	free(f);}voidfsauth(Fs *fs, Request *r, Fid*){	fsreply(fs, r, "consolefs: authentication not required");}voidfsversion(Fs *fs, Request *r, Fid*){	if(r->f.msize < 256){		fsreply(fs, r, "message size too small");		return;	}	messagesize = r->f.msize;	if(messagesize > 8192+IOHDRSZ)		messagesize = 8192+IOHDRSZ;	r->f.msize = messagesize;	if(strncmp(r->f.version, "9P2000", 6) != 0){		fsreply(fs, r, "unrecognized 9P version");		return;	}	r->f.version = "9P2000";	fsreply(fs, r, nil);}voidfsflush(Fs *fs, Request *r, Fid *f){	Request *or;	or = remtag(&f->r, r->f.oldtag);	if(or != nil){		fsputfid(fs, or->fid);		free(or);	}	fsreply(fs, r, nil);}voidfsattach(Fs *fs, Request *r, Fid *f){	f->qid.type = QTDIR;	f->qid.path = QID(0, Ttopdir);	f->qid.vers = 0;	if(r->f.uname[0])		f->user = strdup(r->f.uname);	else		f->user = strdup("none");	/* hold down the fid till the clunk */	f->attached = 1;	lock(fs);	f->ref++;	unlock(fs);	r->f.qid = f->qid;	fsreply(fs, r, nil);}voidfswalk(Fs *fs, Request *r, Fid *f){	char *name;	Dir d;	int i, n, nqid, nwname;	Qid qid, wqid[MAXWELEM];	Fid *nf;	char *err;	if(f->attached == 0){		fsreply(fs, r, Enofid);		return;	}	nf = nil;	if(r->f.fid != r->f.newfid){		nf = fsgetfid(fs, r->f.newfid);		nf->attached = f->attached;		nf->open = f->open;		nf->qid = f->qid;		nf->user = strdup(f->user);		nf->c = f->c;		nf->wp = nf->buf;		nf->rp = nf->wp;		f = nf;	}	qid = f->qid;	err = nil;	nwname = r->f.nwname;	nqid = 0;	if(nwname > 0){		for(; err == nil && nqid < nwname; nqid++){			if(nqid >= MAXWELEM){				err = "too many name elements";				break;			}			name = r->f.wname[nqid];			if(strcmp(name, "..") == 0)				qid = parentqid(qid);			else if(strcmp(name, ".") != 0){				for(i = 0; ; i++){					n = fsdirgen(fs, qid, i, &d, nil, 0);					if(n < 0){						err = Eexist;						break;					}					if(n > 0 && strcmp(name, d.name) == 0){						qid = d.qid;						break;					}				}			}			wqid[nqid] = qid;		}		if(nf != nil && nqid < nwname)			fsputfid(fs, nf);		if(nqid == nwname)			f->qid = qid;	}	memmove(r->f.wqid, wqid, nqid*sizeof(Qid));	r->f.nwqid = nqid;	fsreply(fs, r, err);}intingroup(char *user, char *group){	Ndbtuple *t, *nt;	Ndbs s;	t = ndbsearch(db, &s, "group", group);	if(t == nil)		return 0;	for(nt = t; nt; nt = nt->entry){		if(strcmp(nt->attr, "uid") == 0)		if(strcmp(nt->val, user) == 0)			break;	}	ndbfree(t);	return nt != nil;}intuserok(char *u, char *cname){	Ndbtuple *t, *nt;	Ndbs s;	t = ndbsearch(db, &s, "console", cname);	if(t == nil)		return 0;	for(nt = t; nt; nt = nt->entry){		if(strcmp(nt->attr, "uid") == 0)		if(strcmp(nt->val, u) == 0)			break;		if(strcmp(nt->attr, "gid") == 0)		if(ingroup(u, nt->val))			break;	}	ndbfree(t);	return nt != nil;}int m2p[] ={	[OREAD]		4,	[OWRITE]	2,	[ORDWR]		6};/* *  broadcast a message to all listeners */voidbcastmsg(Fs *fs, Console *c, char *msg, int n){	Fid *fl;	for(fl = c->flist; fl; fl = fl->cnext){		fromconsole(fl, msg, n);		fskick(fs, fl);	}}voidfsopen(Fs *fs, Request *r, Fid *f){	int mode;	Console *c;	if(f->attached == 0){		fsreply(fs, r, Enofid);		return;	}	if(f->open){		fsreply(fs, r, Eisopen);		return;	}	mode = r->f.mode & 3;	if((QTDIR & f->qid.type) && mode != OREAD){		fsreply(fs, r, Eperm);		return;	}	switch(TYPE(f->qid)){	case Qdata:		c = fs->cons[CONS(f->qid)];		if(!userok(f->user, c->name)){			fsreply(fs, r, Eperm);			return;		}		f->rp = f->buf;		f->wp = f->buf;		f->c = c;		lock(c);		sprint(f->mbuf, "[%s] ", f->user);		f->bufn = strlen(f->mbuf);		f->used = 0;		f->cnext = c->flist;		c->flist = f;		bcastmembers(fs, c, "+", f);		if(c->pid == 0)			fsreopen(fs, c);		unlock(c);		break;	case Qctl:		c = fs->cons[CONS(f->qid)];		if(!userok(f->user, c->name)){			fsreply(fs, r, Eperm);			return;		}		f->c = c;		break;	case Qstat:		c = fs->cons[CONS(f->qid)];		if(!userok(f->user, c->name)){			fsreply(fs, r, Eperm);			return;		}		f->c = c;		break;	}	f->open = 1;	r->f.iounit = messagesize-IOHDRSZ;	r->f.qid = f->qid;	fsreply(fs, r, nil);}voidfscreate(Fs *fs, Request *r, Fid*){	fsreply(fs, r, Eperm);}voidfsread(Fs *fs, Request *r, Fid *f){	uchar *p, *e;	int i, m, off;	vlong offset;	Dir d;	char sbuf[ERRMAX];	if(f->attached == 0){		fsreply(fs, r, Enofid);		return;	}	if((int)r->f.count < 0){		fsreply(fs, r, Ebadcount);		return;	}	if(QTDIR & f->qid.type){		p = r->buf + IOHDRSZ;		e = p + r->f.count;		offset = r->f.offset;		off = 0;		for(i=0; p<e; i++, off+=m){			m = fsdirgen(fs, f->qid, i, &d, p, e-p);			if(m < 0)				break;			if(m > BIT16SZ && off >= offset)				p += m;		}		r->f.data = (char*)r->buf + IOHDRSZ;		r->f.count = (char*)p - r->f.data;	} else {		switch(TYPE(f->qid)){		case Qdata:			addreq(&f->r, r);			fskick(fs, f);			return;		case Qctl:			r->f.data = (char*)r->buf+IOHDRSZ;			r->f.count = 0;			break;		case Qstat:			if(r->f.count > sizeof(sbuf))				r->f.count = sizeof(sbuf);			i = pread(f->c->sfd, sbuf, r->f.count, r->f.offset);			if(i < 0){				errstr(sbuf, sizeof sbuf);				fsreply(fs, r, sbuf);				return;			}			r->f.data = sbuf;			r->f.count = i;			break;		default:			fsreply(fs, r, Eexist);			return;		}	}	fsreply(fs, r, nil);}voidfswrite(Fs *fs, Request *r, Fid *f){	int i, eol = 0;	if(f->attached == 0){		fsreply(fs, r, Enofid);		return;	}	if((int)r->f.count < 0){		fsreply(fs, r, Ebadcount);		return;	}	if(QTDIR & f->qid.type){		fsreply(fs, r, Eperm);		return;	}	switch(TYPE(f->qid)){	default:		fsreply(fs, r, Eperm);		return;	case Qctl:		write(f->c->cfd, r->f.data, r->f.count);		break;	case Qdata:		for(i = 0; i < r->f.count; i++){			if(r->f.data[i] == '\n'){				if(f->c->chat && f->used)					eol = 1;				if(f->c->cronly)					r->f.data[i] = '\r';			}			else				f->used = 1;		}		if(f->c->chat){			fskick(fs, f);			if(!f->used)				break;				if(f->bufn + r->f.count > Bufsize){				r->f.count -= (f->bufn + r->f.count) % Bufsize;				eol = 1;			}			strncat(f->mbuf, r->f.data, r->f.count);			f->bufn += r->f.count;			if(eol){				bcastmsg(fs, f->c, f->mbuf, f->bufn);				sprint(f->mbuf, "[%s] ", f->user);				f->bufn = strlen(f->mbuf);				f->used = 0;			}		}		else			write(f->c->fd, r->f.data, r->f.count);		break;	}	fsreply(fs, r, nil);}voidfsclunk(Fs *fs, Request *r, Fid *f){	Fid **l, *fl;	Request *nr;	if(f->open && TYPE(f->qid) == Qdata){		while((nr = remreq(&f->r)) != nil){			fsputfid(fs, f);			free(nr);		}		lock(f->c);		for(l = &f->c->flist; *l; l = &fl->cnext){			fl = *l;			if(fl == f){				*l = fl->cnext;				break;			}		}		bcastmembers(fs, f->c, "-", f);		if(f->c->ondemand && f->c->flist == nil)			fsreopen(fs, f->c);		unlock(f->c);	}	fsreply(fs, r, nil);	fsputfid(fs, f);}voidfsremove(Fs *fs, Request *r, Fid*){	fsreply(fs, r, Eperm);}voidfsstat(Fs *fs, Request *r, Fid *f){	int i, n;	Qid q;	Dir d;	q = parentqid(f->qid);	for(i = 0; ; i++){		r->f.stat = r->buf+IOHDRSZ;		n = fsdirgen(fs, q, i, &d, r->f.stat, messagesize-IOHDRSZ);		if(n < 0){			fsreply(fs, r, Eexist);			return;		}		r->f.nstat = n;		if(r->f.nstat > BIT16SZ && d.qid.path == f->qid.path)			break;	}	fsreply(fs, r, nil);}voidfswstat(Fs *fs, Request *r, Fid*){	fsreply(fs, r, Eperm);}voidfsreply(Fs *fs, Request *r, char *err){	int n;	uchar buf[8192+IOHDRSZ];	if(err){		r->f.type = Rerror;		r->f.ename = err;	}	n = convS2M(&r->f, buf, messagesize);	if(debug)		fprint(2, "%F path %llux n=%d\n", &r->f, r->fid->qid.path, n);	fsputfid(fs, r->fid);	if(write(fs->fd, buf, n) != n)		fatal("unmounted");	free(r);}/* *  called whenever input or a read request has been received */voidfskick(Fs *fs, Fid *f){	Request *r;	char *p, *rp, *wp, *ep;	int i;	lock(f);	while(f->rp != f->wp){		r = remreq(&f->r);		if(r == nil)			break;		p = (char*)r->buf;		rp = f->rp;		wp = f->wp;		ep = &f->buf[Bufsize];		for(i = 0; i < r->f.count && rp != wp; i++){			*p++ = *rp++;			if(rp >= ep)				rp = f->buf;		}		f->rp = rp;		r->f.data = (char*)r->buf;		r->f.count = p - (char*)r->buf;		fsreply(fs, r, nil);	}	unlock(f);}voidusage(void){	fprint(2, "usage: consolefs [-d] [-m mount-point] [-c console-db]\n");	threadexitsall("usage");}voidthreadmain(int argc, char **argv){	fmtinstall('F', fcallfmt);	ARGBEGIN{	case 'd':		debug++;		break;	case 'c':		consoledb = ARGF();		if(consoledb == nil)			usage();		break;	case 'm':		mntpt = ARGF();		if(mntpt == nil)			usage();		break;	}ARGEND;	db = ndbopen(consoledb);	if(db == nil) 		fatal("can't open %s: %r", consoledb);	fsmount(mntpt);}

⌨️ 快捷键说明

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