xref: /plan9/sys/src/cmd/cwfs/sub.c (revision eba00c1180f26027fec6be9f76c54eccfce0d97b)
101a344a2SDavid du Colombier #include "all.h"
201a344a2SDavid du Colombier #include "io.h"
301a344a2SDavid du Colombier 
401a344a2SDavid du Colombier enum {
501a344a2SDavid du Colombier 	Slop = 256,	/* room at the start of a message buf for proto hdrs */
601a344a2SDavid du Colombier };
701a344a2SDavid du Colombier 
801a344a2SDavid du Colombier Filsys*
fsstr(char * p)901a344a2SDavid du Colombier fsstr(char *p)
1001a344a2SDavid du Colombier {
1101a344a2SDavid du Colombier 	Filsys *fs;
1201a344a2SDavid du Colombier 
1301a344a2SDavid du Colombier 	for(fs=filsys; fs->name; fs++)
1401a344a2SDavid du Colombier 		if(strcmp(fs->name, p) == 0)
1501a344a2SDavid du Colombier 			return fs;
1601a344a2SDavid du Colombier 	return 0;
1701a344a2SDavid du Colombier }
1801a344a2SDavid du Colombier 
1901a344a2SDavid du Colombier Filsys*
dev2fs(Device * dev)2001a344a2SDavid du Colombier dev2fs(Device *dev)
2101a344a2SDavid du Colombier {
2201a344a2SDavid du Colombier 	Filsys *fs;
2301a344a2SDavid du Colombier 
2401a344a2SDavid du Colombier 	for(fs=filsys; fs->name; fs++)
2501a344a2SDavid du Colombier 		if(fs->dev == dev)
2601a344a2SDavid du Colombier 			return fs;
2701a344a2SDavid du Colombier 	return 0;
2801a344a2SDavid du Colombier }
2901a344a2SDavid du Colombier 
3001a344a2SDavid du Colombier /*
3101a344a2SDavid du Colombier  * allocate 'count' contiguous channels
3201a344a2SDavid du Colombier  * of type 'type' and return pointer to base
3301a344a2SDavid du Colombier  */
3401a344a2SDavid du Colombier Chan*
fs_chaninit(int type,int count,int data)3501a344a2SDavid du Colombier fs_chaninit(int type, int count, int data)
3601a344a2SDavid du Colombier {
3701a344a2SDavid du Colombier 	uchar *p;
3801a344a2SDavid du Colombier 	Chan *cp, *icp;
3901a344a2SDavid du Colombier 	int i;
4001a344a2SDavid du Colombier 
4101a344a2SDavid du Colombier 	p = malloc(count * (sizeof(Chan)+data));
4201a344a2SDavid du Colombier 	icp = (Chan*)p;
4301a344a2SDavid du Colombier 	for(i = 0; i < count; i++) {
4401a344a2SDavid du Colombier 		cp = (Chan*)p;
4501a344a2SDavid du Colombier 		cp->next = chans;
4601a344a2SDavid du Colombier 		chans = cp;
4701a344a2SDavid du Colombier 		cp->type = type;
4801a344a2SDavid du Colombier 		cp->chan = cons.chano;
4901a344a2SDavid du Colombier 		cons.chano++;
5001a344a2SDavid du Colombier 		strncpy(cp->whoname, "<none>", sizeof cp->whoname);
5101a344a2SDavid du Colombier 		wlock(&cp->reflock);
5201a344a2SDavid du Colombier 		wunlock(&cp->reflock);
5301a344a2SDavid du Colombier 		rlock(&cp->reflock);
5401a344a2SDavid du Colombier 		runlock(&cp->reflock);
5501a344a2SDavid du Colombier 
5601a344a2SDavid du Colombier 		p += sizeof(Chan);
5701a344a2SDavid du Colombier 		if(data){
5801a344a2SDavid du Colombier 			cp->pdata = p;
5901a344a2SDavid du Colombier 			p += data;
6001a344a2SDavid du Colombier 		}
6101a344a2SDavid du Colombier 	}
6201a344a2SDavid du Colombier 	return icp;
6301a344a2SDavid du Colombier }
6401a344a2SDavid du Colombier 
6501a344a2SDavid du Colombier void
fileinit(Chan * cp)6601a344a2SDavid du Colombier fileinit(Chan *cp)
6701a344a2SDavid du Colombier {
6801a344a2SDavid du Colombier 	File *f, *prev;
6901a344a2SDavid du Colombier 	Tlock *t;
7001a344a2SDavid du Colombier 	int h;
7101a344a2SDavid du Colombier 
7201a344a2SDavid du Colombier loop:
7301a344a2SDavid du Colombier 	lock(&flock);
7401a344a2SDavid du Colombier 	for (h=0; h < nelem(flist); h++)
7501a344a2SDavid du Colombier 		for (prev=0, f = flist[h]; f; prev=f, f=f->next) {
7601a344a2SDavid du Colombier 			if(f->cp != cp)
7701a344a2SDavid du Colombier 				continue;
7801a344a2SDavid du Colombier 			if(prev) {
7901a344a2SDavid du Colombier 				prev->next = f->next;
8001a344a2SDavid du Colombier 				f->next = flist[h];
8101a344a2SDavid du Colombier 				flist[h] = f;
8201a344a2SDavid du Colombier 			}
8301a344a2SDavid du Colombier 			flist[h] = f->next;
8401a344a2SDavid du Colombier 			unlock(&flock);
8501a344a2SDavid du Colombier 
8601a344a2SDavid du Colombier 			qlock(f);
8701a344a2SDavid du Colombier 			if(t = f->tlock) {
8801a344a2SDavid du Colombier 				if(t->file == f)
8901a344a2SDavid du Colombier 					t->time = 0;	/* free the lock */
9001a344a2SDavid du Colombier 				f->tlock = 0;
9101a344a2SDavid du Colombier 			}
9201a344a2SDavid du Colombier 			if(f->open & FREMOV)
9301a344a2SDavid du Colombier 				doremove(f, 0);
9401a344a2SDavid du Colombier 			freewp(f->wpath);
9501a344a2SDavid du Colombier 			f->open = 0;
9601a344a2SDavid du Colombier 			authfree(f->auth);
9701a344a2SDavid du Colombier 			f->auth = 0;
9801a344a2SDavid du Colombier 			f->cp = 0;
9901a344a2SDavid du Colombier 			qunlock(f);
10001a344a2SDavid du Colombier 			goto loop;
10101a344a2SDavid du Colombier 		}
10201a344a2SDavid du Colombier 	unlock(&flock);
10301a344a2SDavid du Colombier }
10401a344a2SDavid du Colombier 
10501a344a2SDavid du Colombier enum { NOFID = (ulong)~0 };
10601a344a2SDavid du Colombier 
10701a344a2SDavid du Colombier /*
10801a344a2SDavid du Colombier  * returns a locked file structure
10901a344a2SDavid du Colombier  */
11001a344a2SDavid du Colombier File*
filep(Chan * cp,ulong fid,int flag)11101a344a2SDavid du Colombier filep(Chan *cp, ulong fid, int flag)
11201a344a2SDavid du Colombier {
11301a344a2SDavid du Colombier 	File *f;
11401a344a2SDavid du Colombier 	int h;
11501a344a2SDavid du Colombier 
11601a344a2SDavid du Colombier 	if(fid == NOFID)
11701a344a2SDavid du Colombier 		return 0;
11801a344a2SDavid du Colombier 
119223a0358SDavid du Colombier 	h = (long)(uintptr)cp + fid;
12001a344a2SDavid du Colombier 	if(h < 0)
12101a344a2SDavid du Colombier 		h = ~h;
12201a344a2SDavid du Colombier 	h %= nelem(flist);
12301a344a2SDavid du Colombier 
12401a344a2SDavid du Colombier loop:
12501a344a2SDavid du Colombier 	lock(&flock);
12601a344a2SDavid du Colombier 	for(f=flist[h]; f; f=f->next)
12701a344a2SDavid du Colombier 		if(f->fid == fid && f->cp == cp){
12801a344a2SDavid du Colombier 			/*
12901a344a2SDavid du Colombier 			 * Already in use is an error
13001a344a2SDavid du Colombier 			 * when called from attach or clone (walk
13101a344a2SDavid du Colombier 			 * in 9P2000). The console uses FID[12] and
13201a344a2SDavid du Colombier 			 * never clunks them so catch that case.
13301a344a2SDavid du Colombier 			 */
13401a344a2SDavid du Colombier 			if(flag == 0 || cp == cons.chan)
13501a344a2SDavid du Colombier 				goto out;
13601a344a2SDavid du Colombier 			unlock(&flock);
13701a344a2SDavid du Colombier 			return 0;
13801a344a2SDavid du Colombier 		}
13901a344a2SDavid du Colombier 
14001a344a2SDavid du Colombier 	if(flag) {
14101a344a2SDavid du Colombier 		f = newfp();
14201a344a2SDavid du Colombier 		if(f) {
14301a344a2SDavid du Colombier 			f->fid = fid;
14401a344a2SDavid du Colombier 			f->cp = cp;
14501a344a2SDavid du Colombier 			f->wpath = 0;
14601a344a2SDavid du Colombier 			f->tlock = 0;
14701a344a2SDavid du Colombier 			f->doffset = 0;
14801a344a2SDavid du Colombier 			f->dslot = 0;
14901a344a2SDavid du Colombier 			f->auth = 0;
15001a344a2SDavid du Colombier 			f->next = flist[h];
15101a344a2SDavid du Colombier 			flist[h] = f;
15201a344a2SDavid du Colombier 			goto out;
15301a344a2SDavid du Colombier 		}
15401a344a2SDavid du Colombier 	}
15501a344a2SDavid du Colombier 	unlock(&flock);
15601a344a2SDavid du Colombier 	return 0;
15701a344a2SDavid du Colombier 
15801a344a2SDavid du Colombier out:
15901a344a2SDavid du Colombier 	unlock(&flock);
16001a344a2SDavid du Colombier 	qlock(f);
16101a344a2SDavid du Colombier 	if(f->fid == fid && f->cp == cp)
16201a344a2SDavid du Colombier 		return f;
16301a344a2SDavid du Colombier 	qunlock(f);
16401a344a2SDavid du Colombier 	goto loop;
16501a344a2SDavid du Colombier }
16601a344a2SDavid du Colombier 
16701a344a2SDavid du Colombier /*
16801a344a2SDavid du Colombier  * always called with flock locked
16901a344a2SDavid du Colombier  */
17001a344a2SDavid du Colombier File*
newfp(void)17101a344a2SDavid du Colombier newfp(void)
17201a344a2SDavid du Colombier {
17301a344a2SDavid du Colombier 	static int first;
17401a344a2SDavid du Colombier 	File *f;
17501a344a2SDavid du Colombier 	int start, i;
17601a344a2SDavid du Colombier 
17701a344a2SDavid du Colombier 	i = first;
17801a344a2SDavid du Colombier 	start = i;
17901a344a2SDavid du Colombier 	do {
18001a344a2SDavid du Colombier 		f = &files[i];
18101a344a2SDavid du Colombier 		i++;
18201a344a2SDavid du Colombier 		if(i >= conf.nfile)
18301a344a2SDavid du Colombier 			i = 0;
18401a344a2SDavid du Colombier 		if(f->cp)
18501a344a2SDavid du Colombier 			continue;
18601a344a2SDavid du Colombier 		first = i;
18701a344a2SDavid du Colombier 		return f;
18801a344a2SDavid du Colombier 	} while(i != start);
18901a344a2SDavid du Colombier 
19001a344a2SDavid du Colombier 	print("out of files\n");
19101a344a2SDavid du Colombier 	return 0;
19201a344a2SDavid du Colombier }
19301a344a2SDavid du Colombier 
19401a344a2SDavid du Colombier void
freefp(File * fp)19501a344a2SDavid du Colombier freefp(File *fp)
19601a344a2SDavid du Colombier {
19701a344a2SDavid du Colombier 	Chan *cp;
19801a344a2SDavid du Colombier 	File *f, *prev;
19901a344a2SDavid du Colombier 	int h;
20001a344a2SDavid du Colombier 
20101a344a2SDavid du Colombier 	if(!fp || !(cp = fp->cp))
20201a344a2SDavid du Colombier 		return;
20301a344a2SDavid du Colombier 
204223a0358SDavid du Colombier 	h = (long)(uintptr)cp + fp->fid;
20501a344a2SDavid du Colombier 	if(h < 0)
20601a344a2SDavid du Colombier 		h = ~h;
20701a344a2SDavid du Colombier 	h %= nelem(flist);
20801a344a2SDavid du Colombier 
20901a344a2SDavid du Colombier 	lock(&flock);
21001a344a2SDavid du Colombier 	for(prev=0,f=flist[h]; f; prev=f,f=f->next)
21101a344a2SDavid du Colombier 		if(f == fp) {
21201a344a2SDavid du Colombier 			if(prev)
21301a344a2SDavid du Colombier 				prev->next = f->next;
21401a344a2SDavid du Colombier 			else
21501a344a2SDavid du Colombier 				flist[h] = f->next;
21601a344a2SDavid du Colombier 			break;
21701a344a2SDavid du Colombier 		}
21801a344a2SDavid du Colombier 	fp->cp = 0;
21901a344a2SDavid du Colombier 	unlock(&flock);
22001a344a2SDavid du Colombier }
22101a344a2SDavid du Colombier 
22201a344a2SDavid du Colombier int
iaccess(File * f,Dentry * d,int m)22301a344a2SDavid du Colombier iaccess(File *f, Dentry *d, int m)
22401a344a2SDavid du Colombier {
22501a344a2SDavid du Colombier 	/* uid none gets only other permissions */
22601a344a2SDavid du Colombier 	if(f->uid != 0) {
22701a344a2SDavid du Colombier 		/*
22801a344a2SDavid du Colombier 		 * owner
22901a344a2SDavid du Colombier 		 */
23001a344a2SDavid du Colombier 		if(f->uid == d->uid)
23101a344a2SDavid du Colombier 			if((m<<6) & d->mode)
23201a344a2SDavid du Colombier 				return 0;
23301a344a2SDavid du Colombier 		/*
23401a344a2SDavid du Colombier 		 * group membership
23501a344a2SDavid du Colombier 		 */
23601a344a2SDavid du Colombier 		if(ingroup(f->uid, d->gid))
23701a344a2SDavid du Colombier 			if((m<<3) & d->mode)
23801a344a2SDavid du Colombier 				return 0;
23901a344a2SDavid du Colombier 	}
24001a344a2SDavid du Colombier 
24101a344a2SDavid du Colombier 	/*
24201a344a2SDavid du Colombier 	 * other
24301a344a2SDavid du Colombier 	 */
24401a344a2SDavid du Colombier 	if(m & d->mode) {
24501a344a2SDavid du Colombier 		if((d->mode & DDIR) && (m == DEXEC))
24601a344a2SDavid du Colombier 			return 0;
24701a344a2SDavid du Colombier 		if(!ingroup(f->uid, 9999))
24801a344a2SDavid du Colombier 			return 0;
24901a344a2SDavid du Colombier 	}
25001a344a2SDavid du Colombier 
25101a344a2SDavid du Colombier 	/*
25201a344a2SDavid du Colombier 	 * various forms of superuser
25301a344a2SDavid du Colombier 	 */
25401a344a2SDavid du Colombier 	if(wstatallow)
25501a344a2SDavid du Colombier 		return 0;
25601a344a2SDavid du Colombier 	if(duallow != 0 && duallow == f->uid)
25701a344a2SDavid du Colombier 		if((d->mode & DDIR) && (m == DREAD || m == DEXEC))
25801a344a2SDavid du Colombier 			return 0;
25901a344a2SDavid du Colombier 
26001a344a2SDavid du Colombier 	return 1;
26101a344a2SDavid du Colombier }
26201a344a2SDavid du Colombier 
26301a344a2SDavid du Colombier Tlock*
tlocked(Iobuf * p,Dentry * d)26401a344a2SDavid du Colombier tlocked(Iobuf *p, Dentry *d)
26501a344a2SDavid du Colombier {
26601a344a2SDavid du Colombier 	Tlock *t, *t1;
26701a344a2SDavid du Colombier 	Off qpath;
26801a344a2SDavid du Colombier 	Timet tim;
26901a344a2SDavid du Colombier 	Device *dev;
27001a344a2SDavid du Colombier 
27101a344a2SDavid du Colombier 	tim = toytime();
27201a344a2SDavid du Colombier 	qpath = d->qid.path;
27301a344a2SDavid du Colombier 	dev = p->dev;
27401a344a2SDavid du Colombier 
27501a344a2SDavid du Colombier again:
27601a344a2SDavid du Colombier 	t1 = 0;
27701a344a2SDavid du Colombier 	for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
27801a344a2SDavid du Colombier 		if(t->qpath == qpath)
27901a344a2SDavid du Colombier 		if(t->time >= tim)
28001a344a2SDavid du Colombier 		if(t->dev == dev)
28101a344a2SDavid du Colombier 			return nil;		/* its locked */
28201a344a2SDavid du Colombier 		if(t1 != nil && t->time == 0)
28301a344a2SDavid du Colombier 			t1 = t;			/* remember free lock */
28401a344a2SDavid du Colombier 	}
28501a344a2SDavid du Colombier 	if(t1 == 0) {
28601a344a2SDavid du Colombier 		// reclaim old locks
28701a344a2SDavid du Colombier 		lock(&tlocklock);
28801a344a2SDavid du Colombier 		for(t=tlocks+NTLOCK-1; t>=tlocks; t--)
28901a344a2SDavid du Colombier 			if(t->time < tim) {
29001a344a2SDavid du Colombier 				t->time = 0;
29101a344a2SDavid du Colombier 				t1 = t;
29201a344a2SDavid du Colombier 			}
29301a344a2SDavid du Colombier 		unlock(&tlocklock);
29401a344a2SDavid du Colombier 	}
29501a344a2SDavid du Colombier 	if(t1) {
29601a344a2SDavid du Colombier 		lock(&tlocklock);
29701a344a2SDavid du Colombier 		if(t1->time != 0) {
29801a344a2SDavid du Colombier 			unlock(&tlocklock);
29901a344a2SDavid du Colombier 			goto again;
30001a344a2SDavid du Colombier 		}
30101a344a2SDavid du Colombier 		t1->dev = dev;
30201a344a2SDavid du Colombier 		t1->qpath = qpath;
30301a344a2SDavid du Colombier 		t1->time = tim + TLOCK;
30401a344a2SDavid du Colombier 		unlock(&tlocklock);
30501a344a2SDavid du Colombier 	}
30601a344a2SDavid du Colombier 	/* botch
30701a344a2SDavid du Colombier 	 * out of tlock nodes simulates
30801a344a2SDavid du Colombier 	 * a locked file
30901a344a2SDavid du Colombier 	 */
31001a344a2SDavid du Colombier 	return t1;
31101a344a2SDavid du Colombier }
31201a344a2SDavid du Colombier 
31301a344a2SDavid du Colombier Wpath*
newwp(void)31401a344a2SDavid du Colombier newwp(void)
31501a344a2SDavid du Colombier {
31601a344a2SDavid du Colombier 	static int si = 0;
31701a344a2SDavid du Colombier 	int i;
31801a344a2SDavid du Colombier 	Wpath *w, *sw, *ew;
31901a344a2SDavid du Colombier 
32001a344a2SDavid du Colombier 	i = si + 1;
32101a344a2SDavid du Colombier 	if(i < 0 || i >= conf.nwpath)
32201a344a2SDavid du Colombier 		i = 0;
32301a344a2SDavid du Colombier 	si = i;
32401a344a2SDavid du Colombier 	sw = &wpaths[i];
32501a344a2SDavid du Colombier 	ew = &wpaths[conf.nwpath];
32601a344a2SDavid du Colombier 	for(w=sw;;) {
32701a344a2SDavid du Colombier 		w++;
32801a344a2SDavid du Colombier 		if(w >= ew)
32901a344a2SDavid du Colombier 			w = &wpaths[0];
33001a344a2SDavid du Colombier 		if(w == sw) {
33101a344a2SDavid du Colombier 			print("out of wpaths\n");
33201a344a2SDavid du Colombier 			return 0;
33301a344a2SDavid du Colombier 		}
33401a344a2SDavid du Colombier 		if(w->refs)
33501a344a2SDavid du Colombier 			continue;
33601a344a2SDavid du Colombier 		lock(&wpathlock);
33701a344a2SDavid du Colombier 		if(w->refs) {
33801a344a2SDavid du Colombier 			unlock(&wpathlock);
33901a344a2SDavid du Colombier 			continue;
34001a344a2SDavid du Colombier 		}
34101a344a2SDavid du Colombier 		w->refs = 1;
34201a344a2SDavid du Colombier 		w->up = 0;
34301a344a2SDavid du Colombier 		unlock(&wpathlock);
34401a344a2SDavid du Colombier 		return w;
34501a344a2SDavid du Colombier 	}
34601a344a2SDavid du Colombier 
34701a344a2SDavid du Colombier }
34801a344a2SDavid du Colombier 
34901a344a2SDavid du Colombier void
freewp(Wpath * w)35001a344a2SDavid du Colombier freewp(Wpath *w)
35101a344a2SDavid du Colombier {
35201a344a2SDavid du Colombier 	lock(&wpathlock);
35301a344a2SDavid du Colombier 	for(; w; w=w->up)
35401a344a2SDavid du Colombier 		w->refs--;
35501a344a2SDavid du Colombier 	unlock(&wpathlock);
35601a344a2SDavid du Colombier }
35701a344a2SDavid du Colombier 
35801a344a2SDavid du Colombier Off
qidpathgen(Device * dev)35901a344a2SDavid du Colombier qidpathgen(Device *dev)
36001a344a2SDavid du Colombier {
36101a344a2SDavid du Colombier 	Iobuf *p;
36201a344a2SDavid du Colombier 	Superb *sb;
36301a344a2SDavid du Colombier 	Off path;
36401a344a2SDavid du Colombier 
36501a344a2SDavid du Colombier 	p = getbuf(dev, superaddr(dev), Brd|Bmod);
36601a344a2SDavid du Colombier 	if(!p || checktag(p, Tsuper, QPSUPER))
36701a344a2SDavid du Colombier 		panic("newqid: super block");
36801a344a2SDavid du Colombier 	sb = (Superb*)p->iobuf;
36901a344a2SDavid du Colombier 	sb->qidgen++;
37001a344a2SDavid du Colombier 	path = sb->qidgen;
37101a344a2SDavid du Colombier 	putbuf(p);
37201a344a2SDavid du Colombier 	return path;
37301a344a2SDavid du Colombier }
37401a344a2SDavid du Colombier 
37501a344a2SDavid du Colombier /* truncating to length > 0 */
37601a344a2SDavid du Colombier static void
truncfree(Truncstate * ts,Device * dev,int d,Iobuf * p,int i)37701a344a2SDavid du Colombier truncfree(Truncstate *ts, Device *dev, int d, Iobuf *p, int i)
37801a344a2SDavid du Colombier {
37901a344a2SDavid du Colombier 	int pastlast;
38001a344a2SDavid du Colombier 	Off a;
38101a344a2SDavid du Colombier 
38201a344a2SDavid du Colombier 	pastlast = ts->pastlast;
38301a344a2SDavid du Colombier 	a = ((Off *)p->iobuf)[i];
38401a344a2SDavid du Colombier 	if (d > 0 || pastlast)
38501a344a2SDavid du Colombier 		buffree(dev, a, d, ts);
38601a344a2SDavid du Colombier 	if (pastlast) {
38701a344a2SDavid du Colombier 		((Off *)p->iobuf)[i] = 0;
38801a344a2SDavid du Colombier 		p->flags |= Bmod|Bimm;
38901a344a2SDavid du Colombier 	} else if (d == 0 && ts->relblk == ts->lastblk)
39001a344a2SDavid du Colombier 		ts->pastlast = 1;
39101a344a2SDavid du Colombier 	if (d == 0)
39201a344a2SDavid du Colombier 		ts->relblk++;
39301a344a2SDavid du Colombier }
39401a344a2SDavid du Colombier 
39501a344a2SDavid du Colombier /*
39601a344a2SDavid du Colombier  * free the block at `addr' on dev.
39701a344a2SDavid du Colombier  * if it's an indirect block (d [depth] > 0),
39801a344a2SDavid du Colombier  * first recursively free all the blocks it names.
39901a344a2SDavid du Colombier  *
40001a344a2SDavid du Colombier  * ts->relblk is the block number within the file of this
40101a344a2SDavid du Colombier  * block (or the first data block eventually pointed to via
40201a344a2SDavid du Colombier  * this indirect block).
40301a344a2SDavid du Colombier  */
40401a344a2SDavid du Colombier void
buffree(Device * dev,Off addr,int d,Truncstate * ts)40501a344a2SDavid du Colombier buffree(Device *dev, Off addr, int d, Truncstate *ts)
40601a344a2SDavid du Colombier {
40701a344a2SDavid du Colombier 	Iobuf *p;
40801a344a2SDavid du Colombier 	Off a;
40901a344a2SDavid du Colombier 	int i, pastlast;
41001a344a2SDavid du Colombier 
41101a344a2SDavid du Colombier 	if(!addr)
41201a344a2SDavid du Colombier 		return;
41301a344a2SDavid du Colombier 	pastlast = (ts == nil? 1: ts->pastlast);
41401a344a2SDavid du Colombier 	/*
41501a344a2SDavid du Colombier 	 * if this is an indirect block, recurse and free any
41601a344a2SDavid du Colombier 	 * suitable blocks within it (possibly via further indirect blocks).
41701a344a2SDavid du Colombier 	 */
41801a344a2SDavid du Colombier 	if(d > 0) {
41901a344a2SDavid du Colombier 		d--;
42001a344a2SDavid du Colombier 		p = getbuf(dev, addr, Brd);
42101a344a2SDavid du Colombier 		if(p) {
42201a344a2SDavid du Colombier 			if (ts == nil)		/* common case: create */
42301a344a2SDavid du Colombier 				for(i=INDPERBUF-1; i>=0; i--) {
42401a344a2SDavid du Colombier 					a = ((Off *)p->iobuf)[i];
42501a344a2SDavid du Colombier 					buffree(dev, a, d, nil);
42601a344a2SDavid du Colombier 				}
42701a344a2SDavid du Colombier 			else			/* wstat truncation */
42801a344a2SDavid du Colombier 				for (i = 0; i < INDPERBUF; i++)
42901a344a2SDavid du Colombier 					truncfree(ts, dev, d, p, i);
43001a344a2SDavid du Colombier 			putbuf(p);
43101a344a2SDavid du Colombier 		}
43201a344a2SDavid du Colombier 	}
43301a344a2SDavid du Colombier 	if (!pastlast)
43401a344a2SDavid du Colombier 		return;
43501a344a2SDavid du Colombier 	/*
43601a344a2SDavid du Colombier 	 * having zeroed the pointer to this block, add it to the free list.
43701a344a2SDavid du Colombier 	 * stop outstanding i/o
43801a344a2SDavid du Colombier 	 */
43901a344a2SDavid du Colombier 	p = getbuf(dev, addr, Bprobe);
44001a344a2SDavid du Colombier 	if(p) {
44101a344a2SDavid du Colombier 		p->flags &= ~(Bmod|Bimm);
44201a344a2SDavid du Colombier 		putbuf(p);
44301a344a2SDavid du Colombier 	}
44401a344a2SDavid du Colombier 	/*
44501a344a2SDavid du Colombier 	 * dont put written worm
44601a344a2SDavid du Colombier 	 * blocks into free list
44701a344a2SDavid du Colombier 	 */
44801a344a2SDavid du Colombier 	if(dev->type == Devcw) {
44901a344a2SDavid du Colombier 		i = cwfree(dev, addr);
45001a344a2SDavid du Colombier 		if(i)
45101a344a2SDavid du Colombier 			return;
45201a344a2SDavid du Colombier 	}
45301a344a2SDavid du Colombier 	p = getbuf(dev, superaddr(dev), Brd|Bmod);
45401a344a2SDavid du Colombier 	if(!p || checktag(p, Tsuper, QPSUPER))
45501a344a2SDavid du Colombier 		panic("buffree: super block");
45601a344a2SDavid du Colombier 	addfree(dev, addr, (Superb*)p->iobuf);
45701a344a2SDavid du Colombier 	putbuf(p);
45801a344a2SDavid du Colombier }
45901a344a2SDavid du Colombier 
46001a344a2SDavid du Colombier Off
bufalloc(Device * dev,int tag,long qid,int uid)46101a344a2SDavid du Colombier bufalloc(Device *dev, int tag, long qid, int uid)
46201a344a2SDavid du Colombier {
46301a344a2SDavid du Colombier 	Iobuf *bp, *p;
46401a344a2SDavid du Colombier 	Superb *sb;
46501a344a2SDavid du Colombier 	Off a, n;
46601a344a2SDavid du Colombier 
46701a344a2SDavid du Colombier 	p = getbuf(dev, superaddr(dev), Brd|Bmod);
46801a344a2SDavid du Colombier 	if(!p || checktag(p, Tsuper, QPSUPER)) {
46901a344a2SDavid du Colombier 		print("bufalloc: super block\n");
47001a344a2SDavid du Colombier 		if(p)
47101a344a2SDavid du Colombier 			putbuf(p);
47201a344a2SDavid du Colombier 		return 0;
47301a344a2SDavid du Colombier 	}
47401a344a2SDavid du Colombier 	sb = (Superb*)p->iobuf;
47501a344a2SDavid du Colombier 
47601a344a2SDavid du Colombier loop:
47701a344a2SDavid du Colombier 	n = --sb->fbuf.nfree;
47801a344a2SDavid du Colombier 	sb->tfree--;
47901a344a2SDavid du Colombier 	if(n < 0 || n >= FEPERBUF) {
48001a344a2SDavid du Colombier 		print("bufalloc: %Z: bad freelist\n", dev);
48101a344a2SDavid du Colombier 		n = 0;
48201a344a2SDavid du Colombier 		sb->fbuf.free[0] = 0;
48301a344a2SDavid du Colombier 	}
48401a344a2SDavid du Colombier 	a = sb->fbuf.free[n];
48501a344a2SDavid du Colombier 	if(n <= 0) {
48601a344a2SDavid du Colombier 		if(a == 0) {
48701a344a2SDavid du Colombier 			sb->tfree = 0;
48801a344a2SDavid du Colombier 			sb->fbuf.nfree = 1;
48901a344a2SDavid du Colombier 			if(dev->type == Devcw) {
49001a344a2SDavid du Colombier 				n = uid;
49101a344a2SDavid du Colombier 				if(n < 0 || n >= nelem(growacct))
49201a344a2SDavid du Colombier 					n = 0;
49301a344a2SDavid du Colombier 				growacct[n]++;
49401a344a2SDavid du Colombier 				if(cwgrow(dev, sb, uid))
49501a344a2SDavid du Colombier 					goto loop;
49601a344a2SDavid du Colombier 			}
49701a344a2SDavid du Colombier 			putbuf(p);
49801a344a2SDavid du Colombier 			print("fs %Z full uid=%d\n", dev, uid);
49901a344a2SDavid du Colombier 			return 0;
50001a344a2SDavid du Colombier 		}
50101a344a2SDavid du Colombier 		bp = getbuf(dev, a, Brd);
50201a344a2SDavid du Colombier 		if(!bp || checktag(bp, Tfree, QPNONE)) {
50301a344a2SDavid du Colombier 			if(bp)
50401a344a2SDavid du Colombier 				putbuf(bp);
50501a344a2SDavid du Colombier 			putbuf(p);
50601a344a2SDavid du Colombier 			return 0;
50701a344a2SDavid du Colombier 		}
50801a344a2SDavid du Colombier 		sb->fbuf = *(Fbuf*)bp->iobuf;
50901a344a2SDavid du Colombier 		putbuf(bp);
51001a344a2SDavid du Colombier 	}
51101a344a2SDavid du Colombier 
51201a344a2SDavid du Colombier 	bp = getbuf(dev, a, Bmod);
51301a344a2SDavid du Colombier 	memset(bp->iobuf, 0, RBUFSIZE);
51401a344a2SDavid du Colombier 	settag(bp, tag, qid);
515*eba00c11SDavid du Colombier 	if(tag == Tind1 || tag == Tind2 ||
516*eba00c11SDavid du Colombier #ifndef COMPAT32
517*eba00c11SDavid du Colombier 	    tag == Tind3 || tag == Tind4 ||  /* add more Tind tags here ... */
518*eba00c11SDavid du Colombier #endif
519*eba00c11SDavid du Colombier 	    tag == Tdir)
52001a344a2SDavid du Colombier 		bp->flags |= Bimm;
52101a344a2SDavid du Colombier 	putbuf(bp);
52201a344a2SDavid du Colombier 	putbuf(p);
52301a344a2SDavid du Colombier 	return a;
52401a344a2SDavid du Colombier }
52501a344a2SDavid du Colombier 
52601a344a2SDavid du Colombier /*
52701a344a2SDavid du Colombier  * what are legal characters in a name?
52801a344a2SDavid du Colombier  * only disallow control characters.
52901a344a2SDavid du Colombier  * a) utf avoids control characters.
53001a344a2SDavid du Colombier  * b) '/' may not be the separator
53101a344a2SDavid du Colombier  */
53201a344a2SDavid du Colombier int
checkname(char * n)53301a344a2SDavid du Colombier checkname(char *n)
53401a344a2SDavid du Colombier {
53501a344a2SDavid du Colombier 	int i, c;
53601a344a2SDavid du Colombier 
53701a344a2SDavid du Colombier 	for(i=0; i<NAMELEN; i++) {
53801a344a2SDavid du Colombier 		c = *n & 0xff;
53901a344a2SDavid du Colombier 		if(c == 0) {
54001a344a2SDavid du Colombier 			if(i == 0)
54101a344a2SDavid du Colombier 				return 1;
54201a344a2SDavid du Colombier 			memset(n, 0, NAMELEN-i);
54301a344a2SDavid du Colombier 			return 0;
54401a344a2SDavid du Colombier 		}
54501a344a2SDavid du Colombier 		if(c <= 040)
54601a344a2SDavid du Colombier 			return 1;
54701a344a2SDavid du Colombier 		n++;
54801a344a2SDavid du Colombier 	}
54901a344a2SDavid du Colombier 	return 1;	/* too long */
55001a344a2SDavid du Colombier }
55101a344a2SDavid du Colombier 
55201a344a2SDavid du Colombier void
addfree(Device * dev,Off addr,Superb * sb)55301a344a2SDavid du Colombier addfree(Device *dev, Off addr, Superb *sb)
55401a344a2SDavid du Colombier {
55501a344a2SDavid du Colombier 	int n;
55601a344a2SDavid du Colombier 	Iobuf *p;
55701a344a2SDavid du Colombier 
55801a344a2SDavid du Colombier 	n = sb->fbuf.nfree;
55901a344a2SDavid du Colombier 	if(n < 0 || n > FEPERBUF)
56001a344a2SDavid du Colombier 		panic("addfree: bad freelist");
56101a344a2SDavid du Colombier 	if(n >= FEPERBUF) {
56201a344a2SDavid du Colombier 		p = getbuf(dev, addr, Bmod|Bimm);
56301a344a2SDavid du Colombier 		if(p == 0)
56401a344a2SDavid du Colombier 			panic("addfree: getbuf");
56501a344a2SDavid du Colombier 		*(Fbuf*)p->iobuf = sb->fbuf;
56601a344a2SDavid du Colombier 		settag(p, Tfree, QPNONE);
56701a344a2SDavid du Colombier 		putbuf(p);
56801a344a2SDavid du Colombier 		n = 0;
56901a344a2SDavid du Colombier 	}
57001a344a2SDavid du Colombier 	sb->fbuf.free[n++] = addr;
57101a344a2SDavid du Colombier 	sb->fbuf.nfree = n;
57201a344a2SDavid du Colombier 	sb->tfree++;
57301a344a2SDavid du Colombier 	if(addr >= sb->fsize)
57401a344a2SDavid du Colombier 		sb->fsize = addr+1;
57501a344a2SDavid du Colombier }
57601a344a2SDavid du Colombier 
57701a344a2SDavid du Colombier /*
57801a344a2SDavid du Colombier static int
57901a344a2SDavid du Colombier Yfmt(Fmt* fmt)
58001a344a2SDavid du Colombier {
58101a344a2SDavid du Colombier 	Chan *cp;
58201a344a2SDavid du Colombier 	char s[20];
58301a344a2SDavid du Colombier 
58401a344a2SDavid du Colombier 	cp = va_arg(fmt->args, Chan*);
58501a344a2SDavid du Colombier 	sprint(s, "C%d.%.3d", cp->type, cp->chan);
58601a344a2SDavid du Colombier 	return fmtstrcpy(fmt, s);
58701a344a2SDavid du Colombier }
58801a344a2SDavid du Colombier  */
58901a344a2SDavid du Colombier 
59001a344a2SDavid du Colombier static int
Zfmt(Fmt * fmt)59101a344a2SDavid du Colombier Zfmt(Fmt* fmt)
59201a344a2SDavid du Colombier {
59301a344a2SDavid du Colombier 	Device *d;
59401a344a2SDavid du Colombier 	int c, c1;
59501a344a2SDavid du Colombier 	char s[100];
59601a344a2SDavid du Colombier 
59701a344a2SDavid du Colombier 	d = va_arg(fmt->args, Device*);
59801a344a2SDavid du Colombier 	if(d == nil) {
59901a344a2SDavid du Colombier 		sprint(s, "Z***");
60001a344a2SDavid du Colombier 		goto out;
60101a344a2SDavid du Colombier 	}
60201a344a2SDavid du Colombier 	c = c1 = '\0';
60301a344a2SDavid du Colombier 	switch(d->type) {
60401a344a2SDavid du Colombier 	default:
60501a344a2SDavid du Colombier 		sprint(s, "D%d", d->type);
60601a344a2SDavid du Colombier 		break;
60701a344a2SDavid du Colombier 	case Devwren:
60801a344a2SDavid du Colombier 		c = 'w';
60901a344a2SDavid du Colombier 		/* fallthrough */
61001a344a2SDavid du Colombier 	case Devworm:
61101a344a2SDavid du Colombier 		if (c == '\0')
61201a344a2SDavid du Colombier 			c = 'r';
61301a344a2SDavid du Colombier 		/* fallthrough */
61401a344a2SDavid du Colombier 	case Devlworm:
61501a344a2SDavid du Colombier 		if (c == '\0')
61601a344a2SDavid du Colombier 			c = 'l';
61701a344a2SDavid du Colombier 		if(d->wren.ctrl == 0 && d->wren.lun == 0)
61801a344a2SDavid du Colombier 			sprint(s, "%c%d", c, d->wren.targ);
61901a344a2SDavid du Colombier 		else
62001a344a2SDavid du Colombier 			sprint(s, "%c%d.%d.%d", c, d->wren.ctrl, d->wren.targ,
62101a344a2SDavid du Colombier 				d->wren.lun);
62201a344a2SDavid du Colombier 		break;
62301a344a2SDavid du Colombier 	case Devmcat:
62401a344a2SDavid du Colombier 		c = '(';
62501a344a2SDavid du Colombier 		c1 = ')';
62601a344a2SDavid du Colombier 		/* fallthrough */
62701a344a2SDavid du Colombier 	case Devmlev:
62801a344a2SDavid du Colombier 		if (c == '\0') {
62901a344a2SDavid du Colombier 			c = '[';
63001a344a2SDavid du Colombier 			c1 = ']';
63101a344a2SDavid du Colombier 		}
63201a344a2SDavid du Colombier 		/* fallthrough */
63301a344a2SDavid du Colombier 	case Devmirr:
63401a344a2SDavid du Colombier 		if (c == '\0') {
63501a344a2SDavid du Colombier 			c = '{';
63601a344a2SDavid du Colombier 			c1 = '}';
63701a344a2SDavid du Colombier 		}
63801a344a2SDavid du Colombier 		if(d->cat.first == d->cat.last)
63901a344a2SDavid du Colombier 			sprint(s, "%c%Z%c", c, d->cat.first, c1);
64001a344a2SDavid du Colombier 		else if(d->cat.first->link == d->cat.last)
64101a344a2SDavid du Colombier 			sprint(s, "%c%Z%Z%c", c, d->cat.first, d->cat.last, c1);
64201a344a2SDavid du Colombier 		else
64301a344a2SDavid du Colombier 			sprint(s, "%c%Z-%Z%c", c, d->cat.first, d->cat.last, c1);
64401a344a2SDavid du Colombier 		break;
64501a344a2SDavid du Colombier 	case Devro:
64601a344a2SDavid du Colombier 		sprint(s, "o%Z%Z", d->ro.parent->cw.c, d->ro.parent->cw.w);
64701a344a2SDavid du Colombier 		break;
64801a344a2SDavid du Colombier 	case Devcw:
64901a344a2SDavid du Colombier 		sprint(s, "c%Z%Z", d->cw.c, d->cw.w);
65001a344a2SDavid du Colombier 		break;
65101a344a2SDavid du Colombier 	case Devjuke:
65201a344a2SDavid du Colombier 		sprint(s, "j%Z%Z", d->j.j, d->j.m);
65301a344a2SDavid du Colombier 		break;
65401a344a2SDavid du Colombier 	case Devfworm:
65501a344a2SDavid du Colombier 		sprint(s, "f%Z", d->fw.fw);
65601a344a2SDavid du Colombier 		break;
65701a344a2SDavid du Colombier 	case Devpart:
65801a344a2SDavid du Colombier 		sprint(s, "p(%Z)%ld.%ld", d->part.d, d->part.base, d->part.size);
65901a344a2SDavid du Colombier 		break;
66001a344a2SDavid du Colombier 	case Devswab:
66101a344a2SDavid du Colombier 		sprint(s, "x%Z", d->swab.d);
66201a344a2SDavid du Colombier 		break;
66301a344a2SDavid du Colombier 	case Devnone:
66401a344a2SDavid du Colombier 		sprint(s, "n");
66501a344a2SDavid du Colombier 		break;
66601a344a2SDavid du Colombier 	}
66701a344a2SDavid du Colombier out:
66801a344a2SDavid du Colombier 	return fmtstrcpy(fmt, s);
66901a344a2SDavid du Colombier }
67001a344a2SDavid du Colombier 
67101a344a2SDavid du Colombier static int
Gfmt(Fmt * fmt)67201a344a2SDavid du Colombier Gfmt(Fmt* fmt)
67301a344a2SDavid du Colombier {
67401a344a2SDavid du Colombier 	int t;
67501a344a2SDavid du Colombier 	char *s;
67601a344a2SDavid du Colombier 
67701a344a2SDavid du Colombier 	t = va_arg(fmt->args, int);
67801a344a2SDavid du Colombier 	s = "<badtag>";
67901a344a2SDavid du Colombier 	if(t >= 0 && t < MAXTAG)
68001a344a2SDavid du Colombier 		s = tagnames[t];
68101a344a2SDavid du Colombier 	return fmtstrcpy(fmt, s);
68201a344a2SDavid du Colombier }
68301a344a2SDavid du Colombier 
68401a344a2SDavid du Colombier void
formatinit(void)68501a344a2SDavid du Colombier formatinit(void)
68601a344a2SDavid du Colombier {
68701a344a2SDavid du Colombier 	quotefmtinstall();
68801a344a2SDavid du Colombier //	fmtinstall('Y', Yfmt);	/* print channels */
68901a344a2SDavid du Colombier 	fmtinstall('Z', Zfmt);	/* print devices */
69001a344a2SDavid du Colombier 	fmtinstall('G', Gfmt);	/* print tags */
69101a344a2SDavid du Colombier 	fmtinstall('T', Tfmt);	/* print times */
69201a344a2SDavid du Colombier //	fmtinstall('E', eipfmt);	/* print ether addresses */
69301a344a2SDavid du Colombier 	fmtinstall('I', eipfmt);	/* print ip addresses */
69401a344a2SDavid du Colombier }
69501a344a2SDavid du Colombier 
69601a344a2SDavid du Colombier void
rootream(Device * dev,Off addr)69701a344a2SDavid du Colombier rootream(Device *dev, Off addr)
69801a344a2SDavid du Colombier {
69901a344a2SDavid du Colombier 	Iobuf *p;
70001a344a2SDavid du Colombier 	Dentry *d;
70101a344a2SDavid du Colombier 
70201a344a2SDavid du Colombier 	p = getbuf(dev, addr, Bmod|Bimm);
70301a344a2SDavid du Colombier 	memset(p->iobuf, 0, RBUFSIZE);
70401a344a2SDavid du Colombier 	settag(p, Tdir, QPROOT);
70501a344a2SDavid du Colombier 	d = getdir(p, 0);
70601a344a2SDavid du Colombier 	strcpy(d->name, "/");
70701a344a2SDavid du Colombier 	d->uid = -1;
70801a344a2SDavid du Colombier 	d->gid = -1;
70901a344a2SDavid du Colombier 	d->mode = DALLOC | DDIR |
71001a344a2SDavid du Colombier 		((DREAD|DEXEC) << 6) |
71101a344a2SDavid du Colombier 		((DREAD|DEXEC) << 3) |
71201a344a2SDavid du Colombier 		((DREAD|DEXEC) << 0);
71301a344a2SDavid du Colombier 	d->qid = QID9P1(QPROOT|QPDIR,0);
71401a344a2SDavid du Colombier 	d->atime = time(nil);
71501a344a2SDavid du Colombier 	d->mtime = d->atime;
71601a344a2SDavid du Colombier 	d->muid = 0;
71701a344a2SDavid du Colombier 	putbuf(p);
71801a344a2SDavid du Colombier }
71901a344a2SDavid du Colombier 
72001a344a2SDavid du Colombier void
superream(Device * dev,Off addr)72101a344a2SDavid du Colombier superream(Device *dev, Off addr)
72201a344a2SDavid du Colombier {
72301a344a2SDavid du Colombier 	Iobuf *p;
72401a344a2SDavid du Colombier 	Superb *s;
72501a344a2SDavid du Colombier 	Off i;
72601a344a2SDavid du Colombier 
72701a344a2SDavid du Colombier 	p = getbuf(dev, addr, Bmod|Bimm);
72801a344a2SDavid du Colombier 	memset(p->iobuf, 0, RBUFSIZE);
72901a344a2SDavid du Colombier 	settag(p, Tsuper, QPSUPER);
73001a344a2SDavid du Colombier 
73101a344a2SDavid du Colombier 	s = (Superb*)p->iobuf;
73201a344a2SDavid du Colombier 	s->fstart = 2;
73301a344a2SDavid du Colombier 	s->fsize = devsize(dev);
73401a344a2SDavid du Colombier 	s->fbuf.nfree = 1;
73501a344a2SDavid du Colombier 	s->qidgen = 10;
73601a344a2SDavid du Colombier 	for(i = s->fsize-1; i >= addr+2; i--)
73701a344a2SDavid du Colombier 		addfree(dev, i, s);
73801a344a2SDavid du Colombier 	putbuf(p);
73901a344a2SDavid du Colombier }
74001a344a2SDavid du Colombier 
74101a344a2SDavid du Colombier struct
74201a344a2SDavid du Colombier {
74301a344a2SDavid du Colombier 	Lock;
74401a344a2SDavid du Colombier 	Msgbuf	*smsgbuf;
74501a344a2SDavid du Colombier 	Msgbuf	*lmsgbuf;
74601a344a2SDavid du Colombier } msgalloc;
74701a344a2SDavid du Colombier 
74801a344a2SDavid du Colombier /*
74901a344a2SDavid du Colombier  * pre-allocate some message buffers at boot time.
75001a344a2SDavid du Colombier  * if this supply is exhausted, more will be allocated as needed.
75101a344a2SDavid du Colombier  */
75201a344a2SDavid du Colombier void
mbinit(void)75301a344a2SDavid du Colombier mbinit(void)
75401a344a2SDavid du Colombier {
75501a344a2SDavid du Colombier 	Msgbuf *mb;
75601a344a2SDavid du Colombier 	Rabuf *rb;
75701a344a2SDavid du Colombier 	int i;
75801a344a2SDavid du Colombier 
75901a344a2SDavid du Colombier 	lock(&msgalloc);
76001a344a2SDavid du Colombier 	unlock(&msgalloc);
76101a344a2SDavid du Colombier 	msgalloc.lmsgbuf = 0;
76201a344a2SDavid du Colombier 	msgalloc.smsgbuf = 0;
76301a344a2SDavid du Colombier 	for(i=0; i<conf.nlgmsg; i++) {
76401a344a2SDavid du Colombier 		mb = malloc(sizeof(Msgbuf));
76501a344a2SDavid du Colombier 		mb->magic = Mbmagic;
76601a344a2SDavid du Colombier 		mb->xdata = malloc(LARGEBUF+Slop);
76701a344a2SDavid du Colombier 		mb->flags = LARGE;
76801a344a2SDavid du Colombier 		mbfree(mb);
76901a344a2SDavid du Colombier 		cons.nlarge++;
77001a344a2SDavid du Colombier 	}
77101a344a2SDavid du Colombier 	for(i=0; i<conf.nsmmsg; i++) {
77201a344a2SDavid du Colombier 		mb = malloc(sizeof(Msgbuf));
77301a344a2SDavid du Colombier 		mb->magic = Mbmagic;
77401a344a2SDavid du Colombier 		mb->xdata = malloc(SMALLBUF+Slop);
77501a344a2SDavid du Colombier 		mb->flags = 0;
77601a344a2SDavid du Colombier 		mbfree(mb);
77701a344a2SDavid du Colombier 		cons.nsmall++;
77801a344a2SDavid du Colombier 	}
77901a344a2SDavid du Colombier 	memset(mballocs, 0, sizeof(mballocs));
78001a344a2SDavid du Colombier 
78101a344a2SDavid du Colombier 	lock(&rabuflock);
78201a344a2SDavid du Colombier 	unlock(&rabuflock);
78301a344a2SDavid du Colombier 	rabuffree = 0;
78401a344a2SDavid du Colombier 	for(i=0; i<1000; i++) {
78501a344a2SDavid du Colombier 		rb = malloc(sizeof(*rb));
78601a344a2SDavid du Colombier 		rb->link = rabuffree;
78701a344a2SDavid du Colombier 		rabuffree = rb;
78801a344a2SDavid du Colombier 	}
78901a344a2SDavid du Colombier }
79001a344a2SDavid du Colombier 
79101a344a2SDavid du Colombier Msgbuf*
mballoc(int count,Chan * cp,int category)79201a344a2SDavid du Colombier mballoc(int count, Chan *cp, int category)
79301a344a2SDavid du Colombier {
79401a344a2SDavid du Colombier 	Msgbuf *mb;
79501a344a2SDavid du Colombier 
79601a344a2SDavid du Colombier 	lock(&msgalloc);
79701a344a2SDavid du Colombier 	if(count > SMALLBUF) {
79801a344a2SDavid du Colombier 		if(count > LARGEBUF)
79901a344a2SDavid du Colombier 			panic("msgbuf count");
80001a344a2SDavid du Colombier 		mb = msgalloc.lmsgbuf;
80101a344a2SDavid du Colombier 		if(mb == nil) {
80201a344a2SDavid du Colombier 			mb = malloc(sizeof(Msgbuf));
80301a344a2SDavid du Colombier 			mb->xdata = malloc(LARGEBUF+Slop);
80401a344a2SDavid du Colombier 			cons.nlarge++;
80501a344a2SDavid du Colombier 		} else
80601a344a2SDavid du Colombier 			msgalloc.lmsgbuf = mb->next;
80701a344a2SDavid du Colombier 		mb->flags = LARGE;
80801a344a2SDavid du Colombier 	} else {
80901a344a2SDavid du Colombier 		mb = msgalloc.smsgbuf;
81001a344a2SDavid du Colombier 		if(mb == nil) {
81101a344a2SDavid du Colombier 			mb = malloc(sizeof(Msgbuf));
81201a344a2SDavid du Colombier 			mb->xdata = malloc(SMALLBUF+Slop);
81301a344a2SDavid du Colombier 			cons.nsmall++;
81401a344a2SDavid du Colombier 		} else
81501a344a2SDavid du Colombier 			msgalloc.smsgbuf = mb->next;
81601a344a2SDavid du Colombier 		mb->flags = 0;
81701a344a2SDavid du Colombier 	}
81801a344a2SDavid du Colombier 	mballocs[category]++;
81901a344a2SDavid du Colombier 	unlock(&msgalloc);
82001a344a2SDavid du Colombier 	mb->magic = Mbmagic;
82101a344a2SDavid du Colombier 	mb->count = count;
82201a344a2SDavid du Colombier 	mb->chan = cp;
82301a344a2SDavid du Colombier 	mb->next = 0;
82401a344a2SDavid du Colombier 	mb->param = 0;
82501a344a2SDavid du Colombier 	mb->category = category;
82601a344a2SDavid du Colombier 	mb->data = mb->xdata+Slop;
82701a344a2SDavid du Colombier 	return mb;
82801a344a2SDavid du Colombier }
82901a344a2SDavid du Colombier 
83001a344a2SDavid du Colombier void
mbfree(Msgbuf * mb)83101a344a2SDavid du Colombier mbfree(Msgbuf *mb)
83201a344a2SDavid du Colombier {
83301a344a2SDavid du Colombier 	if(mb == nil)
83401a344a2SDavid du Colombier 		return;
83501a344a2SDavid du Colombier 	assert(mb->magic == Mbmagic);
83601a344a2SDavid du Colombier 	if (mb->magic != Mbmagic)
83701a344a2SDavid du Colombier 		panic("mbfree: bad magic 0x%lux", mb->magic);
83801a344a2SDavid du Colombier 	if(mb->flags & BTRACE)
83901a344a2SDavid du Colombier 		print("mbfree: BTRACE cat=%d flags=%ux, caller %#p\n",
84001a344a2SDavid du Colombier 			mb->category, mb->flags, getcallerpc(&mb));
84101a344a2SDavid du Colombier 
84201a344a2SDavid du Colombier 	if(mb->flags & FREE)
84301a344a2SDavid du Colombier 		panic("mbfree already free");
84401a344a2SDavid du Colombier 
84501a344a2SDavid du Colombier 	lock(&msgalloc);
84601a344a2SDavid du Colombier 	mballocs[mb->category]--;
84701a344a2SDavid du Colombier 	mb->flags |= FREE;
84801a344a2SDavid du Colombier 	if(mb->flags & LARGE) {
84901a344a2SDavid du Colombier 		mb->next = msgalloc.lmsgbuf;
85001a344a2SDavid du Colombier 		msgalloc.lmsgbuf = mb;
85101a344a2SDavid du Colombier 	} else {
85201a344a2SDavid du Colombier 		mb->next = msgalloc.smsgbuf;
85301a344a2SDavid du Colombier 		msgalloc.smsgbuf = mb;
85401a344a2SDavid du Colombier 	}
85501a344a2SDavid du Colombier 	mb->data = 0;
85601a344a2SDavid du Colombier 	mb->magic = 0;
85701a344a2SDavid du Colombier 	unlock(&msgalloc);
85801a344a2SDavid du Colombier }
85901a344a2SDavid du Colombier 
86001a344a2SDavid du Colombier /*
86101a344a2SDavid du Colombier  * returns 1 if n is prime
86201a344a2SDavid du Colombier  * used for adjusting lengths
86301a344a2SDavid du Colombier  * of hashing things.
86401a344a2SDavid du Colombier  * there is no need to be clever
86501a344a2SDavid du Colombier  */
86601a344a2SDavid du Colombier int
prime(vlong n)86701a344a2SDavid du Colombier prime(vlong n)
86801a344a2SDavid du Colombier {
86901a344a2SDavid du Colombier 	long i;
87001a344a2SDavid du Colombier 
87101a344a2SDavid du Colombier 	if((n%2) == 0)
87201a344a2SDavid du Colombier 		return 0;
87301a344a2SDavid du Colombier 	for(i=3;; i+=2) {
87401a344a2SDavid du Colombier 		if((n%i) == 0)
87501a344a2SDavid du Colombier 			return 0;
87601a344a2SDavid du Colombier 		if((vlong)i*i >= n)
87701a344a2SDavid du Colombier 			return 1;
87801a344a2SDavid du Colombier 	}
87901a344a2SDavid du Colombier }
88001a344a2SDavid du Colombier 
88101a344a2SDavid du Colombier char*
getwrd(char * word,char * line)88201a344a2SDavid du Colombier getwrd(char *word, char *line)
88301a344a2SDavid du Colombier {
88401a344a2SDavid du Colombier 	int c, n;
88501a344a2SDavid du Colombier 
88601a344a2SDavid du Colombier 	while(isascii(*line) && isspace(*line) && *line != '\n')
88701a344a2SDavid du Colombier 		line++;
88801a344a2SDavid du Colombier 	for(n = 0; n < Maxword; n++) {
88901a344a2SDavid du Colombier 		c = *line;
89001a344a2SDavid du Colombier 		if(c == '\0' || isascii(c) && isspace(c))
89101a344a2SDavid du Colombier 			break;
89201a344a2SDavid du Colombier 		line++;
89301a344a2SDavid du Colombier 		*word++ = c;
89401a344a2SDavid du Colombier 	}
89501a344a2SDavid du Colombier 	*word = 0;
89601a344a2SDavid du Colombier 	return line;
89701a344a2SDavid du Colombier }
89801a344a2SDavid du Colombier 
89901a344a2SDavid du Colombier void
hexdump(void * a,int n)90001a344a2SDavid du Colombier hexdump(void *a, int n)
90101a344a2SDavid du Colombier {
90201a344a2SDavid du Colombier 	char s1[30], s2[4];
90301a344a2SDavid du Colombier 	uchar *p;
90401a344a2SDavid du Colombier 	int i;
90501a344a2SDavid du Colombier 
90601a344a2SDavid du Colombier 	p = a;
90701a344a2SDavid du Colombier 	s1[0] = 0;
90801a344a2SDavid du Colombier 	for(i = 0; i < n; i++) {
90901a344a2SDavid du Colombier 		sprint(s2, " %.2ux", p[i]);
91001a344a2SDavid du Colombier 		strcat(s1, s2);
91101a344a2SDavid du Colombier 		if((i&7) == 7) {
91201a344a2SDavid du Colombier 			print("%s\n", s1);
91301a344a2SDavid du Colombier 			s1[0] = 0;
91401a344a2SDavid du Colombier 		}
91501a344a2SDavid du Colombier 	}
91601a344a2SDavid du Colombier 	if(s1[0])
91701a344a2SDavid du Colombier 		print("%s\n", s1);
91801a344a2SDavid du Colombier }
91901a344a2SDavid du Colombier 
92001a344a2SDavid du Colombier void*
fs_recv(Queue * q,int)92101a344a2SDavid du Colombier fs_recv(Queue *q, int)
92201a344a2SDavid du Colombier {
92301a344a2SDavid du Colombier 	void *a;
92401a344a2SDavid du Colombier 	int i, c;
92501a344a2SDavid du Colombier 
92601a344a2SDavid du Colombier 	if(q == nil)
92701a344a2SDavid du Colombier 		panic("recv null q");
92801a344a2SDavid du Colombier 	qlock(q);
92901a344a2SDavid du Colombier 	q->waitedfor = 1;
93001a344a2SDavid du Colombier 	while((c = q->count) <= 0)
93101a344a2SDavid du Colombier 		rsleep(&q->empty);
93201a344a2SDavid du Colombier 	i = q->loc;
93301a344a2SDavid du Colombier 	a = q->args[i];
93401a344a2SDavid du Colombier 	i++;
93501a344a2SDavid du Colombier 	if(i >= q->size)
93601a344a2SDavid du Colombier 		i = 0;
93701a344a2SDavid du Colombier 	q->loc = i;
93801a344a2SDavid du Colombier 	q->count = c-1;
93901a344a2SDavid du Colombier 	rwakeup(&q->full);			/* no longer full */
94001a344a2SDavid du Colombier 	qunlock(q);
94101a344a2SDavid du Colombier 	return a;
94201a344a2SDavid du Colombier }
94301a344a2SDavid du Colombier 
94401a344a2SDavid du Colombier void
fs_send(Queue * q,void * a)94501a344a2SDavid du Colombier fs_send(Queue *q, void *a)
94601a344a2SDavid du Colombier {
94701a344a2SDavid du Colombier 	int i, c;
94801a344a2SDavid du Colombier 
94901a344a2SDavid du Colombier 	if(q == nil)
95001a344a2SDavid du Colombier 		panic("send null q");
95101a344a2SDavid du Colombier 	if(!q->waitedfor) {
95201a344a2SDavid du Colombier 		for (i = 0; i < 5 && !q->waitedfor; i++)
95301a344a2SDavid du Colombier 			sleep(1000);
95401a344a2SDavid du Colombier 		if(!q->waitedfor) {
95501a344a2SDavid du Colombier 			/* likely a bug; don't wait forever */
95601a344a2SDavid du Colombier 			print("no readers yet for %s q\n", q->name);
95701a344a2SDavid du Colombier 			abort();
95801a344a2SDavid du Colombier 		}
95901a344a2SDavid du Colombier 	}
96001a344a2SDavid du Colombier 	qlock(q);
96101a344a2SDavid du Colombier 	while((c = q->count) >= q->size)
96201a344a2SDavid du Colombier 		rsleep(&q->full);
96301a344a2SDavid du Colombier 	i = q->loc + c;
96401a344a2SDavid du Colombier 	if(i >= q->size)
96501a344a2SDavid du Colombier 		i -= q->size;
96601a344a2SDavid du Colombier 	q->args[i] = a;
96701a344a2SDavid du Colombier 	q->count = c+1;
96801a344a2SDavid du Colombier 	rwakeup(&q->empty);			/* no longer empty */
96901a344a2SDavid du Colombier 	qunlock(q);
97001a344a2SDavid du Colombier }
97101a344a2SDavid du Colombier 
97201a344a2SDavid du Colombier Queue*
newqueue(int size,char * name)97301a344a2SDavid du Colombier newqueue(int size, char *name)
97401a344a2SDavid du Colombier {
97501a344a2SDavid du Colombier 	Queue *q;
97601a344a2SDavid du Colombier 
97701a344a2SDavid du Colombier 	q = malloc(sizeof(Queue) + (size-1)*sizeof(void*));
97801a344a2SDavid du Colombier 	q->size = size;
97901a344a2SDavid du Colombier 	q->full.l = q->empty.l = &q->QLock;
98001a344a2SDavid du Colombier 	q->name = name;
98101a344a2SDavid du Colombier 	return q;
98201a344a2SDavid du Colombier }
98301a344a2SDavid du Colombier 
98401a344a2SDavid du Colombier int
devread(Device * d,Off b,void * c)98501a344a2SDavid du Colombier devread(Device *d, Off b, void *c)
98601a344a2SDavid du Colombier {
98701a344a2SDavid du Colombier 	int e;
98801a344a2SDavid du Colombier 
98901a344a2SDavid du Colombier 	for (;;)
99001a344a2SDavid du Colombier 		switch(d->type) {
99101a344a2SDavid du Colombier 		case Devcw:
99201a344a2SDavid du Colombier 			return cwread(d, b, c);
99301a344a2SDavid du Colombier 
99401a344a2SDavid du Colombier 		case Devjuke:
99501a344a2SDavid du Colombier 			d = d->j.m;
99601a344a2SDavid du Colombier 			break;
99701a344a2SDavid du Colombier 
99801a344a2SDavid du Colombier 		case Devro:
99901a344a2SDavid du Colombier 			return roread(d, b, c);
100001a344a2SDavid du Colombier 
100101a344a2SDavid du Colombier 		case Devwren:
100201a344a2SDavid du Colombier 			return wrenread(d, b, c);
100301a344a2SDavid du Colombier 
100401a344a2SDavid du Colombier 		case Devworm:
100501a344a2SDavid du Colombier 		case Devlworm:
100601a344a2SDavid du Colombier 			return wormread(d, b, c);
100701a344a2SDavid du Colombier 
100801a344a2SDavid du Colombier 		case Devfworm:
100901a344a2SDavid du Colombier 			return fwormread(d, b, c);
101001a344a2SDavid du Colombier 
101101a344a2SDavid du Colombier 		case Devmcat:
101201a344a2SDavid du Colombier 			return mcatread(d, b, c);
101301a344a2SDavid du Colombier 
101401a344a2SDavid du Colombier 		case Devmlev:
101501a344a2SDavid du Colombier 			return mlevread(d, b, c);
101601a344a2SDavid du Colombier 
101701a344a2SDavid du Colombier 		case Devmirr:
101801a344a2SDavid du Colombier 			return mirrread(d, b, c);
101901a344a2SDavid du Colombier 
102001a344a2SDavid du Colombier 		case Devpart:
102101a344a2SDavid du Colombier 			return partread(d, b, c);
102201a344a2SDavid du Colombier 
102301a344a2SDavid du Colombier 		case Devswab:
102401a344a2SDavid du Colombier 			e = devread(d->swab.d, b, c);
102501a344a2SDavid du Colombier 			if(e == 0)
102601a344a2SDavid du Colombier 				swab(c, 0);
102701a344a2SDavid du Colombier 			return e;
102801a344a2SDavid du Colombier 
102901a344a2SDavid du Colombier 		case Devnone:
103001a344a2SDavid du Colombier 			print("read from device none(%lld)\n", (Wideoff)b);
103101a344a2SDavid du Colombier 			return 1;
103201a344a2SDavid du Colombier 		default:
103301a344a2SDavid du Colombier 			panic("illegal device in devread: %Z %lld",
103401a344a2SDavid du Colombier 				d, (Wideoff)b);
103501a344a2SDavid du Colombier 			return 1;
103601a344a2SDavid du Colombier 		}
103701a344a2SDavid du Colombier }
103801a344a2SDavid du Colombier 
103901a344a2SDavid du Colombier int
devwrite(Device * d,Off b,void * c)104001a344a2SDavid du Colombier devwrite(Device *d, Off b, void *c)
104101a344a2SDavid du Colombier {
104201a344a2SDavid du Colombier 	int e;
104301a344a2SDavid du Colombier 
104401a344a2SDavid du Colombier 	/*
104501a344a2SDavid du Colombier 	 * set readonly to non-0 to prevent all writes;
104601a344a2SDavid du Colombier 	 * mainly for trying dangerous experiments.
104701a344a2SDavid du Colombier 	 */
104801a344a2SDavid du Colombier 	if (readonly)
104901a344a2SDavid du Colombier 		return 0;
105001a344a2SDavid du Colombier 	for (;;)
105101a344a2SDavid du Colombier 		switch(d->type) {
105201a344a2SDavid du Colombier 		case Devcw:
105301a344a2SDavid du Colombier 			return cwwrite(d, b, c);
105401a344a2SDavid du Colombier 
105501a344a2SDavid du Colombier 		case Devjuke:
105601a344a2SDavid du Colombier 			d = d->j.m;
105701a344a2SDavid du Colombier 			break;
105801a344a2SDavid du Colombier 
105901a344a2SDavid du Colombier 		case Devro:
106001a344a2SDavid du Colombier 			print("write to ro device %Z(%lld)\n", d, (Wideoff)b);
106101a344a2SDavid du Colombier 			return 1;
106201a344a2SDavid du Colombier 
106301a344a2SDavid du Colombier 		case Devwren:
106401a344a2SDavid du Colombier 			return wrenwrite(d, b, c);
106501a344a2SDavid du Colombier 
106601a344a2SDavid du Colombier 		case Devworm:
106701a344a2SDavid du Colombier 		case Devlworm:
106801a344a2SDavid du Colombier 			return wormwrite(d, b, c);
106901a344a2SDavid du Colombier 
107001a344a2SDavid du Colombier 		case Devfworm:
107101a344a2SDavid du Colombier 			return fwormwrite(d, b, c);
107201a344a2SDavid du Colombier 
107301a344a2SDavid du Colombier 		case Devmcat:
107401a344a2SDavid du Colombier 			return mcatwrite(d, b, c);
107501a344a2SDavid du Colombier 
107601a344a2SDavid du Colombier 		case Devmlev:
107701a344a2SDavid du Colombier 			return mlevwrite(d, b, c);
107801a344a2SDavid du Colombier 
107901a344a2SDavid du Colombier 		case Devmirr:
108001a344a2SDavid du Colombier 			return mirrwrite(d, b, c);
108101a344a2SDavid du Colombier 
108201a344a2SDavid du Colombier 		case Devpart:
108301a344a2SDavid du Colombier 			return partwrite(d, b, c);
108401a344a2SDavid du Colombier 
108501a344a2SDavid du Colombier 		case Devswab:
108601a344a2SDavid du Colombier 			swab(c, 1);
108701a344a2SDavid du Colombier 			e = devwrite(d->swab.d, b, c);
108801a344a2SDavid du Colombier 			swab(c, 0);
108901a344a2SDavid du Colombier 			return e;
109001a344a2SDavid du Colombier 
109101a344a2SDavid du Colombier 		case Devnone:
109201a344a2SDavid du Colombier 			/* checktag() can generate blocks with type devnone */
109301a344a2SDavid du Colombier 			return 0;
109401a344a2SDavid du Colombier 		default:
109501a344a2SDavid du Colombier 			panic("illegal device in devwrite: %Z %lld",
109601a344a2SDavid du Colombier 				d, (Wideoff)b);
109701a344a2SDavid du Colombier 			return 1;
109801a344a2SDavid du Colombier 		}
109901a344a2SDavid du Colombier }
110001a344a2SDavid du Colombier 
110101a344a2SDavid du Colombier Devsize
devsize(Device * d)110201a344a2SDavid du Colombier devsize(Device *d)
110301a344a2SDavid du Colombier {
110401a344a2SDavid du Colombier 	for (;;)
110501a344a2SDavid du Colombier 		switch(d->type) {
110601a344a2SDavid du Colombier 		case Devcw:
110701a344a2SDavid du Colombier 		case Devro:
110801a344a2SDavid du Colombier 			return cwsize(d);
110901a344a2SDavid du Colombier 
111001a344a2SDavid du Colombier 		case Devjuke:
111101a344a2SDavid du Colombier 			d = d->j.m;
111201a344a2SDavid du Colombier 			break;
111301a344a2SDavid du Colombier 
111401a344a2SDavid du Colombier 		case Devwren:
111501a344a2SDavid du Colombier 			return wrensize(d);
111601a344a2SDavid du Colombier 
111701a344a2SDavid du Colombier 		case Devworm:
111801a344a2SDavid du Colombier 		case Devlworm:
111901a344a2SDavid du Colombier 			return wormsize(d);
112001a344a2SDavid du Colombier 
112101a344a2SDavid du Colombier 		case Devfworm:
112201a344a2SDavid du Colombier 			return fwormsize(d);
112301a344a2SDavid du Colombier 
112401a344a2SDavid du Colombier 		case Devmcat:
112501a344a2SDavid du Colombier 			return mcatsize(d);
112601a344a2SDavid du Colombier 
112701a344a2SDavid du Colombier 		case Devmlev:
112801a344a2SDavid du Colombier 			return mlevsize(d);
112901a344a2SDavid du Colombier 
113001a344a2SDavid du Colombier 		case Devmirr:
113101a344a2SDavid du Colombier 			return mirrsize(d);
113201a344a2SDavid du Colombier 
113301a344a2SDavid du Colombier 		case Devpart:
113401a344a2SDavid du Colombier 			return partsize(d);
113501a344a2SDavid du Colombier 
113601a344a2SDavid du Colombier 		case Devswab:
113701a344a2SDavid du Colombier 			d = d->swab.d;
113801a344a2SDavid du Colombier 			break;
113901a344a2SDavid du Colombier 		default:
114001a344a2SDavid du Colombier 			panic("illegal device in devsize: %Z", d);
114101a344a2SDavid du Colombier 			return 0;
114201a344a2SDavid du Colombier 		}
114301a344a2SDavid du Colombier }
114401a344a2SDavid du Colombier 
114501a344a2SDavid du Colombier /* result is malloced */
114601a344a2SDavid du Colombier char *
sdof(Device * d)114701a344a2SDavid du Colombier sdof(Device *d)
114801a344a2SDavid du Colombier {
114901a344a2SDavid du Colombier 	static char name[256];
115001a344a2SDavid du Colombier 
115101a344a2SDavid du Colombier 	for (;;)
115201a344a2SDavid du Colombier 		switch(d->type) {
115301a344a2SDavid du Colombier 		case Devjuke:
115401a344a2SDavid du Colombier 			d = d->j.j;		/* robotics */
115501a344a2SDavid du Colombier 			break;
115601a344a2SDavid du Colombier 		case Devwren:
115701a344a2SDavid du Colombier 			snprint(name, sizeof name, "/dev/sd%d%d", d->wren.ctrl,
115801a344a2SDavid du Colombier 				d->wren.targ);
115901a344a2SDavid du Colombier 			return strdup(name);
116001a344a2SDavid du Colombier 		case Devswab:
116101a344a2SDavid du Colombier 			d = d->swab.d;
116201a344a2SDavid du Colombier 			break;
116301a344a2SDavid du Colombier 		default:
116401a344a2SDavid du Colombier 			panic("illegal device in sdof: %Z", d);
116501a344a2SDavid du Colombier 			return nil;
116601a344a2SDavid du Colombier 		}
116701a344a2SDavid du Colombier }
116801a344a2SDavid du Colombier 
116901a344a2SDavid du Colombier Off
superaddr(Device * d)117001a344a2SDavid du Colombier superaddr(Device *d)
117101a344a2SDavid du Colombier {
117201a344a2SDavid du Colombier 	for (;;)
117301a344a2SDavid du Colombier 		switch(d->type) {
117401a344a2SDavid du Colombier 		default:
117501a344a2SDavid du Colombier 			return SUPER_ADDR;
117601a344a2SDavid du Colombier 		case Devcw:
117701a344a2SDavid du Colombier 		case Devro:
117801a344a2SDavid du Colombier 			return cwsaddr(d);
117901a344a2SDavid du Colombier 		case Devswab:
118001a344a2SDavid du Colombier 			d = d->swab.d;
118101a344a2SDavid du Colombier 			break;
118201a344a2SDavid du Colombier 		}
118301a344a2SDavid du Colombier }
118401a344a2SDavid du Colombier 
118501a344a2SDavid du Colombier Off
getraddr(Device * d)118601a344a2SDavid du Colombier getraddr(Device *d)
118701a344a2SDavid du Colombier {
118801a344a2SDavid du Colombier 	for (;;)
118901a344a2SDavid du Colombier 		switch(d->type) {
119001a344a2SDavid du Colombier 		default:
119101a344a2SDavid du Colombier 			return ROOT_ADDR;
119201a344a2SDavid du Colombier 		case Devcw:
119301a344a2SDavid du Colombier 		case Devro:
119401a344a2SDavid du Colombier 			return cwraddr(d);
119501a344a2SDavid du Colombier 		case Devswab:
119601a344a2SDavid du Colombier 			d = d->swab.d;
119701a344a2SDavid du Colombier 			break;
119801a344a2SDavid du Colombier 		}
119901a344a2SDavid du Colombier }
120001a344a2SDavid du Colombier 
120101a344a2SDavid du Colombier void
devream(Device * d,int top)120201a344a2SDavid du Colombier devream(Device *d, int top)
120301a344a2SDavid du Colombier {
120401a344a2SDavid du Colombier 	Device *l;
120501a344a2SDavid du Colombier 
120601a344a2SDavid du Colombier loop:
120701a344a2SDavid du Colombier 	print("\tdevream: %Z %d\n", d, top);
120801a344a2SDavid du Colombier 	switch(d->type) {
120901a344a2SDavid du Colombier 	default:
121001a344a2SDavid du Colombier 		print("ream: unknown dev type %Z\n", d);
121101a344a2SDavid du Colombier 		return;
121201a344a2SDavid du Colombier 
121301a344a2SDavid du Colombier 	case Devcw:
121401a344a2SDavid du Colombier 		devream(d->cw.w, 0);
121501a344a2SDavid du Colombier 		devream(d->cw.c, 0);
121601a344a2SDavid du Colombier 		if(top) {
121701a344a2SDavid du Colombier 			wlock(&mainlock);
121801a344a2SDavid du Colombier 			cwream(d);
121901a344a2SDavid du Colombier 			wunlock(&mainlock);
122001a344a2SDavid du Colombier 		}
122101a344a2SDavid du Colombier 		devinit(d);
122201a344a2SDavid du Colombier 		return;
122301a344a2SDavid du Colombier 
122401a344a2SDavid du Colombier 	case Devfworm:
122501a344a2SDavid du Colombier 		devream(d->fw.fw, 0);
122601a344a2SDavid du Colombier 		fwormream(d);
122701a344a2SDavid du Colombier 		break;
122801a344a2SDavid du Colombier 
122901a344a2SDavid du Colombier 	case Devpart:
123001a344a2SDavid du Colombier 		devream(d->part.d, 0);
123101a344a2SDavid du Colombier 		break;
123201a344a2SDavid du Colombier 
123301a344a2SDavid du Colombier 	case Devmlev:
123401a344a2SDavid du Colombier 	case Devmcat:
123501a344a2SDavid du Colombier 	case Devmirr:
123601a344a2SDavid du Colombier 		for(l=d->cat.first; l; l=l->link)
123701a344a2SDavid du Colombier 			devream(l, 0);
123801a344a2SDavid du Colombier 		break;
123901a344a2SDavid du Colombier 
124001a344a2SDavid du Colombier 	case Devjuke:
124101a344a2SDavid du Colombier 	case Devworm:
124201a344a2SDavid du Colombier 	case Devlworm:
124301a344a2SDavid du Colombier 	case Devwren:
124401a344a2SDavid du Colombier 		break;
124501a344a2SDavid du Colombier 
124601a344a2SDavid du Colombier 	case Devswab:
124701a344a2SDavid du Colombier 		d = d->swab.d;
124801a344a2SDavid du Colombier 		goto loop;
124901a344a2SDavid du Colombier 	}
125001a344a2SDavid du Colombier 	devinit(d);
125101a344a2SDavid du Colombier 	if(top) {
125201a344a2SDavid du Colombier 		wlock(&mainlock);
125301a344a2SDavid du Colombier 		rootream(d, ROOT_ADDR);
125401a344a2SDavid du Colombier 		superream(d, SUPER_ADDR);
125501a344a2SDavid du Colombier 		wunlock(&mainlock);
125601a344a2SDavid du Colombier 	}
125701a344a2SDavid du Colombier }
125801a344a2SDavid du Colombier 
125901a344a2SDavid du Colombier void
devrecover(Device * d)126001a344a2SDavid du Colombier devrecover(Device *d)
126101a344a2SDavid du Colombier {
126201a344a2SDavid du Colombier 	for (;;) {
126301a344a2SDavid du Colombier 		print("recover: %Z\n", d);
126401a344a2SDavid du Colombier 		switch(d->type) {
126501a344a2SDavid du Colombier 		default:
126601a344a2SDavid du Colombier 			print("recover: unknown dev type %Z\n", d);
126701a344a2SDavid du Colombier 			return;
126801a344a2SDavid du Colombier 
126901a344a2SDavid du Colombier 		case Devcw:
127001a344a2SDavid du Colombier 			wlock(&mainlock);	/* recover */
127101a344a2SDavid du Colombier 			cwrecover(d);
127201a344a2SDavid du Colombier 			wunlock(&mainlock);
127301a344a2SDavid du Colombier 			return;
127401a344a2SDavid du Colombier 
127501a344a2SDavid du Colombier 		case Devswab:
127601a344a2SDavid du Colombier 			d = d->swab.d;
127701a344a2SDavid du Colombier 			break;
127801a344a2SDavid du Colombier 		}
127901a344a2SDavid du Colombier 	}
128001a344a2SDavid du Colombier }
128101a344a2SDavid du Colombier 
128201a344a2SDavid du Colombier void
devinit(Device * d)128301a344a2SDavid du Colombier devinit(Device *d)
128401a344a2SDavid du Colombier {
128501a344a2SDavid du Colombier 	for (;;) {
128601a344a2SDavid du Colombier 		if(d->init)
128701a344a2SDavid du Colombier 			return;
128801a344a2SDavid du Colombier 		d->init = 1;
128901a344a2SDavid du Colombier 		print("\tdevinit %Z\n", d);
129001a344a2SDavid du Colombier 		switch(d->type) {
129101a344a2SDavid du Colombier 		default:
129201a344a2SDavid du Colombier 			print("devinit unknown device %Z\n", d);
129301a344a2SDavid du Colombier 			return;
129401a344a2SDavid du Colombier 
129501a344a2SDavid du Colombier 		case Devro:
129601a344a2SDavid du Colombier 			cwinit(d->ro.parent);
129701a344a2SDavid du Colombier 			return;
129801a344a2SDavid du Colombier 
129901a344a2SDavid du Colombier 		case Devcw:
130001a344a2SDavid du Colombier 			cwinit(d);
130101a344a2SDavid du Colombier 			return;
130201a344a2SDavid du Colombier 
130301a344a2SDavid du Colombier 		case Devjuke:
130401a344a2SDavid du Colombier 			jukeinit(d);
130501a344a2SDavid du Colombier 			return;
130601a344a2SDavid du Colombier 
130701a344a2SDavid du Colombier 		case Devwren:
130801a344a2SDavid du Colombier 			wreninit(d);
130901a344a2SDavid du Colombier 			return;
131001a344a2SDavid du Colombier 
131101a344a2SDavid du Colombier 		case Devworm:
131201a344a2SDavid du Colombier 		case Devlworm:
131301a344a2SDavid du Colombier 			return;
131401a344a2SDavid du Colombier 
131501a344a2SDavid du Colombier 		case Devfworm:
131601a344a2SDavid du Colombier 			fworminit(d);
131701a344a2SDavid du Colombier 			return;
131801a344a2SDavid du Colombier 
131901a344a2SDavid du Colombier 		case Devmcat:
132001a344a2SDavid du Colombier 			mcatinit(d);
132101a344a2SDavid du Colombier 			return;
132201a344a2SDavid du Colombier 
132301a344a2SDavid du Colombier 		case Devmlev:
132401a344a2SDavid du Colombier 			mlevinit(d);
132501a344a2SDavid du Colombier 			return;
132601a344a2SDavid du Colombier 
132701a344a2SDavid du Colombier 		case Devmirr:
132801a344a2SDavid du Colombier 			mirrinit(d);
132901a344a2SDavid du Colombier 			return;
133001a344a2SDavid du Colombier 
133101a344a2SDavid du Colombier 		case Devpart:
133201a344a2SDavid du Colombier 			partinit(d);
133301a344a2SDavid du Colombier 			return;
133401a344a2SDavid du Colombier 
133501a344a2SDavid du Colombier 		case Devswab:
133601a344a2SDavid du Colombier 			d = d->swab.d;
133701a344a2SDavid du Colombier 			break;
133801a344a2SDavid du Colombier 
133901a344a2SDavid du Colombier 		case Devnone:
134001a344a2SDavid du Colombier 			print("devinit of Devnone\n");
134101a344a2SDavid du Colombier 			return;
134201a344a2SDavid du Colombier 		}
134301a344a2SDavid du Colombier 	}
134401a344a2SDavid du Colombier }
134501a344a2SDavid du Colombier 
134601a344a2SDavid du Colombier void
swab2(void * c)134701a344a2SDavid du Colombier swab2(void *c)
134801a344a2SDavid du Colombier {
134901a344a2SDavid du Colombier 	uchar *p;
135001a344a2SDavid du Colombier 	int t;
135101a344a2SDavid du Colombier 
135201a344a2SDavid du Colombier 	p = c;
135301a344a2SDavid du Colombier 
135401a344a2SDavid du Colombier 	t = p[0];
135501a344a2SDavid du Colombier 	p[0] = p[1];
135601a344a2SDavid du Colombier 	p[1] = t;
135701a344a2SDavid du Colombier }
135801a344a2SDavid du Colombier 
135901a344a2SDavid du Colombier void
swab4(void * c)136001a344a2SDavid du Colombier swab4(void *c)
136101a344a2SDavid du Colombier {
136201a344a2SDavid du Colombier 	uchar *p;
136301a344a2SDavid du Colombier 	int t;
136401a344a2SDavid du Colombier 
136501a344a2SDavid du Colombier 	p = c;
136601a344a2SDavid du Colombier 
136701a344a2SDavid du Colombier 	t = p[0];
136801a344a2SDavid du Colombier 	p[0] = p[3];
136901a344a2SDavid du Colombier 	p[3] = t;
137001a344a2SDavid du Colombier 
137101a344a2SDavid du Colombier 	t = p[1];
137201a344a2SDavid du Colombier 	p[1] = p[2];
137301a344a2SDavid du Colombier 	p[2] = t;
137401a344a2SDavid du Colombier }
137501a344a2SDavid du Colombier 
137601a344a2SDavid du Colombier void
swab8(void * c)137701a344a2SDavid du Colombier swab8(void *c)
137801a344a2SDavid du Colombier {
137901a344a2SDavid du Colombier 	uchar *p;
138001a344a2SDavid du Colombier 	int t;
138101a344a2SDavid du Colombier 
138201a344a2SDavid du Colombier 	p = c;
138301a344a2SDavid du Colombier 
138401a344a2SDavid du Colombier 	t = p[0];
138501a344a2SDavid du Colombier 	p[0] = p[7];
138601a344a2SDavid du Colombier 	p[7] = t;
138701a344a2SDavid du Colombier 
138801a344a2SDavid du Colombier 	t = p[1];
138901a344a2SDavid du Colombier 	p[1] = p[6];
139001a344a2SDavid du Colombier 	p[6] = t;
139101a344a2SDavid du Colombier 
139201a344a2SDavid du Colombier 	t = p[2];
139301a344a2SDavid du Colombier 	p[2] = p[5];
139401a344a2SDavid du Colombier 	p[5] = t;
139501a344a2SDavid du Colombier 
139601a344a2SDavid du Colombier 	t = p[3];
139701a344a2SDavid du Colombier 	p[3] = p[4];
139801a344a2SDavid du Colombier 	p[4] = t;
139901a344a2SDavid du Colombier }
140001a344a2SDavid du Colombier 
140101a344a2SDavid du Colombier /*
140201a344a2SDavid du Colombier  * swab a block
140301a344a2SDavid du Colombier  *	flag = 0 -- convert from foreign to native
140401a344a2SDavid du Colombier  *	flag = 1 -- convert from native to foreign
140501a344a2SDavid du Colombier  */
140601a344a2SDavid du Colombier void
swab(void * c,int flag)140701a344a2SDavid du Colombier swab(void *c, int flag)
140801a344a2SDavid du Colombier {
140901a344a2SDavid du Colombier 	uchar *p;
141001a344a2SDavid du Colombier 	Tag *t;
141101a344a2SDavid du Colombier 	int i, j;
141201a344a2SDavid du Colombier 	Dentry *d;
141301a344a2SDavid du Colombier 	Cache *h;
141401a344a2SDavid du Colombier 	Bucket *b;
141501a344a2SDavid du Colombier 	Superb *s;
141601a344a2SDavid du Colombier 	Fbuf *f;
141701a344a2SDavid du Colombier 	Off *l;
141801a344a2SDavid du Colombier 
141901a344a2SDavid du Colombier 	/* swab the tag */
142001a344a2SDavid du Colombier 	p = (uchar*)c;
142101a344a2SDavid du Colombier 	t = (Tag*)(p + BUFSIZE);
142201a344a2SDavid du Colombier 	if(!flag) {
142301a344a2SDavid du Colombier 		swab2(&t->pad);
142401a344a2SDavid du Colombier 		swab2(&t->tag);
142501a344a2SDavid du Colombier 		swaboff(&t->path);
142601a344a2SDavid du Colombier 	}
142701a344a2SDavid du Colombier 
142801a344a2SDavid du Colombier 	/* swab each block type */
142901a344a2SDavid du Colombier 	switch(t->tag) {
143001a344a2SDavid du Colombier 
143101a344a2SDavid du Colombier 	default:
143201a344a2SDavid du Colombier 		print("no swab for tag=%G rw=%d\n", t->tag, flag);
143301a344a2SDavid du Colombier 		for(j=0; j<16; j++)
143401a344a2SDavid du Colombier 			print(" %.2x", p[BUFSIZE+j]);
143501a344a2SDavid du Colombier 		print("\n");
143601a344a2SDavid du Colombier 		for(i=0; i<16; i++) {
143701a344a2SDavid du Colombier 			print("%.4x", i*16);
143801a344a2SDavid du Colombier 			for(j=0; j<16; j++)
143901a344a2SDavid du Colombier 				print(" %.2x", p[i*16+j]);
144001a344a2SDavid du Colombier 			print("\n");
144101a344a2SDavid du Colombier 		}
144201a344a2SDavid du Colombier 		panic("swab");
144301a344a2SDavid du Colombier 		break;
144401a344a2SDavid du Colombier 
144501a344a2SDavid du Colombier 	case Tsuper:
144601a344a2SDavid du Colombier 		s = (Superb*)p;
144701a344a2SDavid du Colombier 		swaboff(&s->fbuf.nfree);
144801a344a2SDavid du Colombier 		for(i=0; i<FEPERBUF; i++)
144901a344a2SDavid du Colombier 			swaboff(&s->fbuf.free[i]);
145001a344a2SDavid du Colombier 		swaboff(&s->fstart);
145101a344a2SDavid du Colombier 		swaboff(&s->fsize);
145201a344a2SDavid du Colombier 		swaboff(&s->tfree);
145301a344a2SDavid du Colombier 		swaboff(&s->qidgen);
145401a344a2SDavid du Colombier 		swaboff(&s->cwraddr);
145501a344a2SDavid du Colombier 		swaboff(&s->roraddr);
145601a344a2SDavid du Colombier 		swaboff(&s->last);
145701a344a2SDavid du Colombier 		swaboff(&s->next);
145801a344a2SDavid du Colombier 		break;
145901a344a2SDavid du Colombier 
146001a344a2SDavid du Colombier 	case Tdir:
146101a344a2SDavid du Colombier 		for(i=0; i<DIRPERBUF; i++) {
146201a344a2SDavid du Colombier 			d = (Dentry*)p + i;
146301a344a2SDavid du Colombier 			swab2(&d->uid);
146401a344a2SDavid du Colombier 			swab2(&d->gid);
146501a344a2SDavid du Colombier 			swab2(&d->mode);
146601a344a2SDavid du Colombier 			swab2(&d->muid);
146701a344a2SDavid du Colombier 			swaboff(&d->qid.path);
146801a344a2SDavid du Colombier 			swab4(&d->qid.version);
146901a344a2SDavid du Colombier 			swaboff(&d->size);
147001a344a2SDavid du Colombier 			for(j=0; j<NDBLOCK; j++)
147101a344a2SDavid du Colombier 				swaboff(&d->dblock[j]);
147201a344a2SDavid du Colombier 			for (j = 0; j < NIBLOCK; j++)
147301a344a2SDavid du Colombier 				swaboff(&d->iblocks[j]);
147401a344a2SDavid du Colombier 			swab4(&d->atime);
147501a344a2SDavid du Colombier 			swab4(&d->mtime);
147601a344a2SDavid du Colombier 		}
147701a344a2SDavid du Colombier 		break;
147801a344a2SDavid du Colombier 
147901a344a2SDavid du Colombier 	case Tind1:
148001a344a2SDavid du Colombier 	case Tind2:
148101a344a2SDavid du Colombier #ifndef COMPAT32
148201a344a2SDavid du Colombier 	case Tind3:
148301a344a2SDavid du Colombier 	case Tind4:
148401a344a2SDavid du Colombier 	/* add more Tind tags here ... */
148501a344a2SDavid du Colombier #endif
148601a344a2SDavid du Colombier 		l = (Off *)p;
148701a344a2SDavid du Colombier 		for(i=0; i<INDPERBUF; i++) {
148801a344a2SDavid du Colombier 			swaboff(l);
148901a344a2SDavid du Colombier 			l++;
149001a344a2SDavid du Colombier 		}
149101a344a2SDavid du Colombier 		break;
149201a344a2SDavid du Colombier 
149301a344a2SDavid du Colombier 	case Tfree:
149401a344a2SDavid du Colombier 		f = (Fbuf*)p;
149501a344a2SDavid du Colombier 		swaboff(&f->nfree);
149601a344a2SDavid du Colombier 		for(i=0; i<FEPERBUF; i++)
149701a344a2SDavid du Colombier 			swaboff(&f->free[i]);
149801a344a2SDavid du Colombier 		break;
149901a344a2SDavid du Colombier 
150001a344a2SDavid du Colombier 	case Tbuck:
150101a344a2SDavid du Colombier 		for(i=0; i<BKPERBLK; i++) {
150201a344a2SDavid du Colombier 			b = (Bucket*)p + i;
150301a344a2SDavid du Colombier 			swab4(&b->agegen);
150401a344a2SDavid du Colombier 			for(j=0; j<CEPERBK; j++) {
150501a344a2SDavid du Colombier 				swab2(&b->entry[j].age);
150601a344a2SDavid du Colombier 				swab2(&b->entry[j].state);
150701a344a2SDavid du Colombier 				swaboff(&b->entry[j].waddr);
150801a344a2SDavid du Colombier 			}
150901a344a2SDavid du Colombier 		}
151001a344a2SDavid du Colombier 		break;
151101a344a2SDavid du Colombier 
151201a344a2SDavid du Colombier 	case Tcache:
151301a344a2SDavid du Colombier 		h = (Cache*)p;
151401a344a2SDavid du Colombier 		swaboff(&h->maddr);
151501a344a2SDavid du Colombier 		swaboff(&h->msize);
151601a344a2SDavid du Colombier 		swaboff(&h->caddr);
151701a344a2SDavid du Colombier 		swaboff(&h->csize);
151801a344a2SDavid du Colombier 		swaboff(&h->fsize);
151901a344a2SDavid du Colombier 		swaboff(&h->wsize);
152001a344a2SDavid du Colombier 		swaboff(&h->wmax);
152101a344a2SDavid du Colombier 		swaboff(&h->sbaddr);
152201a344a2SDavid du Colombier 		swaboff(&h->cwraddr);
152301a344a2SDavid du Colombier 		swaboff(&h->roraddr);
152401a344a2SDavid du Colombier 		swab4(&h->toytime);
152501a344a2SDavid du Colombier 		swab4(&h->time);
152601a344a2SDavid du Colombier 		break;
152701a344a2SDavid du Colombier 
152801a344a2SDavid du Colombier 	case Tnone:	// unitialized
152901a344a2SDavid du Colombier 	case Tfile:	// someone elses problem
153001a344a2SDavid du Colombier 	case Tvirgo:	// bit map -- all bytes
153101a344a2SDavid du Colombier 	case Tconfig:	// configuration string -- all bytes
153201a344a2SDavid du Colombier 		break;
153301a344a2SDavid du Colombier 	}
153401a344a2SDavid du Colombier 
153501a344a2SDavid du Colombier 	/* swab the tag */
153601a344a2SDavid du Colombier 	if(flag) {
153701a344a2SDavid du Colombier 		swab2(&t->pad);
153801a344a2SDavid du Colombier 		swab2(&t->tag);
153901a344a2SDavid du Colombier 		swaboff(&t->path);
154001a344a2SDavid du Colombier 	}
154101a344a2SDavid du Colombier }
1542