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

📄 sub.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"all.h"#include	"io.h"#ifdef OLD#define swaboff swab4#else#define swaboff swab8#endifFilsys*fsstr(char *p){	Filsys *fs;	for(fs=filsys; fs->name; fs++)		if(strcmp(fs->name, p) == 0)			return fs;	return 0;}Filsys*dev2fs(Device *dev){	Filsys *fs;	for(fs=filsys; fs->name; fs++)		if(fs->dev == dev)			return fs;	return 0;}/* * allocate 'count' contiguous channels * of type 'type' and return pointer to base */Chan*chaninit(int type, int count, int data){	uchar *p;	Chan *cp, *icp;	int i;	p = ialloc(count * (sizeof(Chan)+data), 0);	icp = (Chan*)p;	for(i=0; i<count; i++) {		cp = (Chan*)p;		cp->next = chans;		chans = cp;		cp->type = type;		cp->chan = cons.chano;		cons.chano++;		strncpy(cp->whoname, "<none>", sizeof(cp->whoname));		dofilter(&cp->work, C0a, C0b, 1);		dofilter(&cp->rate, C0a, C0b, 1000);		wlock(&cp->reflock);		wunlock(&cp->reflock);		rlock(&cp->reflock);		runlock(&cp->reflock);		p += sizeof(Chan);		if(data){			cp->pdata = p;			p += data;		}	}	return icp;}voidfileinit(Chan *cp){	File *f, *prev;	Tlock *t;	int h;loop:	lock(&flock);	for (h=0; h<nelem(flist); h++)		for (prev=0, f=flist[h]; f; prev=f, f=f->next) {			if(f->cp != cp)				continue;			if(prev) {				prev->next = f->next;				f->next = flist[h];				flist[h] = f;			}			flist[h] = f->next;			unlock(&flock);			qlock(f);			if(t = f->tlock) {				if(t->file == f)					t->time = 0;	/* free the lock */				f->tlock = 0;			}			if(f->open & FREMOV)				doremove(f, 0);			freewp(f->wpath);			f->open = 0;			authfree(f->auth);			f->auth = 0;			f->cp = 0;			qunlock(f);			goto loop;		}	unlock(&flock);}#define NOFID (ulong)~0/* * returns a locked file structure */File*filep(Chan *cp, ulong fid, int flag){	File *f;	int h;	if(fid == NOFID)		return 0;	h = (long)cp + fid;	if(h < 0)		h = ~h;	h %= nelem(flist);loop:	lock(&flock);	for(f=flist[h]; f; f=f->next)		if(f->fid == fid && f->cp == cp){			/*			 * Already in use is an error			 * when called from attach or clone (walk			 * in 9P2000). The console uses FID[12] and			 * never clunks them so catch that case.			 */			if(flag == 0 || cp == cons.chan)				goto out;			unlock(&flock);			return 0;		}	if(flag) {		f = newfp();		if(f) {			f->fid = fid;			f->cp = cp;			f->wpath = 0;			f->tlock = 0;			f->doffset = 0;			f->dslot = 0;			f->auth = 0;			f->next = flist[h];			flist[h] = f;			goto out;		}	}	unlock(&flock);	return 0;out:	unlock(&flock);	qlock(f);	if(f->fid == fid && f->cp == cp)		return f;	qunlock(f);	goto loop;}/* * always called with flock locked */File*newfp(void){	static int first;	File *f;	int start, i;	i = first;	start = i;	do {		f = &files[i];		i++;		if(i >= conf.nfile)			i = 0;		if(f->cp)			continue;		first = i;		return f;	} while(i != start);	print("out of files\n");	return 0;}voidfreefp(File *fp){	Chan *cp;	File *f, *prev;	int h;	if(!fp || !(cp = fp->cp))		return;	h = (long)cp + fp->fid;	if(h < 0)		h = ~h;	h %= nelem(flist);	lock(&flock);	for(prev=0,f=flist[h]; f; prev=f,f=f->next)		if(f == fp) {			if(prev)				prev->next = f->next;			else				flist[h] = f->next;			break;		}	fp->cp = 0;	unlock(&flock);}intiaccess(File *f, Dentry *d, int m){	/* uid none gets only other permissions */	if(f->uid != 0) {		/*		 * owner		 */		if(f->uid == d->uid)			if((m<<6) & d->mode)				return 0;		/*		 * group membership		 */		if(ingroup(f->uid, d->gid))			if((m<<3) & d->mode)				return 0;	}	/*	 * other	 */	if(m & d->mode) {		if((d->mode & DDIR) && (m == DEXEC))			return 0;		if(!ingroup(f->uid, 9999))			return 0;	}	/*	 * various forms of superuser	 */	if(wstatallow)		return 0;	if(duallow != 0 && duallow == f->uid)		if((d->mode & DDIR) && (m == DREAD || m == DEXEC))			return 0;	return 1;}Tlock*tlocked(Iobuf *p, Dentry *d){	Tlock *t, *t1;	Off qpath;	Timet tim;	Device *dev;	tim = toytime();	qpath = d->qid.path;	dev = p->dev;again:	t1 = 0;	for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {		if(t->qpath == qpath)		if(t->time >= tim)		if(t->dev == dev)			return nil;		/* its locked */		if(t1 != nil && t->time == 0)			t1 = t;			/* remember free lock */	}	if(t1 == 0) {		// reclaim old locks		lock(&tlocklock);		for(t=tlocks+NTLOCK-1; t>=tlocks; t--)			if(t->time < tim) {				t->time = 0;				t1 = t;			}		unlock(&tlocklock);	}	if(t1) {		lock(&tlocklock);		if(t1->time != 0) {			unlock(&tlocklock);			goto again;		}		t1->dev = dev;		t1->qpath = qpath;		t1->time = tim + TLOCK;		unlock(&tlocklock);	}	/* botch	 * out of tlock nodes simulates	 * a locked file	 */	return t1;}Wpath*newwp(void){	static int si = 0;	int i;	Wpath *w, *sw, *ew;	i = si + 1;	if(i < 0 || i >= conf.nwpath)		i = 0;	si = i;	sw = &wpaths[i];	ew = &wpaths[conf.nwpath];	for(w=sw;;) {		w++;		if(w >= ew)			w = &wpaths[0];		if(w == sw) {			print("out of wpaths\n");			return 0;		}		if(w->refs)			continue;		lock(&wpathlock);		if(w->refs) {			unlock(&wpathlock);			continue;		}		w->refs = 1;		w->up = 0;		unlock(&wpathlock);		return w;	}}voidfreewp(Wpath *w){	lock(&wpathlock);	for(; w; w=w->up)		w->refs--;	unlock(&wpathlock);}Offqidpathgen(Device *dev){	Iobuf *p;	Superb *sb;	Off path;	p = getbuf(dev, superaddr(dev), Bread|Bmod);	if(!p || checktag(p, Tsuper, QPSUPER))		panic("newqid: super block");	sb = (Superb*)p->iobuf;	sb->qidgen++;	path = sb->qidgen;	putbuf(p);	return path;}/* truncating to length > 0 */static voidtruncfree(Truncstate *ts, Device *dev, int d, Iobuf *p, int i){	int pastlast;	Off a;	pastlast = ts->pastlast;	a = ((Off *)p->iobuf)[i];	if (d > 0 || pastlast)		buffree(dev, a, d, ts);	if (pastlast) {		((Off *)p->iobuf)[i] = 0;		p->flags |= Bmod|Bimm;	} else if (d == 0 && ts->relblk == ts->lastblk)		ts->pastlast = 1;	if (d == 0)		ts->relblk++;}/* * free the block at `addr' on dev. * if it's an indirect block (d [depth] > 0), * first recursively free all the blocks it names. * * ts->relblk is the block number within the file of this * block (or the first data block eventually pointed to via * this indirect block). */voidbuffree(Device *dev, Off addr, int d, Truncstate *ts){	Iobuf *p;	Off a;	int i, pastlast;	if(!addr)		return;	pastlast = (ts == nil? 1: ts->pastlast);	/*	 * if this is an indirect block, recurse and free any	 * suitable blocks within it (possibly via further indirect blocks).	 */	if(d > 0) {		d--;		p = getbuf(dev, addr, Bread);		if(p) {			if (ts == nil)		/* common case: create */				for(i=INDPERBUF-1; i>=0; i--) {					a = ((Off *)p->iobuf)[i];					buffree(dev, a, d, nil);				}			else			/* wstat truncation */				for (i = 0; i < INDPERBUF; i++)					truncfree(ts, dev, d, p, i);			putbuf(p);		}	}	if (!pastlast)		return;	/*	 * having zeroed the pointer to this block, add it to the free list.	 * stop outstanding i/o	 */	p = getbuf(dev, addr, Bprobe);	if(p) {		p->flags &= ~(Bmod|Bimm);		putbuf(p);	}	/*	 * dont put written worm	 * blocks into free list	 */	if(dev->type == Devcw) {		i = cwfree(dev, addr);		if(i)			return;	}	p = getbuf(dev, superaddr(dev), Bread|Bmod);	if(!p || checktag(p, Tsuper, QPSUPER))		panic("buffree: super block");	addfree(dev, addr, (Superb*)p->iobuf);	putbuf(p);}Offbufalloc(Device *dev, int tag, long qid, int uid){	Iobuf *bp, *p;	Superb *sb;	Off a, n;	p = getbuf(dev, superaddr(dev), Bread|Bmod);	if(!p || checktag(p, Tsuper, QPSUPER)) {		print("bufalloc: super block\n");		if(p)			putbuf(p);		return 0;	}	sb = (Superb*)p->iobuf;loop:	n = --sb->fbuf.nfree;	sb->tfree--;	if(n < 0 || n >= FEPERBUF) {		print("bufalloc: %Z: bad freelist\n", dev);		n = 0;		sb->fbuf.free[0] = 0;	}	a = sb->fbuf.free[n];	if(n <= 0) {		if(a == 0) {			sb->tfree = 0;			sb->fbuf.nfree = 1;			if(dev->type == Devcw) {				n = uid;				if(n < 0 || n >= nelem(growacct))					n = 0;				growacct[n]++;				if(cwgrow(dev, sb, uid))					goto loop;			}			putbuf(p);			print("fs %Z full uid=%d\n", dev, uid);			return 0;		}		bp = getbuf(dev, a, Bread);		if(!bp || checktag(bp, Tfree, QPNONE)) {			if(bp)				putbuf(bp);			putbuf(p);			return 0;		}		sb->fbuf = *(Fbuf*)bp->iobuf;		putbuf(bp);	}	bp = getbuf(dev, a, Bmod);	memset(bp->iobuf, 0, RBUFSIZE);	settag(bp, tag, qid);	if(tag == Tind1 || tag == Tind2 || tag == Tdir)		bp->flags |= Bimm;	putbuf(bp);	putbuf(p);	return a;}/* * what are legal characters in a name? * only disallow control characters. * a) utf avoids control characters. * b) '/' may not be the separator */intcheckname(char *n){	int i, c;	for(i=0; i<NAMELEN; i++) {		c = *n & 0xff;		if(c == 0) {			if(i == 0)				return 1;			memset(n, 0, NAMELEN-i);			return 0;		}		if(c <= 040)			return 1;		n++;	}	return 1;	/* too long */}voidaddfree(Device *dev, Off addr, Superb *sb){	int n;	Iobuf *p;	n = sb->fbuf.nfree;	if(n < 0 || n > FEPERBUF)		panic("addfree: bad freelist");	if(n >= FEPERBUF) {		p = getbuf(dev, addr, Bmod|Bimm);		if(p == 0)			panic("addfree: getbuf");		*(Fbuf*)p->iobuf = sb->fbuf;		settag(p, Tfree, QPNONE);		putbuf(p);		n = 0;	}	sb->fbuf.free[n++] = addr;	sb->fbuf.nfree = n;	sb->tfree++;	if(addr >= sb->fsize)		sb->fsize = addr+1;}static intYfmt(Fmt* fmt){	Chan *cp;	char s[20];	cp = va_arg(fmt->args, Chan*);	sprint(s, "C%d.%.3d", cp->type, cp->chan);	return fmtstrcpy(fmt, s);}static intZfmt(Fmt* fmt){	Device *d;	int c, c1;	char s[100];	d = va_arg(fmt->args, Device*);	if(d == 0) {		sprint(s, "Z***");		goto out;	}	switch(d->type) {	default:		sprint(s, "D%d", d->type);		break;	case Devwren:		c = 'w';		goto d1;	case Devide:		c = 'h';		goto d1;	case Devmarvsata:		c = 'm';		goto d1;	case Devworm:		c = 'r';		goto d1;	case Devlworm:		c = 'l';		goto d1;	d1:		if(d->wren.ctrl == 0 && d->wren.lun == 0)			sprint(s, "%c%d", c, d->wren.targ);		else			sprint(s, "%c%d.%d.%d", c, d->wren.ctrl, d->wren.targ, d->wren.lun);		break;	case Devmcat:		c = '(';		c1 = ')';		goto d2;	case Devmlev:		c = '[';		c1 = ']';		goto d2;	case Devmirr:		c = '{';		c1 = '}';	d2:		if(d->cat.first == d->cat.last)			sprint(s, "%c%Z%c", c, d->cat.first, c1);		else		if(d->cat.first->link == d->cat.last)			sprint(s, "%c%Z%Z%c", c, d->cat.first, d->cat.last, c1);		else			sprint(s, "%c%Z-%Z%c", c, d->cat.first, d->cat.last, c1);		break;	case Devro:		sprint(s, "o%Z%Z", d->ro.parent->cw.c, d->ro.parent->cw.w);		break;	case Devcw:		sprint(s, "c%Z%Z", d->cw.c, d->cw.w);		break;	case Devjuke:		sprint(s, "j%Z%Z", d->j.j, d->j.m);		break;	case Devfworm:		sprint(s, "f%Z", d->fw.fw);		break;	case Devpart:		sprint(s, "p(%Z)%ld.%ld",			d->part.d, d->part.base, d->part.size);		break;	case Devswab:		sprint(s, "x%Z", d->swab.d);		break;	case Devnone:		sprint(s, "n");		break;	}out:	return fmtstrcpy(fmt, s);}static intWfmt(Fmt* fmt){	Filter* a;	char s[30];	a = va_arg(fmt->args, Filter*);	snprint(s, sizeof s, "%lud", fdf(a->filter, a->c3*a->c1));	return fmtstrcpy(fmt, s);}static intGfmt(Fmt* fmt){	int t;	char *s;	t = va_arg(fmt->args, int);	s = "<badtag>";	if(t >= 0 && t < MAXTAG)		s = tagnames[t];	return fmtstrcpy(fmt, s);}static intEfmt(Fmt* fmt){	char s[64];	uchar *p;	p = va_arg(fmt->args, uchar*);	sprint(s, "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux",		p[0], p[1], p[2], p[3], p[4], p[5]);	return fmtstrcpy(fmt, s);}static intIfmt(Fmt* fmt){	char s[64];	uchar *p;	p = va_arg(fmt->args, uchar*);	sprint(s, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);	return fmtstrcpy(fmt, s);}voidformatinit(void){	quotefmtinstall();	fmtinstall('Y', Yfmt);	/* print channels */	fmtinstall('Z', Zfmt);	/* print devices */	fmtinstall('W', Wfmt);	/* print filters */	fmtinstall('G', Gfmt);	/* print tags */	fmtinstall('T', Tfmt);	/* print times */	fmtinstall('E', Efmt);	/* print ether addresses */	fmtinstall('I', Ifmt);	/* print ip addresses */}voidrootream(Device *dev, Off addr){	Iobuf *p;	Dentry *d;	p = getbuf(dev, addr, Bmod|Bimm);	memset(p->iobuf, 0, RBUFSIZE);	settag(p, Tdir, QPROOT);	d = getdir(p, 0);	strcpy(d->name, "/");	d->uid = -1;	d->gid = -1;	d->mode = DALLOC | DDIR |		((DREAD|DEXEC) << 6) |		((DREAD|DEXEC) << 3) |		((DREAD|DEXEC) << 0);	d->qid = QID9P1(QPROOT|QPDIR,0);	d->atime = time();	d->mtime = d->atime;	d->muid = 0;	putbuf(p);}voidsuperream(Device *dev, Off addr){	Iobuf *p;	Superb *s;	Off i;	p = getbuf(dev, addr, Bmod|Bimm);	memset(p->iobuf, 0, RBUFSIZE);	settag(p, Tsuper, QPSUPER);	s = (Superb*)p->iobuf;	s->fstart = 2;	s->fsize = devsize(dev);	s->fbuf.nfree = 1;	s->qidgen = 10;#ifdef AUTOSWAB	s->magic = 0x123456789abcdef0;#endif	for(i=s->fsize-1; i>=addr+2; i--)		addfree(dev, i, s);	putbuf(p);}struct{	Lock;	Msgbuf	*smsgbuf;	Msgbuf	*lmsgbuf;} msgalloc;/* * pre-allocate some message buffers at boot time. * if this supply is exhausted, more will be allocated as needed. */voidmbinit(void){	Msgbuf *mb;	Rabuf *rb;	int i;	lock(&msgalloc);	unlock(&msgalloc);	msgalloc.lmsgbuf = 0;	msgalloc.smsgbuf = 0;	for(i=0; i<conf.nlgmsg; i++) {		mb = ialloc(sizeof(Msgbuf), 0);		if(1)			mb->xdata = ialloc(LARGEBUF+256, 256);		else			mb->xdata = ialloc(LARGEBUF+OFFMSG, LINESIZE);		mb->flags = LARGE;		mb->free = 0;		mbfree(mb);		cons.nlarge++;	}	for(i=0; i<conf.nsmmsg; i++) {		mb = ialloc(sizeof(Msgbuf), 0);		if(1)			mb->xdata = ialloc(SMALLBUF+256, 256);		else			mb->xdata = ialloc(SMALLBUF+OFFMSG, LINESIZE);		mb->flags = 0;		mb->free = 0;		mbfree(mb);		cons.nsmall++;	}	memset(mballocs, 0, sizeof(mballocs));

⌨️ 快捷键说明

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