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

📄 9p1.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"all.h"#include	"9p1.h"extern Nvrsafe	nvr;typedef struct {	uchar	chal[CHALLEN];		/* locally generated challenge */	uchar	rchal[CHALLEN];		/* remotely generated challenge */	Lock	idlock;	ulong	idoffset;		/* offset of id vector */	ulong	idvec;			/* vector of acceptable id's */} Authinfo;static voidf_nop(Chan *cp, Fcall*, Fcall*){	if(CHAT(cp))		print("c_nop %d\n", cp->chan);}static voidf_flush(Chan *cp, Fcall*, Fcall*){	if(CHAT(cp))		print("c_flush %d\n", cp->chan);	runlock(&cp->reflock);	wlock(&cp->reflock);	wunlock(&cp->reflock);	rlock(&cp->reflock);}/* *  create a challenge for a fid space */static voidmkchallenge(Authinfo *aip){	int i;	srand((ulong)aip + m->ticks);	for(i = 0; i < CHALLEN; i++)		aip->chal[i] = nrand(256);	aip->idoffset = 0;	aip->idvec = 0;}static voidf_session(Chan *cp, Fcall *in, Fcall *ou){	Authinfo *aip;	aip = (Authinfo*)cp->authinfo;	if(CHAT(cp))		print("c_session %d\n", cp->chan);	memmove(aip->rchal, in->chal, sizeof(aip->rchal));	mkchallenge(aip);	memmove(ou->chal, aip->chal, sizeof(ou->chal));	if(noauth || wstatallow)		memset(ou->authid, 0, sizeof(ou->authid));	else		memmove(ou->authid, nvr.authid, sizeof(ou->authid));	sprint(ou->authdom, "%s.%s", service, nvr.authdom);	fileinit(cp);}/* *  match a challenge from an attach */static intauthorize(Chan *cp, Fcall *in, Fcall *ou){	Ticket t;	Authenticator a;	int x;	ulong bit;	Authinfo *aip;	if(noauth || wstatallow)	/* set to allow entry during boot */		return 1;	if(strcmp(in->uname, "none") == 0)		return 1;	if(in->type == Toattach)		return 0;	/* decrypt and unpack ticket */	convM2T9p1(in->ticket, &t, nvr.authkey);	if(t.num != AuthTs){		print("9p1: bad AuthTs num\n");		return 0;	}	/* decrypt and unpack authenticator */	convM2A9p1(in->auth, &a, t.key);	if(a.num != AuthAc){		print("9p1: bad AuthAc num\n");		return 0;	}	/* challenges must match */	aip = (Authinfo*)cp->authinfo;	if(memcmp(a.chal, aip->chal, sizeof(a.chal)) != 0){		print("9p1: bad challenge\n");		return 0;	}	/*	 *  the id must be in a valid range.  the range is specified by a	 *  lower bound (idoffset) and a bit vector (idvec) where a	 *  bit set to 1 means unusable	 */	lock(&aip->idlock);	x = a.id - aip->idoffset;	bit = 1<<x;	if(x < 0 || x > 31 || (bit&aip->idvec)){		unlock(&aip->idlock);		print("9p1: id out of range: idoff %ld idvec %lux id %ld\n", 		   aip->idoffset, aip->idvec, a.id);		return 0;	}	aip->idvec |= bit;	/* normalize the vector */	while(aip->idvec&0xffff0001){		aip->idvec >>= 1;		aip->idoffset++;	}	unlock(&aip->idlock);	/* ticket name and attach name must match */	if(memcmp(in->uname, t.cuid, sizeof(in->uname)) != 0){		print("9p1: names don't match\n");		return 0;	}	/* copy translated name into input record */	memmove(in->uname, t.suid, sizeof(in->uname));	/* craft a reply */	a.num = AuthAs;	memmove(a.chal, aip->rchal, CHALLEN);	convA2M9p1(&a, ou->rauth, t.key);	return 1;}/* * buggery to give false qid for * the top 2 levels of the dump fs */voidmkqid(Qid* qid, Dentry *d, int buggery){	int c;	if(buggery && d->qid.path == (QPDIR|QPROOT)){		c = d->name[0];		if(c >= '0' && c <= '9'){			qid->path = 3;			qid->vers = d->qid.version;			qid->type = QTDIR;			c = (c-'0')*10 + (d->name[1]-'0');			if(c >= 1 && c <= 12)				qid->path = 4;			return;		}	}	mkqid9p2(qid, &d->qid, d->mode);}intmkqidcmp(Qid* qid, Dentry *d){	Qid tmp;	mkqid(&tmp, d, 1);	if(qid->path == tmp.path && qid->type == tmp.type)		return 0;	return Eqid;}static voidf_attach(Chan *cp, Fcall *in, Fcall *ou){	Iobuf *p;	Dentry *d;	File *f;	int u;	Filsys *fs;	Off raddr;	if(CHAT(cp)) {		print("c_attach %d\n", cp->chan);		print("	fid = %d\n", in->fid);		print("	uid = %s\n", in->uname);		print("	arg = %s\n", in->aname);	}	ou->qid = QID9P1(0,0);	ou->fid = in->fid;	if(!in->aname[0])	/* default */		strncpy(in->aname, "main", sizeof(in->aname));	p = 0;	f = filep(cp, in->fid, 1);	if(!f) {		ou->err = Efid;		goto out;	}	u = -1;	if(cp != cons.chan) {		if(noattach && strcmp(in->uname, "none")) {			ou->err = Enoattach;			goto out;		}		if(authorize(cp, in, ou) == 0 || strcmp(in->uname, "adm") == 0) {			ou->err = Eauth;			goto out;		}		u = strtouid(in->uname);		if(u < 0) {			ou->err = Ebadu;			goto out;		}	}	f->uid = u;	fs = fsstr(in->aname);	if(fs == 0) {		ou->err = Ebadspc;		goto out;	}	raddr = getraddr(fs->dev);	p = getbuf(fs->dev, raddr, Bread);	d = getdir(p, 0);	if(!d || checktag(p, Tdir, QPROOT) || !(d->mode & DALLOC)) {		ou->err = Ealloc;		goto out;	}	if (iaccess(f, d, DEXEC) ||	    f->uid == 0 && fs->dev->type == Devro) {		/*		 * 'none' not allowed on dump		 */		ou->err = Eaccess;		goto out;	}	accessdir(p, d, FREAD, f->uid);	mkqid(&f->qid, d, 1);	f->fs = fs;	f->addr = raddr;	f->slot = 0;	f->open = 0;	freewp(f->wpath);	f->wpath = 0;	mkqid9p1(&ou->qid, &f->qid);	strncpy(cp->whoname, in->uname, sizeof(cp->whoname));	cp->whotime = time();	if(cons.flags & attachflag)		print("9p1: attach %s %T to \"%s\" C%d\n",			cp->whoname, cp->whotime, fs->name, cp->chan);out:	if((cons.flags & attachflag) && ou->err)		print("9p1: attach %s %T SUCK EGGS --- %s\n",			in->uname, time(), errstr9p[ou->err]);	if(p)		putbuf(p);	if(f) {		qunlock(f);		if(ou->err)			freefp(f);	}}static voidf_clone(Chan *cp, Fcall *in, Fcall *ou){	File *f1, *f2;	Wpath *p;	int fid, fid1;	if(CHAT(cp)) {		print("c_clone %d\n", cp->chan);		print("	old fid = %d\n", in->fid);		print("	new fid = %d\n", in->newfid);	}	fid = in->fid;	fid1 = in->newfid;	f1 = 0;	f2 = 0;	if(fid < fid1) {		f1 = filep(cp, fid, 0);		f2 = filep(cp, fid1, 1);	} else	if(fid1 < fid) {		f2 = filep(cp, fid1, 1);		f1 = filep(cp, fid, 0);	}	if(!f1 || !f2) {		ou->err = Efid;		goto out;	}	f2->fs = f1->fs;	f2->addr = f1->addr;	f2->open = f1->open & ~FREMOV;	f2->uid = f1->uid;	f2->slot = f1->slot;	f2->qid = f1->qid;	freewp(f2->wpath);	lock(&wpathlock);	f2->wpath = f1->wpath;	for(p = f2->wpath; p; p = p->up)		p->refs++;	unlock(&wpathlock);out:	ou->fid = fid;	if(f1)		qunlock(f1);	if(f2) {		qunlock(f2);		if(ou->err)			freefp(f2);	}}static voidf_walk(Chan *cp, Fcall *in, Fcall *ou){	Iobuf *p, *p1;	Dentry *d, *d1;	File *f;	Wpath *w;	int slot;	Off addr, qpath;	if(CHAT(cp)) {		print("c_walk %d\n", cp->chan);		print("	fid = %d\n", in->fid);		print("	name = %s\n", in->name);	}	ou->fid = in->fid;	ou->qid = QID9P1(0,0);	p = 0;	f = filep(cp, in->fid, 0);	if(!f) {		ou->err = Efid;		goto out;	}	p = getbuf(f->fs->dev, f->addr, Bread);	d = getdir(p, f->slot);	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {		ou->err = Ealloc;		goto out;	}	if(!(d->mode & DDIR)) {		ou->err = Edir1;		goto out;	}	if(ou->err = mkqidcmp(&f->qid, d))		goto out;	if(cp != cons.chan && iaccess(f, d, DEXEC)) {		ou->err = Eaccess;		goto out;	}	accessdir(p, d, FREAD, f->uid);	if(strcmp(in->name, ".") == 0)		goto setdot;	if(strcmp(in->name, "..") == 0) {		if(f->wpath == 0)			goto setdot;		putbuf(p);		p = 0;		addr = f->wpath->addr;		slot = f->wpath->slot;		p1 = getbuf(f->fs->dev, addr, Bread);		d1 = getdir(p1, slot);		if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {			if(p1)				putbuf(p1);			ou->err = Ephase;			goto out;		}		lock(&wpathlock);		f->wpath->refs--;		f->wpath = f->wpath->up;		unlock(&wpathlock);		goto found;	}	for(addr=0;; addr++) {		if(p == 0) {			p = getbuf(f->fs->dev, f->addr, Bread);			d = getdir(p, f->slot);			if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {				ou->err = Ealloc;				goto out;			}		}		qpath = d->qid.path;		p1 = dnodebuf1(p, d, addr, 0, f->uid);		p = 0;		if(!p1 || checktag(p1, Tdir, qpath) ) {			if(p1)				putbuf(p1);			ou->err = Eentry;			goto out;		}		for(slot=0; slot<DIRPERBUF; slot++) {			d1 = getdir(p1, slot);			if(!(d1->mode & DALLOC))				continue;			if(strncmp(in->name, d1->name, sizeof(in->name)) != 0)				continue;			/*			 * update walk path			 */			w = newwp();			if(!w) {				ou->err = Ewalk;				putbuf(p1);				goto out;			}			w->addr = f->addr;			w->slot = f->slot;			w->up = f->wpath;			f->wpath = w;			slot += DIRPERBUF*addr;			goto found;		}		putbuf(p1);	}found:	f->addr = p1->addr;	mkqid(&f->qid, d1, 1);	putbuf(p1);	f->slot = slot;setdot:	mkqid9p1(&ou->qid, &f->qid);	f->open = 0;out:	if(p)		putbuf(p);	if(f)		qunlock(f);}static voidf_open(Chan *cp, Fcall *in, Fcall *ou){	Iobuf *p;	Dentry *d;	File *f;	Tlock *t;	Qid qid;	int ro, fmod, wok;	if(CHAT(cp)) {		print("c_open %d\n", cp->chan);		print("	fid = %d\n", in->fid);		print("	mode = %o\n", in->mode);	}	wok = 0;	if(cp == cons.chan || writeallow)		wok = 1;	p = 0;	f = filep(cp, in->fid, 0);	if(!f) {		ou->err = Efid;		goto out;	}	/*	 * if remove on close, check access here	 */	ro = f->fs->dev->type == Devro;	if(in->mode & ORCLOSE) {		if(ro) {			ou->err = Eronly;			goto out;		}		/*		 * check on parent directory of file to be deleted		 */		if(f->wpath == 0 || f->wpath->addr == f->addr) {			ou->err = Ephase;			goto out;		}		p = getbuf(f->fs->dev, f->wpath->addr, Bread);		d = getdir(p, f->wpath->slot);		if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {			ou->err = Ephase;			goto out;		}		if(iaccess(f, d, DWRITE)) {			ou->err = Eaccess;			goto out;		}		putbuf(p);	}	p = getbuf(f->fs->dev, f->addr, Bread);	d = getdir(p, f->slot);	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {		ou->err = Ealloc;		goto out;	}	if(ou->err = mkqidcmp(&f->qid, d))		goto out;	mkqid(&qid, d, 1);	switch(in->mode & 7) {	case OREAD:		if(iaccess(f, d, DREAD) && !wok)			goto badaccess;		fmod = FREAD;		break;	case OWRITE:		if((d->mode & DDIR) ||		   (iaccess(f, d, DWRITE) && !wok))			goto badaccess;		if(ro) {			ou->err = Eronly;			goto out;		}		fmod = FWRITE;		break;	case ORDWR:		if((d->mode & DDIR) ||		   (iaccess(f, d, DREAD) && !wok) ||		   (iaccess(f, d, DWRITE) && !wok))			goto badaccess;		if(ro) {			ou->err = Eronly;			goto out;		}		fmod = FREAD+FWRITE;		break;	case OEXEC:		if((d->mode & DDIR) ||		   (iaccess(f, d, DEXEC) && !wok))			goto badaccess;		fmod = FREAD;		break;	default:		ou->err = Emode;		goto out;	}	if(in->mode & OTRUNC) {		if((d->mode & DDIR) ||		   (iaccess(f, d, DWRITE) && !wok))			goto badaccess;		if(ro) {			ou->err = Eronly;			goto out;		}	}	t = 0;	if(d->mode & DLOCK) {		t = tlocked(p, d);		if(t == nil) {			ou->err = Elocked;			goto out;		}	}	if(in->mode & ORCLOSE)		fmod |= FREMOV;	f->open = fmod;	if(in->mode & OTRUNC)		if(!(d->mode & DAPND)) {			dtrunc(p, d, f->uid);			qid.vers = d->qid.version;		}	f->tlock = t;	if(t)		t->file = f;	f->lastra = 1;	mkqid9p1(&ou->qid, &qid);	goto out;badaccess:	ou->err = Eaccess;	f->open = 0;out:	if(p)		putbuf(p);	if(f)		qunlock(f);	ou->fid = in->fid;}static voidf_create(Chan *cp, Fcall *in, Fcall *ou){	Iobuf *p, *p1;	Dentry *d, *d1;	File *f;	int slot, slot1, fmod, wok;	Off addr, addr1, path;	Qid qid;	Tlock *t;	Wpath *w;	if(CHAT(cp)) {		print("c_create %d\n", cp->chan);		print("	fid = %d\n", in->fid);		print("	name = %s\n", in->name);		print("	perm = %lx+%lo\n", (in->perm>>28)&0xf,				in->perm&0777);		print("	mode = %o\n", in->mode);	}	wok = 0;	if(cp == cons.chan || writeallow)		wok = 1;	p = 0;	f = filep(cp, in->fid, 0);	if(!f) {		ou->err = Efid;		goto out;	}	if(f->fs->dev->type == Devro) {		ou->err = Eronly;		goto out;	}	p = getbuf(f->fs->dev, f->addr, Bread);	d = getdir(p, f->slot);	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {		ou->err = Ealloc;		goto out;	}	if(ou->err = mkqidcmp(&f->qid, d))		goto out;	if(!(d->mode & DDIR)) {		ou->err = Edir2;		goto out;	}	if(iaccess(f, d, DWRITE) && !wok) {		ou->err = Eaccess;		goto out;	}	accessdir(p, d, FREAD, f->uid);	if(!strncmp(in->name, ".", sizeof(in->name)) ||	   !strncmp(in->name, "..", sizeof(in->name))) {		ou->err = Edot;		goto out;	}	if(checkname(in->name)) {		ou->err = Ename;		goto out;	}	addr1 = 0;	slot1 = 0;	/* set */	for(addr=0;; addr++) {		p1 = dnodebuf(p, d, addr, 0, f->uid);		if(!p1) {			if(addr1)				break;			p1 = dnodebuf(p, d, addr, Tdir, f->uid);		}		if(p1 == 0) {			ou->err = Efull;			goto out;		}		if(checktag(p1, Tdir, d->qid.path)) {			putbuf(p1);			goto phase;		}		for(slot=0; slot<DIRPERBUF; slot++) {			d1 = getdir(p1, slot);			if(!(d1->mode & DALLOC)) {				if(!addr1) {					addr1 = p1->addr;					slot1 = slot + addr*DIRPERBUF;				}				continue;			}			if(!strncmp(in->name, d1->name, sizeof(in->name))) {				putbuf(p1);				ou->err = Eexist;				goto out;			}		}		putbuf(p1);	}	switch(in->mode & 7) {	case OEXEC:	case OREAD:		/* seems only useful to make directories */		fmod = FREAD;		break;	case OWRITE:		fmod = FWRITE;		break;	case ORDWR:		fmod = FREAD+FWRITE;		break;	default:		ou->err = Emode;		goto out;	}	if(in->perm & PDIR)		if((in->mode & OTRUNC) || (in->perm & PAPND) || (fmod & FWRITE))			goto badaccess;	/*	 * do it	 */	path = qidpathgen(f->fs->dev);	p1 = getbuf(f->fs->dev, addr1, Bread|Bimm|Bmod);	d1 = getdir(p1, slot1);	if(!d1 || checktag(p1, Tdir, d->qid.path)) {		if(p1)			putbuf(p1);		goto phase;	}	if(d1->mode & DALLOC) {		putbuf(p1);		goto phase;	}	strncpy(d1->name, in->name, sizeof(in->name));	if(cp == cons.chan) {		d1->uid = cons.uid;		d1->gid = cons.gid;	} else {		d1->uid = f->uid;		d1->gid = d->gid;		in->perm &= d->mode | ~0666;		if(in->perm & PDIR)			in->perm &= d->mode | ~0777;	}	d1->qid.path = path;	d1->qid.version = 0;	d1->mode = DALLOC | (in->perm & 0777);	if(in->perm & PDIR) {		d1->mode |= DDIR;		d1->qid.path |= QPDIR;	}	if(in->perm & PAPND)		d1->mode |= DAPND;	t = 0;	if(in->perm & PLOCK) {		d1->mode |= DLOCK;		t = tlocked(p1, d1);		/* if nil, out of tlock structures */	}	accessdir(p1, d1, FWRITE, f->uid);	mkqid(&qid, d1, 0);	putbuf(p1);	accessdir(p, d, FWRITE, f->uid);	/*	 * do a walk to new directory entry	 */	w = newwp();	if(!w) {		ou->err = Ewalk;		goto out;	}	w->addr = f->addr;	w->slot = f->slot;	w->up = f->wpath;	f->wpath = w;	f->qid = qid;	f->tlock = t;	if(t)		t->file = f;	f->lastra = 1;	if(in->mode & ORCLOSE)		fmod |= FREMOV;	f->open = fmod;	f->addr = addr1;	f->slot = slot1;	mkqid9p1(&ou->qid, &qid);	goto out;badaccess:	ou->err = Eaccess;	goto out;phase:	ou->err = Ephase;out:	if(p)		putbuf(p);	if(f)		qunlock(f);	ou->fid = in->fid;}static voidf_read(Chan *cp, Fcall *in, Fcall *ou){	Iobuf *p, *p1;	File *f;

⌨️ 快捷键说明

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