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

📄 9p1.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	Dentry *d, *d1;	Tlock *t;	Off addr, offset;	Timet 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 = %lld\n", (Wideoff)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 = toytime();		if(t->time < tim || t->file != f) {			ou->err = Ebroken;			goto out;		}		/* renew the lock */		t->time = tim + TLOCK;	}	accessdir(p, d, FREAD, f->uid);	if(d->mode & DDIR) {		addr = 0;		goto dread;	}	/* XXXX terrible hack to get at raw data XXXX */	if(rawreadok && strncmp(d->name, "--raw--", 7) == 0) {		Device *dev;		Devsize boff, bsize;		dev = p->dev;		putbuf(p);		p = 0;		boff = number(d->name + 7, 0, 10) * 100000;		if(boff < 0)			boff = 0;		if(boff > devsize(dev))			boff = devsize(dev);		bsize = devsize(dev) - boff;		if(offset+count >= 100000*RBUFSIZE)			count = 100000*RBUFSIZE - offset;		if((offset+count)/RBUFSIZE >= bsize) {			/* will not overflow */			count = bsize*RBUFSIZE - offset;		}		while(count > 0) {			addr = offset / RBUFSIZE;			addr += boff;			o = offset % RBUFSIZE;			n = RBUFSIZE - o;			if(n > count)				n = count;			p1 = getbuf(dev, addr, Bread);			if(p1) {				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;	}	if(offset+count > d->size)		count = d->size - offset;	while(count > 0) {		if(p == 0) {			p = getbuf(f->fs->dev, f->addr, Bread);			d = getdir(p, f->slot);			if(!d || !(d->mode & DALLOC)) {				ou->err = Ealloc;				goto out;			}		}		addr = offset / BUFSIZE;		f->lastra = dbufread(p, d, addr, f->lastra, f->uid);		o = offset % BUFSIZE;		n = BUFSIZE - o;		if(n > count)			n = count;		p1 = dnodebuf1(p, d, addr, 0, f->uid);		p = 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:	for (;;) {		if(p == 0) {			p = getbuf(f->fs->dev, f->addr, Bread);			d = getdir(p, f->slot);			if(!d || !(d->mode & DALLOC)) {				ou->err = Ealloc;				goto out;			}		}		p1 = dnodebuf1(p, d, addr, 0, f->uid);		p = 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("9p1: dirread convD2M1990\n");			nread += n;			count -= n;		}		putbuf(p1);		addr++;	}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);}static voidf_write(Chan *cp, Fcall *in, Fcall *ou){	Iobuf *p, *p1;	Dentry *d;	File *f;	Tlock *t;	Off offset, addr, qpath;	Timet tim;	int count, nwrite, o, n;	if(CHAT(cp)) {		print("c_write %d\n", cp->chan);		print("	fid = %d\n", in->fid);		print("	offset = %lld\n", (Wideoff)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(f->fs->dev->type == Devro) {		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 = toytime();		if(t->time < tim || t->file != f) {			ou->err = Ebroken;			goto out;		}		/* renew the lock */		t->time = tim + TLOCK;	}	accessdir(p, d, FWRITE, f->uid);	if(d->mode & DAPND)		offset = d->size;	if(offset+count > d->size)		d->size = offset+count;	while(count > 0) {		if(p == 0) {			p = getbuf(f->fs->dev, f->addr, Bread|Bmod);			d = getdir(p, f->slot);			if(!d || !(d->mode & DALLOC)) {				ou->err = Ealloc;				goto out;			}		}		addr = offset / BUFSIZE;		o = offset % BUFSIZE;		n = BUFSIZE - o;		if(n > count)			n = count;		qpath = d->qid.path;		p1 = dnodebuf1(p, d, addr, Tfile, f->uid);		p = 0;		if(p1 == 0) {			ou->err = Efull;			goto out;		}		if(checktag(p1, Tfile, qpath)) {			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 wok){	Iobuf *p, *p1;	Dentry *d, *d1;	Off addr;	int slot, err;	p = 0;	p1 = 0;	if(f->fs->dev->type == Devro) {		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(iaccess(f, d1, DWRITE) && !wok) {		err = Eaccess;		goto out;	}	accessdir(p1, d1, FWRITE, f->uid);	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, f->uid);		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, f->uid);	memset(d, 0, sizeof(Dentry));	settag(p, Tdir, QPNONE);out:	if(p1)		putbuf(p1);	if(p)		putbuf(p);	return err;}static intdoclunk(File* f, int remove, int wok){	Tlock *t;	int err;	err = 0;	if(t = f->tlock) {		if(t->file == f)			t->time = 0;	/* free the lock */		f->tlock = 0;	}	if(remove)		err = doremove(f, wok);	f->open = 0;	freewp(f->wpath);	freefp(f);	return err;}static voidf_clunk(Chan *cp, Fcall *in, Fcall *ou){	File *f;	if(CHAT(cp)) {		print("c_clunk %d\n", cp->chan);		print("	fid = %d\n", in->fid);	}	f = filep(cp, in->fid, 0);	if(!f)		ou->err = Efid;	else {		doclunk(f, f->open & FREMOV, 0);		qunlock(f);	}	ou->fid = in->fid;}static voidf_remove(Chan *cp, Fcall *in, Fcall *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;	else {		ou->err = doclunk(f, 1, cp==cons.chan);		qunlock(f);	}	ou->fid = in->fid;}static voidf_stat(Chan *cp, Fcall *in, Fcall *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();	if(convD2M9p1(d, ou->stat) != DIRREC)		print("9p1: stat convD2M\n");out:	if(p)		putbuf(p);	if(f)		qunlock(f);	ou->fid = in->fid;}static voidf_wstat(Chan *cp, Fcall *in, Fcall *ou){	Iobuf *p, *p1;	Dentry *d, *d1, xd;	File *f;	int slot;	Off 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(f->fs->dev->type == Devro) {		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 = %o\n", xd.mode);	}	/*	 * if user none,	 * cant do anything	 */	if(f->uid == 0) {		ou->err = Eaccess;		goto out;	}	/*	 * if chown,	 * must be god	 */	if(xd.uid != d->uid && !wstatallow) { /* set to allow chown during boot */		ou->err = Ewstatu;		goto out;	}	/*	 * if chgroup,	 * must be either	 *	a) owner and in new group	 *	b) leader of both groups	 */	if (xd.gid != d->gid &&	    (!wstatallow && !writeallow &&  /* set to allow chgrp during boot */	     (d->uid != f->uid || !ingroup(f->uid, xd.gid)) &&	     (!leadgroup(f->uid, xd.gid) || !leadgroup(f->uid, d->gid)))) {		ou->err = Ewstatg;		goto out;	}	/*	 * if rename,	 * must have write permission in parent	 */	if (strncmp(d->name, xd.name, sizeof(d->name)) != 0) {		if (checkname(xd.name) || !d1 ||		    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, f->uid);			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 */		    (!d1 || iaccess(f, d1, DWRITE))) {			ou->err = Eaccess;			goto out;		}	}	/*	 * if mode/time, either	 *	a) owner	 *	b) leader of either group	 */	if (d->mtime != xd.mtime ||	    ((d->mode^xd.mode) & (DAPND|DLOCK|0777)))		if (!wstatallow &&	/* set to allow chmod during boot */		    d->uid != f->uid &&		    !leadgroup(f->uid, xd.gid) &&		    !leadgroup(f->uid, d->gid)) {			ou->err = Ewstatu;			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));	accessdir(p, d, FREAD, f->uid);out:	if(p)		putbuf(p);	if(p1)		putbuf(p1);	if(f)		qunlock(f);	ou->fid = in->fid;}static voidf_clwalk(Chan *cp, Fcall *in, Fcall *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", errstr9p[er]);	} else if(er) {		/*		 * if any other error		 * return an error		 */		ou->err = 0;		f_clunk(cp, in, ou);	/* sets tag, fid */		ou->err = er;	}	/*	 * non error	 * return newfid	 */}void(*call9p1[MAXSYSCALL])(Chan*, Fcall*, Fcall*) ={	[Tnop]		f_nop,	[Tosession]	f_session,	[Tsession]	f_session,	[Tflush]	f_flush,	[Toattach]	f_attach,	[Tattach]	f_attach,	[Tclone]	f_clone,	[Twalk]		f_walk,	[Topen]		f_open,	[Tcreate]	f_create,	[Tread]		f_read,	[Twrite]	f_write,	[Tclunk]	f_clunk,	[Tremove]	f_remove,	[Tstat]		f_stat,	[Twstat]	f_wstat,	[Tclwalk]	f_clwalk,};interror9p1(Chan* cp, Msgbuf* mb){	Msgbuf *mb1;	print("type=%d count=%d\n", mb->data[0], mb->count);	print(" %.2x %.2x %.2x %.2x\n",		mb->data[1]&0xff, mb->data[2]&0xff,		mb->data[3]&0xff, mb->data[4]&0xff);	print(" %.2x %.2x %.2x %.2x\n",		mb->data[5]&0xff, mb->data[6]&0xff,		mb->data[7]&0xff, mb->data[8]&0xff);	print(" %.2x %.2x %.2x %.2x\n",		mb->data[9]&0xff, mb->data[10]&0xff,		mb->data[11]&0xff, mb->data[12]&0xff);	mb1 = mballoc(3, cp, Mbreply4);	mb1->data[0] = Rnop;	/* your nop was ok */	mb1->data[1] = ~0;	mb1->data[2] = ~0;	mb1->count = 3;	mb1->param = mb->param;	send(cp->reply, mb1);	return 1;}intserve9p1(Msgbuf* mb){	int t, n;	Chan *cp;	Msgbuf *mb1;	Fcall fi, fo;	cp = mb->chan;	if(convM2S9p1(mb->data, &fi, mb->count) == 0){		if(cp->protocol == nil)			return 0;		print("9p1: bad M2S conversion\n");		return error9p1(cp, mb);	}	t = fi.type;	if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) {		print("9p1: bad message type\n");		return error9p1(cp, mb);	}	/*	 * allocate reply message	 */	if(t == Tread) {		mb1 = mballoc(MAXMSG+MAXDAT, cp, Mbreply2);		fo.data = (char*)(mb1->data + 8);	} else		mb1 = mballoc(MAXMSG, cp, Mbreply3);	/*	 * call the file system	 */	cons.work[0].count++;	cons.work[1].count++;	cons.work[2].count++;	cp->work.count++;	cons.rate[0].count += mb->count;	cons.rate[1].count += mb->count;	cons.rate[2].count += mb->count;	cp->rate.count += mb->count;	fo.err = 0;	(*call9p1[t])(cp, &fi, &fo);	fo.type = t+1;	fo.tag = fi.tag;	if(fo.err) {		if(cons.flags&errorflag)			print("	type %d: error: %s\n", t,				errstr9p[fo.err]);		if(CHAT(cp))			print("	error: %s\n", errstr9p[fo.err]);		fo.type = Rerror;		strncpy(fo.ename, errstr9p[fo.err], sizeof(fo.ename));	}	n = convS2M9p1(&fo, mb1->data);	if(n == 0) {		print("9p1: bad S2M conversion\n");		mbfree(mb1);		return error9p1(cp, mb);	}	mb1->count = n;	mb1->param = mb->param;	cons.rate[0].count += n;	cons.rate[1].count += n;	cons.rate[2].count += n;	cp->rate.count += n;	send(cp->reply, mb1);	return 1;}

⌨️ 快捷键说明

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