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

📄 9p1.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	f->lastra = 0;	if(in->mode & MRCLOSE)		fmod |= FREMOV;	f->open = fmod;	f->addr = addr1;	f->slot = slot1;	if(t)		t->file = f;	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;}voidf_read(Chan *cp, Oldfcall *in, Oldfcall *ou){	Iobuf *p, *p1;	File *f;	Dentry *d, *d1;	Tlock *t;	long addr, offset, tim;	int nread, count, n, o, slot;	if(CHAT(cp)) {		print("c_read %d\n", cp->chan);		print("	fid = %d\n", in->fid);		print("	offset = %ld\n", in->offset);		print("	count = %ld\n", in->count);	}	p = 0;	count = in->count;	offset = in->offset;	nread = 0;	f = filep(cp, in->fid, 0);	if(!f) {		ou->err = Efid;		goto out;	}	if(!(f->open & FREAD)) {		ou->err = Eopen;		goto out;	}	if(count < 0 || count > MAXDAT) {		ou->err = Ecount;		goto out;	}	if(offset < 0) {		ou->err = Eoffset;		goto out;	}	p = getbuf(f->fs->dev, f->addr, Bread);	d = getdir(p, f->slot);	if(!d || !(d->mode & DALLOC)) {		ou->err = Ealloc;		goto out;	}	if(ou->err = mkqidcmp(&f->qid, d))		goto out;	if(t = f->tlock) {		tim = time(0);		if(t->time < tim || t->file != f) {			ou->err = Ebroken;			goto out;		}		/* renew the lock */		t->time = tim + TLOCK;	}	accessdir(p, d, FREAD);	if(d->mode & DDIR) {		addr = 0;		goto dread;	}	if(offset+count > d->size)		count = d->size - offset;	while(count > 0) {		addr = offset / BUFSIZE;		if(addr == f->lastra+1)			dbufread(p, d, addr+1);		f->lastra = addr;		o = offset % BUFSIZE;		n = BUFSIZE - o;		if(n > count)			n = count;		p1 = dnodebuf(p, d, addr, 0);		if(p1) {			if(checktag(p1, Tfile, QPNONE)) {				ou->err = Ephase;				putbuf(p1);				goto out;			}			memmove(ou->data+nread, p1->iobuf+o, n);			putbuf(p1);		} else			memset(ou->data+nread, 0, n);		count -= n;		nread += n;		offset += n;	}	goto out;dread:	p1 = dnodebuf(p, d, addr, 0);	if(!p1)		goto out;	if(checktag(p1, Tdir, QPNONE)) {		ou->err = Ephase;		putbuf(p1);		goto out;	}	n = DIRREC;	for(slot=0; slot<DIRPERBUF; slot++) {		d1 = getdir(p1, slot);		if(!(d1->mode & DALLOC))			continue;		if(offset >= n) {			offset -= n;			continue;		}		if(count < n) {			putbuf(p1);			goto out;		}		if(convD2M9p1(d1, ou->data+nread) != n)			print("dirread convD2M\n");		nread += n;		count -= n;	}	putbuf(p1);	addr++;	goto dread;out:	count = in->count - nread;	if(count > 0)		memset(ou->data+nread, 0, count);	if(p)		putbuf(p);	if(f)		qunlock(f);	ou->fid = in->fid;	ou->count = nread;	if(CHAT(cp))		print("	nread = %d\n", nread);}voidf_write(Chan *cp, Oldfcall *in, Oldfcall *ou){	Iobuf *p, *p1;	Dentry *d;	File *f;	Tlock *t;	long offset, addr, tim;	int count, nwrite, o, n;	if(CHAT(cp)) {		print("c_write %d\n", cp->chan);		print("	fid = %d\n", in->fid);		print("	offset = %ld\n", in->offset);		print("	count = %ld\n", in->count);	}	offset = in->offset;	count = in->count;	nwrite = 0;	p = 0;	f = filep(cp, in->fid, 0);	if(!f) {		ou->err = Efid;		goto out;	}	if(!(f->open & FWRITE)) {		ou->err = Eopen;		goto out;	}	if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {		ou->err = Eronly;		goto out;	}	if(count < 0 || count > MAXDAT) {		ou->err = Ecount;		goto out;	}	if(offset < 0) {		ou->err = Eoffset;		goto out;	}	p = getbuf(f->fs->dev, f->addr, Bread|Bmod);	d = getdir(p, f->slot);	if(!d || !(d->mode & DALLOC)) {		ou->err = Ealloc;		goto out;	}	if(ou->err = mkqidcmp(&f->qid, d))		goto out;	if(t = f->tlock) {		tim = time(0);		if(t->time < tim || t->file != f) {			ou->err = Ebroken;			goto out;		}		/* renew the lock */		t->time = tim + TLOCK;	}	accessdir(p, d, FWRITE);	if(d->mode & DAPND)		offset = d->size;	if(offset+count > d->size)		d->size = offset+count;	while(count > 0) {		addr = offset / BUFSIZE;		o = offset % BUFSIZE;		n = BUFSIZE - o;		if(n > count)			n = count;		p1 = dnodebuf(p, d, addr, Tfile);		if(p1 == 0) {			ou->err = Efull;			goto out;		}		if(checktag(p1, Tfile, d->qid.path)) {			putbuf(p1);			ou->err = Ephase;			goto out;		}		memmove(p1->iobuf+o, in->data+nwrite, n);		p1->flags |= Bmod;		putbuf(p1);		count -= n;		nwrite += n;		offset += n;	}	if(CHAT(cp))		print("	nwrite = %d\n", nwrite);out:	if(p)		putbuf(p);	if(f)		qunlock(f);	ou->fid = in->fid;	ou->count = nwrite;}intdoremove(File *f, int iscon){	Iobuf *p, *p1;	Dentry *d, *d1;	long addr;	int slot, err;	p = 0;	p1 = 0;	if(isro(f->fs->dev) || (f->cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {		err = Eronly;		goto out;	}	/*	 * check on parent directory of file to be deleted	 */	if(f->wpath == 0 || f->wpath->addr == f->addr) {		err = Ephase;		goto out;	}	p1 = getbuf(f->fs->dev, f->wpath->addr, Bread);	d1 = getdir(p1, f->wpath->slot);	if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {		err = Ephase;		goto out;	}	if(!iscon && iaccess(f, d1, DWRITE)) {		err = Eaccess;		goto out;	}	accessdir(p1, d1, FWRITE);	putbuf(p1);	p1 = 0;	/*	 * check on file to be deleted	 */	p = getbuf(f->fs->dev, f->addr, Bread);	d = getdir(p, f->slot);	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {		err = Ealloc;		goto out;	}	if(err = mkqidcmp(&f->qid, d))		goto out;	/*	 * if deleting a directory, make sure it is empty	 */	if((d->mode & DDIR))	for(addr=0;; addr++) {		p1 = dnodebuf(p, d, addr, 0);		if(!p1)			break;		if(checktag(p1, Tdir, d->qid.path)) {			err = Ephase;			goto out;		}		for(slot=0; slot<DIRPERBUF; slot++) {			d1 = getdir(p1, slot);			if(!(d1->mode & DALLOC))				continue;			err = Eempty;			goto out;		}		putbuf(p1);	}	/*	 * do it	 */	dtrunc(p, d);	memset(d, 0, sizeof(Dentry));	settag(p, Tdir, QPNONE);out:	if(p1)		putbuf(p1);	if(p)		putbuf(p);	return err;}voidf_remove(Chan *cp, Oldfcall *in, Oldfcall *ou){	File *f;	if(CHAT(cp)) {		print("c_remove %d\n", cp->chan);		print("	fid = %d\n", in->fid);	}	f = filep(cp, in->fid, 0);	if(!f) {		ou->err = Efid;		goto out;	}	ou->err = doremove(f, cp==cons.chan);out:	ou->fid = in->fid;	if(f)		qunlock(f);}voidf_stat(Chan *cp, Oldfcall *in, Oldfcall *ou){	Iobuf *p;	Dentry *d;	File *f;	if(CHAT(cp)) {		print("c_stat %d\n", cp->chan);		print("	fid = %d\n", in->fid);	}	p = 0;	memset(ou->stat, 0, sizeof(ou->stat));	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(ou->err = mkqidcmp(&f->qid, d))		goto out;	if(d->qid.path == QPROOT)	/* stat of root gives time */		d->atime = time(0);	if(convD2M9p1(d, ou->stat) != DIRREC)		print("stat convD2M\n");out:	if(p)		putbuf(p);	if(f)		qunlock(f);	ou->fid = in->fid;}voidf_wstat(Chan *cp, Oldfcall *in, Oldfcall *ou){	Iobuf *p, *p1;	Dentry *d, *d1, xd;	File *f;	int slot;	long addr;	if(CHAT(cp)) {		print("c_wstat %d\n", cp->chan);		print("	fid = %d\n", in->fid);	}	p = 0;	p1 = 0;	d1 = 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;	}	/*	 * first get parent	 */	if(f->wpath) {		p1 = getbuf(f->fs->dev, f->wpath->addr, Bread);		d1 = getdir(p1, f->wpath->slot);		if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {			ou->err = Ephase;			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;	convM2D9p1(in->stat, &xd);	if(CHAT(cp)) {		print("	d.name = %s\n", xd.name);		print("	d.uid  = %d\n", xd.uid);		print("	d.gid  = %d\n", xd.gid);		print("	d.mode = %.4x\n", xd.mode);	}	/*	 * if chown,	 * must be god	 */	while(xd.uid != d->uid) {		if(wstatallow)			/* set to allow chown during boot */			break;		ou->err = Enotu;		goto out;	}	/*	 * if chgroup,	 * must be either	 *	a) owner and in new group	 *	b) leader of both groups	 */	while(xd.gid != d->gid) {		if(wstatallow || writeallow)		/* set to allow chgrp during boot */			break;		if(d->uid == f->uid && ingroup(f->uid, xd.gid))			break;		if(leadgroup(f->uid, xd.gid))			if(leadgroup(f->uid, d->gid))				break;		ou->err = Enotg;		goto out;	}	/*	 * if rename,	 * must have write permission in parent	 */	if(xd.name[0] == 0)		strncpy(xd.name, d->name, sizeof(xd.name));	while(strncmp(d->name, xd.name, sizeof(d->name)) != 0) {		if(checkname(xd.name)) {			ou->err = Ename;			goto out;		}		if(strcmp(xd.name, ".") == 0 || strcmp(xd.name, "..") == 0) {			ou->err = Ename;			goto out;		}		/*		 * drop entry to prevent lock, then		 * check that destination name is unique,		 */		putbuf(p);		for(addr=0;; addr++) {			p = dnodebuf(p1, d1, addr, 0);			if(!p)				break;			if(checktag(p, Tdir, d1->qid.path)) {				putbuf(p);				continue;			}			for(slot=0; slot<DIRPERBUF; slot++) {				d = getdir(p, slot);				if(!(d->mode & DALLOC))					continue;				if(!strncmp(xd.name, d->name, sizeof(xd.name))) {					ou->err = Eexist;					goto out;				}			}			putbuf(p);		}		/*		 * reacquire entry		 */		p = getbuf(f->fs->dev, f->addr, Bread);		d = getdir(p, f->slot);		if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {			ou->err = Ephase;			goto out;		}		if(wstatallow || writeallow) /* set to allow rename during boot */			break;		if(!d1 || iaccess(f, d1, DWRITE)) {			ou->err = Eaccess;			goto out;		}		break;	}	/*	 * if mode/time, either	 *	a) owner	 *	b) leader of either group	 */	while(d->mtime != xd.mtime ||	     ((d->mode^xd.mode) & (DAPND|DLOCK|0777))) {		if(wstatallow)			/* set to allow chmod during boot */			break;		if(d->uid == f->uid)			break;		if(leadgroup(f->uid, xd.gid))			break;		if(leadgroup(f->uid, d->gid))			break;		ou->err = Enotu;		goto out;	}	d->mtime = xd.mtime;	d->uid = xd.uid;	d->gid = xd.gid;	d->mode = (xd.mode & (DAPND|DLOCK|0777)) | (d->mode & (DALLOC|DDIR));	strncpy(d->name, xd.name, sizeof(d->name));	if(wstatallow) {		p->flags |= Bmod;		if(xd.atime)			d->atime = xd.atime;		if(xd.mtime)			d->mtime = xd.mtime;	} else		accessdir(p, d, FWSTAT);out:	if(p)		putbuf(p);	if(p1)		putbuf(p1);	if(f)		qunlock(f);	ou->fid = in->fid;}void(*call9p1[MAXSYSCALL])(Chan*, Oldfcall*, Oldfcall*) ={	[Tnop9p1]		f_nop,	[Tosession9p1]	f_session,	[Tsession9p1]	f_session,	[Tflush9p1]	f_flush,	[Toattach9p1]	f_attach,	[Tattach9p1]	f_attach,	[Tclone9p1]	f_clone,	[Twalk9p1]		f_walk,	[Topen9p1]		f_open,	[Tcreate9p1]	f_create,	[Tread9p1]		f_read,	[Twrite9p1]	f_write,	[Tclunk9p1]	f_clunk,	[Tremove9p1]	f_remove,	[Tstat9p1]		f_stat,	[Twstat9p1]	f_wstat,	[Tclwalk9p1]	f_clwalk,};static voidsend(Chan *c, uchar *buf, int n){	int fd, m;	fd = c->chan;	m = write(fd, buf, n);	if(m == n)		return;	panic("write failed");}voiderror9p1(Chan *c, uchar *buf){	buf[0] = Rnop9p1;	buf[1] = ~0;	buf[2] = ~0;	send(c, buf, 3);}voidserve9p1(Chan *chan, uchar *ib, int nib){	int n, t;	uchar inbuf[MAXMSG+MAXDAT], outbuf[MAXMSG+MAXDAT];	Oldfcall fi, fo;	for(;;){		if(nib){			memmove(inbuf, ib, nib);			n = nib;			nib = 0;		}else			n = read(chan->chan, inbuf, sizeof inbuf);		if(chat)			print("read msg %d\n", n);		if(n == 0 && (chan == cons.srvchan || chan == cons.chan))			continue;		if(n <= 0)			return;		if(convM2S9p1(inbuf, &fi, n) != n){			error9p1(chan, outbuf);			continue;		}		t = fi.type;		if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) {			print("9p1: bad message type\n");			error9p1(chan, outbuf);			continue;		}		if(CHAT(chan))			print("9p1: fi %O\n", &fi);		/*		 * set up reply message		 */		fo.err = 0;		if(t == Tread9p1)			fo.data = (char*)outbuf + 8;			/*		 * call the file system		 */		cons.work.count++;		cons.rate.count += n;		/*		 * call the file system		 */		rlock(&mainlock);		rlock(&chan->reflock);			(*call9p1[t])(chan, &fi, &fo);			runlock(&chan->reflock);		runlock(&mainlock);			fo.type = t+1;		fo.tag = fi.tag;			if(chat)			print("9p1: fo %O\n", &fo);		if(fo.err) {			strcpy(fo.ename, errstring[fo.err]);			if(CHAT(cp))				print("	error: %s\n", fo.ename);			fo.type = Terror9p1+1;		}			n = convS2M9p1(&fo, outbuf);		if(n == 0) {			print("9p1: bad S2M conversion\n");			error9p1(chan, outbuf);			continue;		}		cons.rate.count += n;		send(chan, outbuf, n);	}}

⌨️ 快捷键说明

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