xref: /plan9/sys/src/cmd/disk/kfs/sub.c (revision 2bef681aed9a53ac1dc6db418047b00f7a5ce209)
13e12c5d1SDavid du Colombier #include	"all.h"
23e12c5d1SDavid du Colombier 
39a747e4fSDavid du Colombier Lock wpathlock;
49a747e4fSDavid du Colombier 
57dd7cddfSDavid du Colombier struct {
67dd7cddfSDavid du Colombier 	Lock	flock;
77dd7cddfSDavid du Colombier 	File*	ffree;		/* free file structures */
87dd7cddfSDavid du Colombier 	Wpath*	wfree;
97dd7cddfSDavid du Colombier } suballoc;
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier enum{
127dd7cddfSDavid du Colombier 	Finc=	128,	/* allocation chunksize for files */
137dd7cddfSDavid du Colombier 	Fmax=	10000,	/* maximum file structures to be allocated */
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier 	Winc=	8*128,	/* allocation chunksize for wpath */
167dd7cddfSDavid du Colombier 	Wmax=	8*10000,	/* maximum wpath structures to be allocated */
177dd7cddfSDavid du Colombier };
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier 
203e12c5d1SDavid du Colombier Filsys*
fsstr(char * p)213e12c5d1SDavid du Colombier fsstr(char *p)
223e12c5d1SDavid du Colombier {
233e12c5d1SDavid du Colombier 	Filsys *fs;
243e12c5d1SDavid du Colombier 
257dd7cddfSDavid du Colombier 	for(fs=filesys; fs->name; fs++)
263e12c5d1SDavid du Colombier 		if(strcmp(fs->name, p) == 0)
273e12c5d1SDavid du Colombier 			return fs;
283e12c5d1SDavid du Colombier 	return 0;
293e12c5d1SDavid du Colombier }
303e12c5d1SDavid du Colombier 
313e12c5d1SDavid du Colombier void
fileinit(Chan * cp)323e12c5d1SDavid du Colombier fileinit(Chan *cp)
333e12c5d1SDavid du Colombier {
343e12c5d1SDavid du Colombier 	File *f;
353e12c5d1SDavid du Colombier 	Tlock *t;
363e12c5d1SDavid du Colombier 
373e12c5d1SDavid du Colombier loop:
383e12c5d1SDavid du Colombier 	lock(&cp->flock);
393e12c5d1SDavid du Colombier 	f = cp->flist;
403e12c5d1SDavid du Colombier 	if(!f) {
413e12c5d1SDavid du Colombier 		unlock(&cp->flock);
423e12c5d1SDavid du Colombier 		return;
433e12c5d1SDavid du Colombier 	}
443e12c5d1SDavid du Colombier 	cp->flist = f->next;
453e12c5d1SDavid du Colombier 	unlock(&cp->flock);
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier 	qlock(f);
483e12c5d1SDavid du Colombier 	if(t = f->tlock) {
493e12c5d1SDavid du Colombier 		t->time = 0;
503e12c5d1SDavid du Colombier 		f->tlock = 0;
513e12c5d1SDavid du Colombier 	}
523e12c5d1SDavid du Colombier 	if(f->open & FREMOV)
533e12c5d1SDavid du Colombier 		doremove(f, 0);
543e12c5d1SDavid du Colombier 	freewp(f->wpath);
553e12c5d1SDavid du Colombier 	f->open = 0;
563e12c5d1SDavid du Colombier 	f->cp = 0;
573e12c5d1SDavid du Colombier 	qunlock(f);
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier 	goto loop;
603e12c5d1SDavid du Colombier }
613e12c5d1SDavid du Colombier 
623e12c5d1SDavid du Colombier /*
633e12c5d1SDavid du Colombier  * returns a locked file structure
643e12c5d1SDavid du Colombier  */
653e12c5d1SDavid du Colombier File*
filep(Chan * cp,int fid,int flag)663e12c5d1SDavid du Colombier filep(Chan *cp, int fid, int flag)
673e12c5d1SDavid du Colombier {
683e12c5d1SDavid du Colombier 	File *f, *prev;
693e12c5d1SDavid du Colombier 
703e12c5d1SDavid du Colombier 	if(fid == NOF)
713e12c5d1SDavid du Colombier 		return 0;
723e12c5d1SDavid du Colombier 
733e12c5d1SDavid du Colombier loop:
743e12c5d1SDavid du Colombier 	lock(&cp->flock);
753e12c5d1SDavid du Colombier 	for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
763e12c5d1SDavid du Colombier 		if(f->fid != fid)
773e12c5d1SDavid du Colombier 			continue;
783e12c5d1SDavid du Colombier 		if(prev) {
793e12c5d1SDavid du Colombier 			prev->next = f->next;
803e12c5d1SDavid du Colombier 			f->next = cp->flist;
813e12c5d1SDavid du Colombier 			cp->flist = f;
823e12c5d1SDavid du Colombier 		}
833e12c5d1SDavid du Colombier 		goto out;
843e12c5d1SDavid du Colombier 	}
853e12c5d1SDavid du Colombier 	if(flag) {
863e12c5d1SDavid du Colombier 		f = newfp(cp);
873e12c5d1SDavid du Colombier 		if(f) {
883e12c5d1SDavid du Colombier 			f->fid = fid;
893e12c5d1SDavid du Colombier 			goto out;
903e12c5d1SDavid du Colombier 		}
913e12c5d1SDavid du Colombier 	}
929a747e4fSDavid du Colombier else print("cannot find %p.%d (list=%p)\n", cp, fid, cp->flist);
933e12c5d1SDavid du Colombier 	unlock(&cp->flock);
943e12c5d1SDavid du Colombier 	return 0;
953e12c5d1SDavid du Colombier 
963e12c5d1SDavid du Colombier out:
973e12c5d1SDavid du Colombier 	unlock(&cp->flock);
983e12c5d1SDavid du Colombier 	qlock(f);
993e12c5d1SDavid du Colombier 	if(f->fid != fid) {
1003e12c5d1SDavid du Colombier 		qunlock(f);
1013e12c5d1SDavid du Colombier 		goto loop;
1023e12c5d1SDavid du Colombier 	}
1033e12c5d1SDavid du Colombier 	return f;
1043e12c5d1SDavid du Colombier }
1053e12c5d1SDavid du Colombier 
1067dd7cddfSDavid du Colombier void
sublockinit(void)1077dd7cddfSDavid du Colombier sublockinit(void)
1087dd7cddfSDavid du Colombier {
1097dd7cddfSDavid du Colombier 	lock(&suballoc.flock);
1109a747e4fSDavid du Colombier 	lock(&wpathlock);
1117dd7cddfSDavid du Colombier 	conf.nfile = 0;
1127dd7cddfSDavid du Colombier 	conf.nwpath = 0;
1137dd7cddfSDavid du Colombier 	unlock(&suballoc.flock);
1149a747e4fSDavid du Colombier 	unlock(&wpathlock);
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier 
1173e12c5d1SDavid du Colombier /*
1183e12c5d1SDavid du Colombier  * always called with cp->flock locked
1193e12c5d1SDavid du Colombier  */
1203e12c5d1SDavid du Colombier File*
newfp(Chan * cp)1213e12c5d1SDavid du Colombier newfp(Chan *cp)
1223e12c5d1SDavid du Colombier {
1237dd7cddfSDavid du Colombier 	File *f, *e;
1243e12c5d1SDavid du Colombier 
1257dd7cddfSDavid du Colombier retry:
1267dd7cddfSDavid du Colombier 	lock(&suballoc.flock);
1277dd7cddfSDavid du Colombier 	f = suballoc.ffree;
1287dd7cddfSDavid du Colombier 	if(f != nil){
1297dd7cddfSDavid du Colombier 		suballoc.ffree = f->list;
1307dd7cddfSDavid du Colombier 		unlock(&suballoc.flock);
1317dd7cddfSDavid du Colombier 		f->list = 0;
1323e12c5d1SDavid du Colombier 		f->cp = cp;
1333e12c5d1SDavid du Colombier 		f->next = cp->flist;
1343e12c5d1SDavid du Colombier 		f->wpath = 0;
1353e12c5d1SDavid du Colombier 		f->tlock = 0;
1369a747e4fSDavid du Colombier 		f->dslot = 0;
1379a747e4fSDavid du Colombier 		f->doffset = 0;
1385d459b5aSDavid du Colombier 		f->uid = 0;
1395d459b5aSDavid du Colombier 		f->cuid = 0;
1403e12c5d1SDavid du Colombier 		cp->flist = f;
1413e12c5d1SDavid du Colombier 		return f;
1427dd7cddfSDavid du Colombier 	}
1437dd7cddfSDavid du Colombier 	unlock(&suballoc.flock);
1443e12c5d1SDavid du Colombier 
1457dd7cddfSDavid du Colombier 	if(conf.nfile > Fmax){
1463e12c5d1SDavid du Colombier 		print("%d: out of files\n", cp->chan);
1473e12c5d1SDavid du Colombier 		return 0;
1483e12c5d1SDavid du Colombier 	}
1493e12c5d1SDavid du Colombier 
1507dd7cddfSDavid du Colombier 	/*
1517dd7cddfSDavid du Colombier 	 *  create a few new files
1527dd7cddfSDavid du Colombier 	 */
1537dd7cddfSDavid du Colombier 	f = malloc(Finc*sizeof(*f));
1547dd7cddfSDavid du Colombier 	memset(f, 0, Finc*sizeof(*f));
1557dd7cddfSDavid du Colombier 	lock(&suballoc.flock);
1567dd7cddfSDavid du Colombier 	for(e = f+Finc; f < e; f++){
1577dd7cddfSDavid du Colombier 		qlock(f);
1587dd7cddfSDavid du Colombier 		qunlock(f);
1597dd7cddfSDavid du Colombier 		f->list = suballoc.ffree;
1607dd7cddfSDavid du Colombier 		suballoc.ffree = f;
1617dd7cddfSDavid du Colombier 	}
1627dd7cddfSDavid du Colombier 	conf.nfile += Finc;
1637dd7cddfSDavid du Colombier 	unlock(&suballoc.flock);
1647dd7cddfSDavid du Colombier 	goto retry;
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier 
1673e12c5d1SDavid du Colombier void
freefp(File * fp)1683e12c5d1SDavid du Colombier freefp(File *fp)
1693e12c5d1SDavid du Colombier {
1703e12c5d1SDavid du Colombier 	Chan *cp;
1713e12c5d1SDavid du Colombier 	File *f, *prev;
1723e12c5d1SDavid du Colombier 
1733e12c5d1SDavid du Colombier 	if(!fp || !(cp = fp->cp))
1743e12c5d1SDavid du Colombier 		return;
175b7b24591SDavid du Colombier 	authfree(fp);
1763e12c5d1SDavid du Colombier 	lock(&cp->flock);
1773e12c5d1SDavid du Colombier 	for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
1783e12c5d1SDavid du Colombier 		if(f != fp)
1793e12c5d1SDavid du Colombier 			continue;
1803e12c5d1SDavid du Colombier 		if(prev)
1813e12c5d1SDavid du Colombier 			prev->next = f->next;
1823e12c5d1SDavid du Colombier 		else
1833e12c5d1SDavid du Colombier 			cp->flist = f->next;
1843e12c5d1SDavid du Colombier 		f->cp = 0;
1857dd7cddfSDavid du Colombier 		lock(&suballoc.flock);
1867dd7cddfSDavid du Colombier 		f->list = suballoc.ffree;
1877dd7cddfSDavid du Colombier 		suballoc.ffree = f;
1887dd7cddfSDavid du Colombier 		unlock(&suballoc.flock);
1893e12c5d1SDavid du Colombier 		break;
1903e12c5d1SDavid du Colombier 	}
1913e12c5d1SDavid du Colombier 	unlock(&cp->flock);
1923e12c5d1SDavid du Colombier }
1933e12c5d1SDavid du Colombier 
1947dd7cddfSDavid du Colombier Wpath*
newwp(void)1957dd7cddfSDavid du Colombier newwp(void)
1967dd7cddfSDavid du Colombier {
1977dd7cddfSDavid du Colombier 	Wpath *w, *e;
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier retry:
2009a747e4fSDavid du Colombier 	lock(&wpathlock);
2017dd7cddfSDavid du Colombier 	w = suballoc.wfree;
2027dd7cddfSDavid du Colombier 	if(w != nil){
2037dd7cddfSDavid du Colombier 		suballoc.wfree = w->list;
2049a747e4fSDavid du Colombier 		unlock(&wpathlock);
2057dd7cddfSDavid du Colombier 		memset(w, 0, sizeof(*w));
2067dd7cddfSDavid du Colombier 		w->refs = 1;
2077dd7cddfSDavid du Colombier 		w->up = 0;
2087dd7cddfSDavid du Colombier 		return w;
2097dd7cddfSDavid du Colombier 	}
2109a747e4fSDavid du Colombier 	unlock(&wpathlock);
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier 	if(conf.nwpath > Wmax){
2137dd7cddfSDavid du Colombier 		print("out of wpaths\n");
2147dd7cddfSDavid du Colombier 		return 0;
2157dd7cddfSDavid du Colombier 	}
2167dd7cddfSDavid du Colombier 
2177dd7cddfSDavid du Colombier 	/*
2187dd7cddfSDavid du Colombier 	 *  create a few new wpaths
2197dd7cddfSDavid du Colombier 	 */
2207dd7cddfSDavid du Colombier 	w = malloc(Winc*sizeof(*w));
2217dd7cddfSDavid du Colombier 	memset(w, 0, Winc*sizeof(*w));
2229a747e4fSDavid du Colombier 	lock(&wpathlock);
2237dd7cddfSDavid du Colombier 	for(e = w+Winc; w < e; w++){
2247dd7cddfSDavid du Colombier 		w->list = suballoc.wfree;
2257dd7cddfSDavid du Colombier 		suballoc.wfree = w;
2267dd7cddfSDavid du Colombier 	}
2277dd7cddfSDavid du Colombier 	conf.nwpath += Winc;
2289a747e4fSDavid du Colombier 	unlock(&wpathlock);
2297dd7cddfSDavid du Colombier 	goto retry;
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier 
2327dd7cddfSDavid du Colombier /*
2337dd7cddfSDavid du Colombier  *  increment the references for the whole path
2347dd7cddfSDavid du Colombier  */
2357dd7cddfSDavid du Colombier Wpath*
getwp(Wpath * w)2367dd7cddfSDavid du Colombier getwp(Wpath *w)
2377dd7cddfSDavid du Colombier {
2387dd7cddfSDavid du Colombier 	Wpath *nw;
2397dd7cddfSDavid du Colombier 
2409a747e4fSDavid du Colombier 	lock(&wpathlock);
2417dd7cddfSDavid du Colombier 	for(nw = w; nw; nw=nw->up)
2427dd7cddfSDavid du Colombier 		nw->refs++;
2439a747e4fSDavid du Colombier 	unlock(&wpathlock);
2447dd7cddfSDavid du Colombier 	return w;
2457dd7cddfSDavid du Colombier }
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier /*
2487dd7cddfSDavid du Colombier  *  decrement the reference for each element of the path
2497dd7cddfSDavid du Colombier  */
2507dd7cddfSDavid du Colombier void
freewp(Wpath * w)2517dd7cddfSDavid du Colombier freewp(Wpath *w)
2527dd7cddfSDavid du Colombier {
2539a747e4fSDavid du Colombier 	lock(&wpathlock);
2547dd7cddfSDavid du Colombier 	for(; w; w=w->up){
2557dd7cddfSDavid du Colombier 		w->refs--;
2567dd7cddfSDavid du Colombier 		if(w->refs == 0){
2577dd7cddfSDavid du Colombier 			w->list = suballoc.wfree;
2587dd7cddfSDavid du Colombier 			suballoc.wfree = w;
2597dd7cddfSDavid du Colombier 		}
2607dd7cddfSDavid du Colombier 	}
2619a747e4fSDavid du Colombier 	unlock(&wpathlock);
2627dd7cddfSDavid du Colombier }
2637dd7cddfSDavid du Colombier 
2647dd7cddfSDavid du Colombier /*
2657dd7cddfSDavid du Colombier  *  decrement the reference for just this element
2667dd7cddfSDavid du Colombier  */
2677dd7cddfSDavid du Colombier void
putwp(Wpath * w)2687dd7cddfSDavid du Colombier putwp(Wpath *w)
2697dd7cddfSDavid du Colombier {
2709a747e4fSDavid du Colombier 	lock(&wpathlock);
2717dd7cddfSDavid du Colombier 	w->refs--;
2727dd7cddfSDavid du Colombier 	if(w->refs == 0){
2737dd7cddfSDavid du Colombier 		w->list = suballoc.wfree;
2747dd7cddfSDavid du Colombier 		suballoc.wfree = w;
2757dd7cddfSDavid du Colombier 	}
2769a747e4fSDavid du Colombier 	unlock(&wpathlock);
2777dd7cddfSDavid du Colombier }
2787dd7cddfSDavid du Colombier 
2793e12c5d1SDavid du Colombier int
iaccess(File * f,Dentry * d,int m)2803e12c5d1SDavid du Colombier iaccess(File *f, Dentry *d, int m)
2813e12c5d1SDavid du Colombier {
282bd389b36SDavid du Colombier 	if(wstatallow)
2833e12c5d1SDavid du Colombier 		return 0;
2849a747e4fSDavid du Colombier 
2853e12c5d1SDavid du Colombier 	/*
2863e12c5d1SDavid du Colombier 	 * owner is next
2873e12c5d1SDavid du Colombier 	 */
2883e12c5d1SDavid du Colombier 	if(f->uid == d->uid)
2893e12c5d1SDavid du Colombier 		if((m<<6) & d->mode)
2903e12c5d1SDavid du Colombier 			return 0;
2913e12c5d1SDavid du Colombier 	/*
2923e12c5d1SDavid du Colombier 	 * group membership is hard
2933e12c5d1SDavid du Colombier 	 */
2943e12c5d1SDavid du Colombier 	if(ingroup(f->uid, d->gid))
2953e12c5d1SDavid du Colombier 		if((m<<3) & d->mode)
2963e12c5d1SDavid du Colombier 			return 0;
2975d459b5aSDavid du Colombier 	/*
2985d459b5aSDavid du Colombier 	 * other access for everyone except members of group 9999
2995d459b5aSDavid du Colombier 	 */
3005d459b5aSDavid du Colombier 	if(m & d->mode){
3015d459b5aSDavid du Colombier 		/*
3025d459b5aSDavid du Colombier 		 *  walk directories regardless.
3035d459b5aSDavid du Colombier 		 *  otherwise its impossible to get
3045d459b5aSDavid du Colombier 		 *  from the root to noworld's directories.
3055d459b5aSDavid du Colombier 		 */
3065d459b5aSDavid du Colombier 		if((d->mode & DDIR) && (m == DEXEC))
3075d459b5aSDavid du Colombier 			return 0;
3085d459b5aSDavid du Colombier 		if(!ingroup(f->uid, 9999))
3095d459b5aSDavid du Colombier 			return 0;
3105d459b5aSDavid du Colombier 	}
3113e12c5d1SDavid du Colombier 	return 1;
3123e12c5d1SDavid du Colombier }
3133e12c5d1SDavid du Colombier 
3143e12c5d1SDavid du Colombier Tlock*
tlocked(Iobuf * p,Dentry * d)3153e12c5d1SDavid du Colombier tlocked(Iobuf *p, Dentry *d)
3163e12c5d1SDavid du Colombier {
3173e12c5d1SDavid du Colombier 	Tlock *t, *t1;
3183e12c5d1SDavid du Colombier 	long qpath, tim;
3193e12c5d1SDavid du Colombier 	Device dev;
3203e12c5d1SDavid du Colombier 
3217dd7cddfSDavid du Colombier 	tim = time(0);
3223e12c5d1SDavid du Colombier 	qpath = d->qid.path;
3233e12c5d1SDavid du Colombier 	dev = p->dev;
3243e12c5d1SDavid du Colombier 	t1 = 0;
3253e12c5d1SDavid du Colombier 	for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
3263e12c5d1SDavid du Colombier 		if(t->qpath == qpath)
3273e12c5d1SDavid du Colombier 		if(t->time >= tim)
3283e12c5d1SDavid du Colombier 		if(devcmp(t->dev, dev) == 0)
3293e12c5d1SDavid du Colombier 			return 0;		/* its locked */
3303e12c5d1SDavid du Colombier 		if(!t1 && t->time < tim)
3313e12c5d1SDavid du Colombier 			t1 = t;			/* steal first lock */
3323e12c5d1SDavid du Colombier 	}
3333e12c5d1SDavid du Colombier 	if(t1) {
3343e12c5d1SDavid du Colombier 		t1->dev = dev;
3353e12c5d1SDavid du Colombier 		t1->qpath = qpath;
3363e12c5d1SDavid du Colombier 		t1->time = tim + TLOCK;
3373e12c5d1SDavid du Colombier 	}
3383e12c5d1SDavid du Colombier 	/* botch
3393e12c5d1SDavid du Colombier 	 * out of tlock nodes simulates
3403e12c5d1SDavid du Colombier 	 * a locked file
3413e12c5d1SDavid du Colombier 	 */
3423e12c5d1SDavid du Colombier 	return t1;
3433e12c5d1SDavid du Colombier }
3443e12c5d1SDavid du Colombier 
3453e12c5d1SDavid du Colombier Qid
newqid(Device dev)3463e12c5d1SDavid du Colombier newqid(Device dev)
3473e12c5d1SDavid du Colombier {
3483e12c5d1SDavid du Colombier 	Iobuf *p;
3493e12c5d1SDavid du Colombier 	Superb *sb;
3503e12c5d1SDavid du Colombier 	Qid qid;
3513e12c5d1SDavid du Colombier 
3523e12c5d1SDavid du Colombier 	p = getbuf(dev, superaddr(dev), Bread|Bmod);
3533e12c5d1SDavid du Colombier 	if(!p || checktag(p, Tsuper, QPSUPER))
3543e12c5d1SDavid du Colombier 		panic("newqid: super block");
3553e12c5d1SDavid du Colombier 	sb = (Superb*)p->iobuf;
3563e12c5d1SDavid du Colombier 	sb->qidgen++;
3573e12c5d1SDavid du Colombier 	qid.path = sb->qidgen;
3587dd7cddfSDavid du Colombier 	qid.vers = 0;
359*2bef681aSDavid du Colombier 	qid.type = 0;
3603e12c5d1SDavid du Colombier 	putbuf(p);
3613e12c5d1SDavid du Colombier 	return qid;
3623e12c5d1SDavid du Colombier }
3633e12c5d1SDavid du Colombier 
3643e12c5d1SDavid du Colombier /*
3653e12c5d1SDavid du Colombier  * what are legal characters in a name?
3663e12c5d1SDavid du Colombier  * only disallow control characters.
3673e12c5d1SDavid du Colombier  * a) utf avoids control characters.
3683e12c5d1SDavid du Colombier  * b) '/' may not be the separator
3693e12c5d1SDavid du Colombier  */
3703e12c5d1SDavid du Colombier int
checkname(char * n)3713e12c5d1SDavid du Colombier checkname(char *n)
3723e12c5d1SDavid du Colombier {
3733e12c5d1SDavid du Colombier 	int i, c;
3743e12c5d1SDavid du Colombier 
3753e12c5d1SDavid du Colombier 	for(i=0; i<NAMELEN; i++) {
3763e12c5d1SDavid du Colombier 		c = *n & 0xff;
3773e12c5d1SDavid du Colombier 		if(c == 0) {
3783e12c5d1SDavid du Colombier 			if(i == 0)
3793e12c5d1SDavid du Colombier 				return 1;
3803e12c5d1SDavid du Colombier 			memset(n, 0, NAMELEN-i);
3813e12c5d1SDavid du Colombier 			return 0;
3823e12c5d1SDavid du Colombier 		}
3833e12c5d1SDavid du Colombier 		if(c <= 040)
3843e12c5d1SDavid du Colombier 			return 1;
3853e12c5d1SDavid du Colombier 		n++;
3863e12c5d1SDavid du Colombier 	}
3873e12c5d1SDavid du Colombier 	return 1;	/* too long */
3883e12c5d1SDavid du Colombier }
3893e12c5d1SDavid du Colombier 
3903e12c5d1SDavid du Colombier void
bfree(Device dev,long addr,int d)3913e12c5d1SDavid du Colombier bfree(Device dev, long addr, int d)
3923e12c5d1SDavid du Colombier {
3933e12c5d1SDavid du Colombier 	Iobuf *p;
3943e12c5d1SDavid du Colombier 	long a;
3953e12c5d1SDavid du Colombier 	int i;
3963e12c5d1SDavid du Colombier 
3973e12c5d1SDavid du Colombier 	if(!addr)
3983e12c5d1SDavid du Colombier 		return;
3993e12c5d1SDavid du Colombier 	if(d > 0) {
4003e12c5d1SDavid du Colombier 		d--;
4013e12c5d1SDavid du Colombier 		p = getbuf(dev, addr, Bread);
4023e12c5d1SDavid du Colombier 		if(p) {
4033e12c5d1SDavid du Colombier 			for(i=INDPERBUF-1; i>=0; i--) {
4043e12c5d1SDavid du Colombier 				a = ((long*)p->iobuf)[i];
4053e12c5d1SDavid du Colombier 				bfree(dev, a, d);
4063e12c5d1SDavid du Colombier 			}
4073e12c5d1SDavid du Colombier 			putbuf(p);
4083e12c5d1SDavid du Colombier 		}
4093e12c5d1SDavid du Colombier 	}
4103e12c5d1SDavid du Colombier 	/*
4113e12c5d1SDavid du Colombier 	 * stop outstanding i/o
4123e12c5d1SDavid du Colombier 	 */
4133e12c5d1SDavid du Colombier 	p = getbuf(dev, addr, Bprobe);
4143e12c5d1SDavid du Colombier 	if(p) {
4153e12c5d1SDavid du Colombier 		p->flags &= ~(Bmod|Bimm);
4163e12c5d1SDavid du Colombier 		putbuf(p);
4173e12c5d1SDavid du Colombier 	}
4183e12c5d1SDavid du Colombier 	/*
4193e12c5d1SDavid du Colombier 	 * dont put written worm
4203e12c5d1SDavid du Colombier 	 * blocks into free list
4213e12c5d1SDavid du Colombier 	 */
4223e12c5d1SDavid du Colombier 	if(nofree(dev, addr))
4233e12c5d1SDavid du Colombier 		return;
4243e12c5d1SDavid du Colombier 	p = getbuf(dev, superaddr(dev), Bread|Bmod);
4253e12c5d1SDavid du Colombier 	if(!p || checktag(p, Tsuper, QPSUPER))
4263e12c5d1SDavid du Colombier 		panic("bfree: super block");
4273e12c5d1SDavid du Colombier 	addfree(dev, addr, (Superb*)p->iobuf);
4283e12c5d1SDavid du Colombier 	putbuf(p);
4293e12c5d1SDavid du Colombier }
4303e12c5d1SDavid du Colombier 
4313e12c5d1SDavid du Colombier long
balloc(Device dev,int tag,long qid)4323e12c5d1SDavid du Colombier balloc(Device dev, int tag, long qid)
4333e12c5d1SDavid du Colombier {
4343e12c5d1SDavid du Colombier 	Iobuf *bp, *p;
4353e12c5d1SDavid du Colombier 	Superb *sb;
4363e12c5d1SDavid du Colombier 	long a;
4373e12c5d1SDavid du Colombier 	int n;
4383e12c5d1SDavid du Colombier 
4393e12c5d1SDavid du Colombier 	p = getbuf(dev, superaddr(dev), Bread|Bmod);
4403e12c5d1SDavid du Colombier 	if(!p || checktag(p, Tsuper, QPSUPER))
4413e12c5d1SDavid du Colombier 		panic("balloc: super block");
4423e12c5d1SDavid du Colombier 	sb = (Superb*)p->iobuf;
4433e12c5d1SDavid du Colombier 
4443e12c5d1SDavid du Colombier loop:
4453e12c5d1SDavid du Colombier 	n = --sb->fbuf.nfree;
4463e12c5d1SDavid du Colombier 	sb->tfree--;
4473e12c5d1SDavid du Colombier 	if(n < 0 || n >= FEPERBUF)
4483e12c5d1SDavid du Colombier 		panic("balloc: bad freelist");
4493e12c5d1SDavid du Colombier 	a = sb->fbuf.free[n];
4503e12c5d1SDavid du Colombier 	if(n <= 0) {
4513e12c5d1SDavid du Colombier 		if(a == 0) {
4523e12c5d1SDavid du Colombier 			sb->tfree = 0;
4533e12c5d1SDavid du Colombier 			sb->fbuf.nfree = 1;
4543e12c5d1SDavid du Colombier 			if(devgrow(dev, sb))
4553e12c5d1SDavid du Colombier 				goto loop;
4563e12c5d1SDavid du Colombier 			putbuf(p);
4573e12c5d1SDavid du Colombier 			return 0;
4583e12c5d1SDavid du Colombier 		}
4593e12c5d1SDavid du Colombier 		bp = getbuf(dev, a, Bread);
4603e12c5d1SDavid du Colombier 		if(!bp || checktag(bp, Tfree, QPNONE)) {
4613e12c5d1SDavid du Colombier 			if(bp)
4623e12c5d1SDavid du Colombier 				putbuf(bp);
4633e12c5d1SDavid du Colombier 			putbuf(p);
4643e12c5d1SDavid du Colombier 			return 0;
4653e12c5d1SDavid du Colombier 		}
466bd389b36SDavid du Colombier 		memmove(&sb->fbuf, bp->iobuf, (FEPERBUF+1)*sizeof(long));
4673e12c5d1SDavid du Colombier 		putbuf(bp);
4683e12c5d1SDavid du Colombier 	}
4693e12c5d1SDavid du Colombier 	bp = getbuf(dev, a, Bmod);
4703e12c5d1SDavid du Colombier 	memset(bp->iobuf, 0, RBUFSIZE);
4713e12c5d1SDavid du Colombier 	settag(bp, tag, qid);
4723e12c5d1SDavid du Colombier 	if(tag == Tind1 || tag == Tind2 || tag == Tdir)
4733e12c5d1SDavid du Colombier 		bp->flags |= Bimm;
4743e12c5d1SDavid du Colombier 	putbuf(bp);
4753e12c5d1SDavid du Colombier 	putbuf(p);
4763e12c5d1SDavid du Colombier 	return a;
4773e12c5d1SDavid du Colombier }
4783e12c5d1SDavid du Colombier 
4793e12c5d1SDavid du Colombier void
addfree(Device dev,long addr,Superb * sb)4803e12c5d1SDavid du Colombier addfree(Device dev, long addr, Superb *sb)
4813e12c5d1SDavid du Colombier {
4823e12c5d1SDavid du Colombier 	int n;
4833e12c5d1SDavid du Colombier 	Iobuf *p;
4843e12c5d1SDavid du Colombier 
4853e12c5d1SDavid du Colombier 	if(addr >= sb->fsize){
4863e12c5d1SDavid du Colombier 		print("addfree: bad addr %lux\n", addr);
4873e12c5d1SDavid du Colombier 		return;
4883e12c5d1SDavid du Colombier 	}
4893e12c5d1SDavid du Colombier 	n = sb->fbuf.nfree;
4903e12c5d1SDavid du Colombier 	if(n < 0 || n > FEPERBUF)
4913e12c5d1SDavid du Colombier 		panic("addfree: bad freelist");
4923e12c5d1SDavid du Colombier 	if(n >= FEPERBUF) {
4933e12c5d1SDavid du Colombier 		p = getbuf(dev, addr, Bmod);
4943e12c5d1SDavid du Colombier 		if(p == 0)
4953e12c5d1SDavid du Colombier 			panic("addfree: getbuf");
496bd389b36SDavid du Colombier 		memmove(p->iobuf, &sb->fbuf, (FEPERBUF+1)*sizeof(long));
4973e12c5d1SDavid du Colombier 		settag(p, Tfree, QPNONE);
4983e12c5d1SDavid du Colombier 		putbuf(p);
4993e12c5d1SDavid du Colombier 		n = 0;
5003e12c5d1SDavid du Colombier 	}
5013e12c5d1SDavid du Colombier 	sb->fbuf.free[n++] = addr;
5023e12c5d1SDavid du Colombier 	sb->fbuf.nfree = n;
5033e12c5d1SDavid du Colombier 	sb->tfree++;
5043e12c5d1SDavid du Colombier 	if(addr >= sb->fsize)
5053e12c5d1SDavid du Colombier 		sb->fsize = addr+1;
5063e12c5d1SDavid du Colombier }
5073e12c5d1SDavid du Colombier 
5083e12c5d1SDavid du Colombier int
Cfmt(Fmt * f1)5099a747e4fSDavid du Colombier Cfmt(Fmt *f1)
5103e12c5d1SDavid du Colombier {
5113e12c5d1SDavid du Colombier 	Chan *cp;
5123e12c5d1SDavid du Colombier 
5139a747e4fSDavid du Colombier 	cp = va_arg(f1->args, Chan*);
5149a747e4fSDavid du Colombier 	return fmtprint(f1, "C%d.%.3d", cp->type, cp->chan);
5153e12c5d1SDavid du Colombier }
5163e12c5d1SDavid du Colombier 
5173e12c5d1SDavid du Colombier int
Dfmt(Fmt * f1)5189a747e4fSDavid du Colombier Dfmt(Fmt *f1)
5193e12c5d1SDavid du Colombier {
5203e12c5d1SDavid du Colombier 	Device d;
5213e12c5d1SDavid du Colombier 
5229a747e4fSDavid du Colombier 	d = va_arg(f1->args, Device);
5239a747e4fSDavid du Colombier 	return fmtprint(f1, "D%d.%d.%d.%d", d.type, d.ctrl, d.unit, d.part);
5243e12c5d1SDavid du Colombier }
5253e12c5d1SDavid du Colombier 
5263e12c5d1SDavid du Colombier int
Afmt(Fmt * f1)5279a747e4fSDavid du Colombier Afmt(Fmt *f1)
5283e12c5d1SDavid du Colombier {
5293e12c5d1SDavid du Colombier 	Filta a;
5303e12c5d1SDavid du Colombier 
5319a747e4fSDavid du Colombier 	a = va_arg(f1->args, Filta);
5329a747e4fSDavid du Colombier 	return fmtprint(f1, "%6lud %6lud %6lud",
5333e12c5d1SDavid du Colombier 		fdf(a.f->filter[0], a.scale*60),
5343e12c5d1SDavid du Colombier 		fdf(a.f->filter[1], a.scale*600),
5353e12c5d1SDavid du Colombier 		fdf(a.f->filter[2], a.scale*6000));
5363e12c5d1SDavid du Colombier }
5373e12c5d1SDavid du Colombier 
5383e12c5d1SDavid du Colombier int
Gfmt(Fmt * f1)5399a747e4fSDavid du Colombier Gfmt(Fmt *f1)
5403e12c5d1SDavid du Colombier {
5413e12c5d1SDavid du Colombier 	int t;
5423e12c5d1SDavid du Colombier 
5439a747e4fSDavid du Colombier 	t = va_arg(f1->args, int);
5443e12c5d1SDavid du Colombier 	if(t >= 0 && t < MAXTAG)
5459a747e4fSDavid du Colombier 		return fmtstrcpy(f1, tagnames[t]);
5469a747e4fSDavid du Colombier 	else
5479a747e4fSDavid du Colombier 		return fmtprint(f1, "<badtag %d>", t);
5487dd7cddfSDavid du Colombier }
5497dd7cddfSDavid du Colombier 
5503e12c5d1SDavid du Colombier void
formatinit(void)5513e12c5d1SDavid du Colombier formatinit(void)
5523e12c5d1SDavid du Colombier {
5533e12c5d1SDavid du Colombier 
5549a747e4fSDavid du Colombier 	fmtinstall('C', Cfmt);	/* print channels */
5559a747e4fSDavid du Colombier 	fmtinstall('D', Dfmt);	/* print devices */
5569a747e4fSDavid du Colombier 	fmtinstall('A', Afmt);	/* print filters */
5579a747e4fSDavid du Colombier 	fmtinstall('G', Gfmt);	/* print tags */
5589a747e4fSDavid du Colombier 	fmtinstall('T', Tfmt);	/* print times */
5599a747e4fSDavid du Colombier 	fmtinstall('O', ofcallfmt);	/* print old fcalls */
5603e12c5d1SDavid du Colombier }
5613e12c5d1SDavid du Colombier int
devcmp(Device d1,Device d2)5623e12c5d1SDavid du Colombier devcmp(Device d1, Device d2)
5633e12c5d1SDavid du Colombier {
5643e12c5d1SDavid du Colombier 
5653e12c5d1SDavid du Colombier 	if(d1.type == d2.type)
5663e12c5d1SDavid du Colombier 	if(d1.ctrl == d2.ctrl)
5673e12c5d1SDavid du Colombier 	if(d1.unit == d2.unit)
5683e12c5d1SDavid du Colombier 	if(d1.part == d2.part)
5693e12c5d1SDavid du Colombier 		return 0;
5703e12c5d1SDavid du Colombier 	return 1;
5713e12c5d1SDavid du Colombier }
5723e12c5d1SDavid du Colombier 
5733e12c5d1SDavid du Colombier void
rootream(Device dev,long addr)5743e12c5d1SDavid du Colombier rootream(Device dev, long addr)
5753e12c5d1SDavid du Colombier {
5763e12c5d1SDavid du Colombier 	Iobuf *p;
5773e12c5d1SDavid du Colombier 	Dentry *d;
5783e12c5d1SDavid du Colombier 
5793e12c5d1SDavid du Colombier 	p = getbuf(dev, addr, Bmod|Bimm);
5803e12c5d1SDavid du Colombier 	memset(p->iobuf, 0, RBUFSIZE);
5813e12c5d1SDavid du Colombier 	settag(p, Tdir, QPROOT);
5823e12c5d1SDavid du Colombier 	d = getdir(p, 0);
5833e12c5d1SDavid du Colombier 	strcpy(d->name, "/");
5843e12c5d1SDavid du Colombier 	d->uid = -1;
5853e12c5d1SDavid du Colombier 	d->gid = -1;
5863e12c5d1SDavid du Colombier 	d->mode = DALLOC | DDIR |
5873e12c5d1SDavid du Colombier 		((DREAD|DWRITE|DEXEC) << 6) |
5883e12c5d1SDavid du Colombier 		((DREAD|DWRITE|DEXEC) << 3) |
5893e12c5d1SDavid du Colombier 		((DREAD|DWRITE|DEXEC) << 0);
5909a747e4fSDavid du Colombier 	d->qid = QID9P1(QPROOT|QPDIR,0);
5917dd7cddfSDavid du Colombier 	d->atime = time(0);
5923e12c5d1SDavid du Colombier 	d->mtime = d->atime;
5933e12c5d1SDavid du Colombier 	putbuf(p);
5943e12c5d1SDavid du Colombier }
5953e12c5d1SDavid du Colombier 
596219b2ee8SDavid du Colombier int
superok(Device dev,long addr,int set)597219b2ee8SDavid du Colombier superok(Device dev, long addr, int set)
598219b2ee8SDavid du Colombier {
599219b2ee8SDavid du Colombier 	Iobuf *p;
600219b2ee8SDavid du Colombier 	Superb *s;
601219b2ee8SDavid du Colombier 	int ok;
602219b2ee8SDavid du Colombier 
603219b2ee8SDavid du Colombier 	p = getbuf(dev, addr, Bread|Bmod|Bimm);
604219b2ee8SDavid du Colombier 	s = (Superb*)p->iobuf;
605219b2ee8SDavid du Colombier 	ok = s->fsok;
606219b2ee8SDavid du Colombier 	s->fsok = set;
607219b2ee8SDavid du Colombier 	putbuf(p);
608219b2ee8SDavid du Colombier 	return ok;
609219b2ee8SDavid du Colombier }
610219b2ee8SDavid du Colombier 
6113e12c5d1SDavid du Colombier void
superream(Device dev,long addr)6123e12c5d1SDavid du Colombier superream(Device dev, long addr)
6133e12c5d1SDavid du Colombier {
6143e12c5d1SDavid du Colombier 	Iobuf *p;
6153e12c5d1SDavid du Colombier 	Superb *s;
6163e12c5d1SDavid du Colombier 	long i;
6173e12c5d1SDavid du Colombier 
6183e12c5d1SDavid du Colombier 	p = getbuf(dev, addr, Bmod|Bimm);
6193e12c5d1SDavid du Colombier 	memset(p->iobuf, 0, RBUFSIZE);
6203e12c5d1SDavid du Colombier 	settag(p, Tsuper, QPSUPER);
6213e12c5d1SDavid du Colombier 
6223e12c5d1SDavid du Colombier 	s = (Superb*)p->iobuf;
6233e12c5d1SDavid du Colombier 	s->fstart = 1;
6243e12c5d1SDavid du Colombier 	s->fsize = devsize(dev);
6253e12c5d1SDavid du Colombier 	s->fbuf.nfree = 1;
6263e12c5d1SDavid du Colombier 	s->qidgen = 10;
6273e12c5d1SDavid du Colombier 	for(i=s->fsize-1; i>=addr+2; i--)
6283e12c5d1SDavid du Colombier 		addfree(dev, i, s);
6293e12c5d1SDavid du Colombier 	putbuf(p);
6303e12c5d1SDavid du Colombier }
6313e12c5d1SDavid du Colombier 
6323e12c5d1SDavid du Colombier /*
6333e12c5d1SDavid du Colombier  * returns 1 if n is prime
6343e12c5d1SDavid du Colombier  * used for adjusting lengths
6353e12c5d1SDavid du Colombier  * of hashing things.
6363e12c5d1SDavid du Colombier  * there is no need to be clever
6373e12c5d1SDavid du Colombier  */
6383e12c5d1SDavid du Colombier int
prime(long n)6393e12c5d1SDavid du Colombier prime(long n)
6403e12c5d1SDavid du Colombier {
6413e12c5d1SDavid du Colombier 	long i;
6423e12c5d1SDavid du Colombier 
6433e12c5d1SDavid du Colombier 	if((n%2) == 0)
6443e12c5d1SDavid du Colombier 		return 0;
6453e12c5d1SDavid du Colombier 	for(i=3;; i+=2) {
6463e12c5d1SDavid du Colombier 		if((n%i) == 0)
6473e12c5d1SDavid du Colombier 			return 0;
6483e12c5d1SDavid du Colombier 		if(i*i >= n)
6493e12c5d1SDavid du Colombier 			return 1;
6503e12c5d1SDavid du Colombier 	}
6513e12c5d1SDavid du Colombier }
6523e12c5d1SDavid du Colombier 
6533e12c5d1SDavid du Colombier void
hexdump(void * a,int n)6543e12c5d1SDavid du Colombier hexdump(void *a, int n)
6553e12c5d1SDavid du Colombier {
6563e12c5d1SDavid du Colombier 	char s1[30], s2[4];
6573e12c5d1SDavid du Colombier 	uchar *p;
6583e12c5d1SDavid du Colombier 	int i;
6593e12c5d1SDavid du Colombier 
6603e12c5d1SDavid du Colombier 	p = a;
6613e12c5d1SDavid du Colombier 	s1[0] = 0;
6623e12c5d1SDavid du Colombier 	for(i=0; i<n; i++) {
6633e12c5d1SDavid du Colombier 		sprint(s2, " %.2ux", p[i]);
6643e12c5d1SDavid du Colombier 		strcat(s1, s2);
6653e12c5d1SDavid du Colombier 		if((i&7) == 7) {
6663e12c5d1SDavid du Colombier 			print("%s\n", s1);
6673e12c5d1SDavid du Colombier 			s1[0] = 0;
6683e12c5d1SDavid du Colombier 		}
6693e12c5d1SDavid du Colombier 	}
6703e12c5d1SDavid du Colombier 	if(s1[0])
6713e12c5d1SDavid du Colombier 		print("%s\n", s1);
6723e12c5d1SDavid du Colombier }
6739a747e4fSDavid du Colombier 
6749a747e4fSDavid du Colombier long
qidpathgen(Device * dev)6759a747e4fSDavid du Colombier qidpathgen(Device *dev)
6769a747e4fSDavid du Colombier {
6779a747e4fSDavid du Colombier 	Iobuf *p;
6789a747e4fSDavid du Colombier 	Superb *sb;
6799a747e4fSDavid du Colombier 	long path;
6809a747e4fSDavid du Colombier 
6819a747e4fSDavid du Colombier 	p = getbuf(*dev, superaddr((*dev)), Bread|Bmod);
6829a747e4fSDavid du Colombier 	if(!p || checktag(p, Tsuper, QPSUPER))
6839a747e4fSDavid du Colombier 		panic("newqid: super block");
6849a747e4fSDavid du Colombier 	sb = (Superb*)p->iobuf;
6859a747e4fSDavid du Colombier 	sb->qidgen++;
6869a747e4fSDavid du Colombier 	path = sb->qidgen;
6879a747e4fSDavid du Colombier 	putbuf(p);
6889a747e4fSDavid du Colombier 	return path;
6899a747e4fSDavid du Colombier }
6909a747e4fSDavid du Colombier 
691