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

📄 9p1.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"all.h"#include	"9p1.h"/* * 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 == QPROOT && (d->qid.path & QPDIR)){		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&QTDIR)==(tmp.type&QTDIR))		return 0;	return Eqid;}voidf_nop(Chan *cp, Oldfcall *in, Oldfcall *ou){	USED(in);	USED(ou);	if(CHAT(cp))		print("c_nop %d\n", cp->chan);}voidf_flush(Chan *cp, Oldfcall *in, Oldfcall *ou){	USED(in);	USED(ou);	if(CHAT(cp))		print("c_flush %d\n", cp->chan);	runlock(&cp->reflock);	wlock(&cp->reflock);	wunlock(&cp->reflock);	rlock(&cp->reflock);}voidf_session(Chan *cp, Oldfcall *in, Oldfcall *ou){	if(CHAT(cp))		print("c_session %d\n", cp->chan);	memmove(cp->rchal, in->chal, sizeof(cp->rchal));	if(wstatallow || cp == cons.srvchan){		memset(ou->chal, 0, sizeof(ou->chal));		memset(ou->authid, 0, sizeof(ou->authid));	}else{		mkchallenge(cp);		memmove(ou->chal, cp->chal, sizeof(ou->chal));		memmove(ou->authid, nvr.authid, sizeof(ou->authid));	}	sprint(ou->authdom, "%s.%s", service, nvr.authdom);	fileinit(cp);}voidf_attach(Chan *cp, Oldfcall *in, Oldfcall *ou){	Iobuf *p;	Dentry *d;	File *f;	int u;	Filsys *fs;	long 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, filesys[0].name, 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(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;		}	}	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;	}	f->uid = u;	if(iaccess(f, d, DREAD)) {		ou->err = Eaccess;		goto out;	}	accessdir(p, d, FREAD);	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);out:	if(p)		putbuf(p);	if(f) {		qunlock(f);		if(ou->err)			freefp(f);	}}voidf_clone(Chan *cp, Oldfcall *in, Oldfcall *ou){	File *f1, *f2;	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);	f2->wpath = getwp(f1->wpath);out:	ou->fid = fid;	if(f1)		qunlock(f1);	if(f2)		qunlock(f2);}voidf_walk(Chan *cp, Oldfcall *in, Oldfcall *ou){	Iobuf *p, *p1;	Dentry *d, *d1;	File *f;	Wpath *w, *ow;	int slot;	long addr;	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);	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;		}		ow = f->wpath;		f->wpath = ow->up;		putwp(ow);		goto found;	}	for(addr=0;; addr++) {		p1 = dnodebuf(p, d, addr, 0);		if(!p1 || checktag(p1, Tdir, d->qid.path) ) {			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)))				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);}voidf_clunk(Chan *cp, Oldfcall *in, Oldfcall *ou){	File *f;	Tlock *t;	long tim;	if(CHAT(cp)) {		print("c_clunk %d\n", cp->chan);		print("	fid = %d\n", in->fid);	}	f = filep(cp, in->fid, 0);	if(!f) {		print("%p\n", f);		ou->err = Efid;		goto out;	}	if(t = f->tlock) {		tim = time(0);		if(t->time < tim || t->file != f)			ou->err = Ebroken;		t->time = 0;	/* free the lock */		f->tlock = 0;	}	if(f->open & FREMOV)		ou->err = doremove(f, 0);	f->open = 0;	freewp(f->wpath);	freefp(f);out:	if(f)		qunlock(f);	ou->fid = in->fid;}voidf_clwalk(Chan *cp, Oldfcall *in, Oldfcall *ou){	int er, fid;	if(CHAT(cp))		print("c_clwalk macro\n");	f_clone(cp, in, ou);		/* sets tag, fid */	if(ou->err)		return;	fid = in->fid;	in->fid = in->newfid;	f_walk(cp, in, ou);		/* sets tag, fid, qid */	er = ou->err;	if(er == Eentry) {		/*		 * if error is "no entry"		 * return non error and fid		 */		ou->err = 0;		f_clunk(cp, in, ou);	/* sets tag, fid */		ou->err = 0;		ou->fid = fid;		if(CHAT(cp)) 			print("	error: %s\n", errstring[er]);		return;	}	if(er) {		/*		 * if any other error		 * return an error		 */		ou->err = 0;		f_clunk(cp, in, ou);	/* sets tag, fid */		ou->err = er;		return;	}	/*	 * non error	 * return newfid	 */}voidf_open(Chan *cp, Oldfcall *in, Oldfcall *ou){	Iobuf *p;	Dentry *d;	File *f;	Tlock *t;	Qid qid;	int ro, fmod;	if(CHAT(cp)) {		print("c_open %d\n", cp->chan);		print("	fid = %d\n", in->fid);		print("	mode = %o\n", in->mode);	}	p = 0;	f = filep(cp, in->fid, 0);	if(!f) {		ou->err = Efid;		goto out;	}	/*	 * if remove on close, check access here	 */	ro = isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup));	if(in->mode & MRCLOSE) {		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 MREAD:		if(iaccess(f, d, DREAD) && !writeallow)			goto badaccess;		fmod = FREAD;		break;	case MWRITE:		if((d->mode & DDIR) ||		   (iaccess(f, d, DWRITE) && !writeallow))			goto badaccess;		if(ro) {			ou->err = Eronly;			goto out;		}		fmod = FWRITE;		break;	case MBOTH:		if((d->mode & DDIR) ||		   (iaccess(f, d, DREAD) && !writeallow) ||		   (iaccess(f, d, DWRITE) && !writeallow))			goto badaccess;		if(ro) {			ou->err = Eronly;			goto out;		}		fmod = FREAD+FWRITE;		break;	case MEXEC:		if((d->mode & DDIR) ||		   iaccess(f, d, DEXEC))			goto badaccess;		fmod = FREAD;		break;	default:		ou->err = Emode;		goto out;	}	if(in->mode & MTRUNC) {		if((d->mode & DDIR) ||		   (iaccess(f, d, DWRITE) && !writeallow))			goto badaccess;		if(ro) {			ou->err = Eronly;			goto out;		}	}	t = 0;	if(d->mode & DLOCK) {		t = tlocked(p, d);		if(t == 0) {			ou->err = Elocked;			goto out;		}		t->file = f;	}	if(in->mode & MRCLOSE)		fmod |= FREMOV;	f->open = fmod;	if(in->mode & MTRUNC)		if(!(d->mode & DAPND))			dtrunc(p, d);	f->tlock = t;	f->lastra = 0;	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;}voidf_create(Chan *cp, Oldfcall *in, Oldfcall *ou){	Iobuf *p, *p1;	Dentry *d, *d1;	File *f;	int slot, slot1, fmod;	long 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 = %d\n", in->mode);	}	p = 0;	f = filep(cp, in->fid, 0);	if(!f) {		ou->err = Efid;		goto out;	}	if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {		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(cp != cons.chan && iaccess(f, d, DWRITE) && !writeallow) {		ou->err = Eaccess;		goto out;	}	accessdir(p, d, FREAD);	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);		if(!p1) {			if(addr1)				break;			p1 = dnodebuf(p, d, addr, Tdir);		}		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 MEXEC:	case MREAD:		/* seems only useful to make directories */		fmod = FREAD;		break;	case MWRITE:		fmod = FWRITE;		break;	case MBOTH:		fmod = FREAD+FWRITE;		break;	default:		ou->err = Emode;		goto out;	}	if(in->perm & PDIR)		if((in->mode & MTRUNC) || (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));	/*	 * bogus argument passing -- see console.c	 */	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);	}	accessdir(p1, d1, FWRITE);	mkqid(&qid, d1, 0);	putbuf(p1);	accessdir(p, d, FWRITE);	/*	 * 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;

⌨️ 快捷键说明

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