xref: /plan9/sys/src/cmd/cwfs/chk.c (revision 01a344a29f2ff35133953eaef092a50fc8c3163b)
1*01a344a2SDavid du Colombier #include	"all.h"
2*01a344a2SDavid du Colombier 
3*01a344a2SDavid du Colombier /* augmented Dentry */
4*01a344a2SDavid du Colombier typedef struct {
5*01a344a2SDavid du Colombier 	Dentry	*d;
6*01a344a2SDavid du Colombier 	Off	qpath;
7*01a344a2SDavid du Colombier 	int	ns;
8*01a344a2SDavid du Colombier } Extdentry;
9*01a344a2SDavid du Colombier 
10*01a344a2SDavid du Colombier static	char*	abits;
11*01a344a2SDavid du Colombier static	long	sizabits;
12*01a344a2SDavid du Colombier static	char*	qbits;
13*01a344a2SDavid du Colombier static	long	sizqbits;
14*01a344a2SDavid du Colombier 
15*01a344a2SDavid du Colombier static	char*	name;
16*01a344a2SDavid du Colombier static	long	sizname;
17*01a344a2SDavid du Colombier 
18*01a344a2SDavid du Colombier static	Off	fstart;
19*01a344a2SDavid du Colombier static	Off	fsize;
20*01a344a2SDavid du Colombier static	Off	nfiles;
21*01a344a2SDavid du Colombier static	Off	maxq;
22*01a344a2SDavid du Colombier static	Device*	dev;
23*01a344a2SDavid du Colombier static	Off	ndup;
24*01a344a2SDavid du Colombier static	Off	nused;
25*01a344a2SDavid du Colombier static	Off	nfdup;
26*01a344a2SDavid du Colombier static	Off	nqbad;
27*01a344a2SDavid du Colombier static	Off	nfree;
28*01a344a2SDavid du Colombier static	Off	nbad;
29*01a344a2SDavid du Colombier static	int	mod;
30*01a344a2SDavid du Colombier static	int	flags;
31*01a344a2SDavid du Colombier static	int	ronly;
32*01a344a2SDavid du Colombier static	int	cwflag;
33*01a344a2SDavid du Colombier static	Devsize	sbaddr;
34*01a344a2SDavid du Colombier static	Devsize	oldblock;
35*01a344a2SDavid du Colombier 
36*01a344a2SDavid du Colombier static	int	depth;
37*01a344a2SDavid du Colombier static	int	maxdepth;
38*01a344a2SDavid du Colombier static	uchar	*lowstack, *startstack;
39*01a344a2SDavid du Colombier 
40*01a344a2SDavid du Colombier /* local prototypes */
41*01a344a2SDavid du Colombier static	int	amark(Off);
42*01a344a2SDavid du Colombier static	void*	chkalloc(ulong);
43*01a344a2SDavid du Colombier static	void	ckfreelist(Superb*);
44*01a344a2SDavid du Colombier static	int	fmark(Off);
45*01a344a2SDavid du Colombier static	int	fsck(Dentry*);
46*01a344a2SDavid du Colombier static	int	ftest(Off);
47*01a344a2SDavid du Colombier static	Dentry*	maked(Off, int, Off);
48*01a344a2SDavid du Colombier static	void	missing(void);
49*01a344a2SDavid du Colombier static	void	mkfreelist(Superb*);
50*01a344a2SDavid du Colombier static	void	modd(Off, int, Dentry*);
51*01a344a2SDavid du Colombier static	void	qmark(Off);
52*01a344a2SDavid du Colombier static	void	trfreelist(Superb*);
53*01a344a2SDavid du Colombier static	void	xaddfree(Device*, Off, Superb*, Iobuf*);
54*01a344a2SDavid du Colombier static	void	xflush(Device*, Superb*, Iobuf*);
55*01a344a2SDavid du Colombier static	void	xread(Off, Off);
56*01a344a2SDavid du Colombier static	Iobuf*	xtag(Off, int, Off);
57*01a344a2SDavid du Colombier 
58*01a344a2SDavid du Colombier static void *
chkalloc(ulong n)59*01a344a2SDavid du Colombier chkalloc(ulong n)
60*01a344a2SDavid du Colombier {
61*01a344a2SDavid du Colombier 	char *p = mallocz(n, 1);
62*01a344a2SDavid du Colombier 
63*01a344a2SDavid du Colombier 	if (p == nil)
64*01a344a2SDavid du Colombier 		panic("chkalloc: out of memory");
65*01a344a2SDavid du Colombier 	return p;
66*01a344a2SDavid du Colombier }
67*01a344a2SDavid du Colombier 
68*01a344a2SDavid du Colombier void
chkfree(void * p)69*01a344a2SDavid du Colombier chkfree(void *p)
70*01a344a2SDavid du Colombier {
71*01a344a2SDavid du Colombier 	free(p);
72*01a344a2SDavid du Colombier }
73*01a344a2SDavid du Colombier 
74*01a344a2SDavid du Colombier /*
75*01a344a2SDavid du Colombier  * check flags
76*01a344a2SDavid du Colombier  */
77*01a344a2SDavid du Colombier enum
78*01a344a2SDavid du Colombier {
79*01a344a2SDavid du Colombier 	Crdall	= (1<<0),	/* read all files */
80*01a344a2SDavid du Colombier 	Ctag	= (1<<1),	/* rebuild tags */
81*01a344a2SDavid du Colombier 	Cpfile	= (1<<2),	/* print files */
82*01a344a2SDavid du Colombier 	Cpdir	= (1<<3),	/* print directories */
83*01a344a2SDavid du Colombier 	Cfree	= (1<<4),	/* rebuild free list */
84*01a344a2SDavid du Colombier //	Csetqid	= (1<<5),	/* resequence qids */
85*01a344a2SDavid du Colombier 	Cream	= (1<<6),	/* clear all bad tags */
86*01a344a2SDavid du Colombier 	Cbad	= (1<<7),	/* clear all bad blocks */
87*01a344a2SDavid du Colombier 	Ctouch	= (1<<8),	/* touch old dir and indir */
88*01a344a2SDavid du Colombier 	Ctrim	= (1<<9),   /* trim fsize back to fit when checking free list */
89*01a344a2SDavid du Colombier };
90*01a344a2SDavid du Colombier 
91*01a344a2SDavid du Colombier static struct {
92*01a344a2SDavid du Colombier 	char*	option;
93*01a344a2SDavid du Colombier 	long	flag;
94*01a344a2SDavid du Colombier } ckoption[] = {
95*01a344a2SDavid du Colombier 	"rdall",	Crdall,
96*01a344a2SDavid du Colombier 	"tag",		Ctag,
97*01a344a2SDavid du Colombier 	"pfile",	Cpfile,
98*01a344a2SDavid du Colombier 	"pdir",		Cpdir,
99*01a344a2SDavid du Colombier 	"free",		Cfree,
100*01a344a2SDavid du Colombier //	"setqid",	Csetqid,
101*01a344a2SDavid du Colombier 	"ream",		Cream,
102*01a344a2SDavid du Colombier 	"bad",		Cbad,
103*01a344a2SDavid du Colombier 	"touch",	Ctouch,
104*01a344a2SDavid du Colombier 	"trim",		Ctrim,
105*01a344a2SDavid du Colombier 	0,
106*01a344a2SDavid du Colombier };
107*01a344a2SDavid du Colombier 
108*01a344a2SDavid du Colombier void
cmd_check(int argc,char * argv[])109*01a344a2SDavid du Colombier cmd_check(int argc, char *argv[])
110*01a344a2SDavid du Colombier {
111*01a344a2SDavid du Colombier 	long f, i, flag;
112*01a344a2SDavid du Colombier 	Off raddr;
113*01a344a2SDavid du Colombier 	Filsys *fs;
114*01a344a2SDavid du Colombier 	Iobuf *p;
115*01a344a2SDavid du Colombier 	Superb *sb;
116*01a344a2SDavid du Colombier 	Dentry *d;
117*01a344a2SDavid du Colombier 
118*01a344a2SDavid du Colombier 	flag = 0;
119*01a344a2SDavid du Colombier 	for(i=1; i<argc; i++) {
120*01a344a2SDavid du Colombier 		for(f=0; ckoption[f].option; f++)
121*01a344a2SDavid du Colombier 			if(strcmp(argv[i], ckoption[f].option) == 0)
122*01a344a2SDavid du Colombier 				goto found;
123*01a344a2SDavid du Colombier 		print("unknown check option %s\n", argv[i]);
124*01a344a2SDavid du Colombier 		for(f=0; ckoption[f].option; f++)
125*01a344a2SDavid du Colombier 			print("\t%s\n", ckoption[f].option);
126*01a344a2SDavid du Colombier 		return;
127*01a344a2SDavid du Colombier 	found:
128*01a344a2SDavid du Colombier 		flag |= ckoption[f].flag;
129*01a344a2SDavid du Colombier 	}
130*01a344a2SDavid du Colombier 	fs = cons.curfs;
131*01a344a2SDavid du Colombier 
132*01a344a2SDavid du Colombier 	dev = fs->dev;
133*01a344a2SDavid du Colombier 	ronly = (dev->type == Devro);
134*01a344a2SDavid du Colombier 	cwflag = (dev->type == Devcw) | (dev->type == Devro);
135*01a344a2SDavid du Colombier 	if(!ronly)
136*01a344a2SDavid du Colombier 		wlock(&mainlock);		/* check */
137*01a344a2SDavid du Colombier 	flags = flag;
138*01a344a2SDavid du Colombier 
139*01a344a2SDavid du Colombier 	name = abits = qbits = nil;		/* in case of goto */
140*01a344a2SDavid du Colombier 	sbaddr = superaddr(dev);
141*01a344a2SDavid du Colombier 	raddr = getraddr(dev);
142*01a344a2SDavid du Colombier 	p = xtag(sbaddr, Tsuper, QPSUPER);
143*01a344a2SDavid du Colombier 	if(!p)
144*01a344a2SDavid du Colombier 		goto out;
145*01a344a2SDavid du Colombier 	sb = (Superb*)p->iobuf;
146*01a344a2SDavid du Colombier 	fstart = 2;
147*01a344a2SDavid du Colombier 	cons.noage = 1;
148*01a344a2SDavid du Colombier 
149*01a344a2SDavid du Colombier 	/* 200 is slop since qidgen is likely to be a little bit low */
150*01a344a2SDavid du Colombier 	sizqbits = (sb->qidgen+200 + 7) / 8;
151*01a344a2SDavid du Colombier 	qbits = chkalloc(sizqbits);
152*01a344a2SDavid du Colombier 
153*01a344a2SDavid du Colombier 	fsize = sb->fsize;
154*01a344a2SDavid du Colombier 	sizabits = (fsize-fstart + 7)/8;
155*01a344a2SDavid du Colombier 	abits = chkalloc(sizabits);
156*01a344a2SDavid du Colombier 
157*01a344a2SDavid du Colombier 	sizname = 4000;
158*01a344a2SDavid du Colombier 	name = chkalloc(sizname);
159*01a344a2SDavid du Colombier 	sizname -= NAMELEN+10;	/* for safety */
160*01a344a2SDavid du Colombier 
161*01a344a2SDavid du Colombier 	mod = 0;
162*01a344a2SDavid du Colombier 	nfree = 0;
163*01a344a2SDavid du Colombier 	nfdup = 0;
164*01a344a2SDavid du Colombier 	nused = 0;
165*01a344a2SDavid du Colombier 	nbad = 0;
166*01a344a2SDavid du Colombier 	ndup = 0;
167*01a344a2SDavid du Colombier 	nqbad = 0;
168*01a344a2SDavid du Colombier 	depth = 0;
169*01a344a2SDavid du Colombier 	maxdepth = 0;
170*01a344a2SDavid du Colombier 
171*01a344a2SDavid du Colombier 	if(flags & Ctouch) {
172*01a344a2SDavid du Colombier 		/* round fsize down to start of current side */
173*01a344a2SDavid du Colombier 		int s;
174*01a344a2SDavid du Colombier 		Devsize dsize;
175*01a344a2SDavid du Colombier 
176*01a344a2SDavid du Colombier 		oldblock = 0;
177*01a344a2SDavid du Colombier 		for (s = 0; dsize = wormsizeside(dev, s),
178*01a344a2SDavid du Colombier 		     dsize > 0 && oldblock + dsize < fsize; s++)
179*01a344a2SDavid du Colombier 			oldblock += dsize;
180*01a344a2SDavid du Colombier 		print("oldblock = %lld\n", (Wideoff)oldblock);
181*01a344a2SDavid du Colombier 	}
182*01a344a2SDavid du Colombier 	amark(sbaddr);
183*01a344a2SDavid du Colombier 	if(cwflag) {
184*01a344a2SDavid du Colombier 		amark(sb->roraddr);
185*01a344a2SDavid du Colombier 		amark(sb->next);
186*01a344a2SDavid du Colombier 	}
187*01a344a2SDavid du Colombier 
188*01a344a2SDavid du Colombier 	print("checking filsys: %s\n", fs->name);
189*01a344a2SDavid du Colombier 	nfiles = 0;
190*01a344a2SDavid du Colombier 	maxq = 0;
191*01a344a2SDavid du Colombier 
192*01a344a2SDavid du Colombier 	d = maked(raddr, 0, QPROOT);
193*01a344a2SDavid du Colombier 	if(d) {
194*01a344a2SDavid du Colombier 		amark(raddr);
195*01a344a2SDavid du Colombier 		if(fsck(d))
196*01a344a2SDavid du Colombier 			modd(raddr, 0, d);
197*01a344a2SDavid du Colombier 		chkfree(d);
198*01a344a2SDavid du Colombier 		depth--;
199*01a344a2SDavid du Colombier 		if(depth)
200*01a344a2SDavid du Colombier 			print("depth not zero on return\n");
201*01a344a2SDavid du Colombier 	}
202*01a344a2SDavid du Colombier 
203*01a344a2SDavid du Colombier 	if(flags & Cfree)
204*01a344a2SDavid du Colombier 		if(cwflag)
205*01a344a2SDavid du Colombier 			trfreelist(sb);
206*01a344a2SDavid du Colombier 		else
207*01a344a2SDavid du Colombier 			mkfreelist(sb);
208*01a344a2SDavid du Colombier 
209*01a344a2SDavid du Colombier 	if(sb->qidgen < maxq)
210*01a344a2SDavid du Colombier 		print("qid generator low path=%lld maxq=%lld\n",
211*01a344a2SDavid du Colombier 			(Wideoff)sb->qidgen, (Wideoff)maxq);
212*01a344a2SDavid du Colombier 	if(!(flags & Cfree))
213*01a344a2SDavid du Colombier 		ckfreelist(sb);
214*01a344a2SDavid du Colombier 	if(mod) {
215*01a344a2SDavid du Colombier 		sb->qidgen = maxq;
216*01a344a2SDavid du Colombier 		print("file system was modified\n");
217*01a344a2SDavid du Colombier 		settag(p, Tsuper, QPNONE);
218*01a344a2SDavid du Colombier 	}
219*01a344a2SDavid du Colombier 
220*01a344a2SDavid du Colombier 	print("nfiles = %lld\n", (Wideoff)nfiles);
221*01a344a2SDavid du Colombier 	print("fsize  = %lld\n", (Wideoff)fsize);
222*01a344a2SDavid du Colombier 	print("nused  = %lld\n", (Wideoff)nused);
223*01a344a2SDavid du Colombier 	print("ndup   = %lld\n", (Wideoff)ndup);
224*01a344a2SDavid du Colombier 	print("nfree  = %lld\n", (Wideoff)nfree);
225*01a344a2SDavid du Colombier 	print("tfree  = %lld\n", (Wideoff)sb->tfree);
226*01a344a2SDavid du Colombier 	print("nfdup  = %lld\n", (Wideoff)nfdup);
227*01a344a2SDavid du Colombier 	print("nmiss  = %lld\n", (Wideoff)fsize-fstart-nused-nfree);
228*01a344a2SDavid du Colombier 	print("nbad   = %lld\n", (Wideoff)nbad);
229*01a344a2SDavid du Colombier 	print("nqbad  = %lld\n", (Wideoff)nqbad);
230*01a344a2SDavid du Colombier 	print("maxq   = %lld\n", (Wideoff)maxq);
231*01a344a2SDavid du Colombier 	print("base stack=%llud\n", (vlong)startstack);
232*01a344a2SDavid du Colombier 	/* high-water mark of stack usage */
233*01a344a2SDavid du Colombier 	print("high stack=%llud\n", (vlong)lowstack);
234*01a344a2SDavid du Colombier 	print("deepest recursion=%d\n", maxdepth-1);	/* one-origin */
235*01a344a2SDavid du Colombier 	if(!cwflag)
236*01a344a2SDavid du Colombier 		missing();
237*01a344a2SDavid du Colombier 
238*01a344a2SDavid du Colombier out:
239*01a344a2SDavid du Colombier 	cons.noage = 0;
240*01a344a2SDavid du Colombier 	putbuf(p);
241*01a344a2SDavid du Colombier 	chkfree(name);
242*01a344a2SDavid du Colombier 	chkfree(abits);
243*01a344a2SDavid du Colombier 	chkfree(qbits);
244*01a344a2SDavid du Colombier 	name = abits = qbits = nil;
245*01a344a2SDavid du Colombier 	if(!ronly)
246*01a344a2SDavid du Colombier 		wunlock(&mainlock);
247*01a344a2SDavid du Colombier }
248*01a344a2SDavid du Colombier 
249*01a344a2SDavid du Colombier /*
250*01a344a2SDavid du Colombier  * if *blkp is already allocated and Cbad is set, zero it.
251*01a344a2SDavid du Colombier  * returns *blkp if it's free, else 0.
252*01a344a2SDavid du Colombier  */
253*01a344a2SDavid du Colombier static Off
blkck(Off * blkp,int * flgp)254*01a344a2SDavid du Colombier blkck(Off *blkp, int *flgp)
255*01a344a2SDavid du Colombier {
256*01a344a2SDavid du Colombier 	Off a = *blkp;
257*01a344a2SDavid du Colombier 
258*01a344a2SDavid du Colombier 	if(amark(a)) {
259*01a344a2SDavid du Colombier 		if(flags & Cbad) {
260*01a344a2SDavid du Colombier 			*blkp = 0;
261*01a344a2SDavid du Colombier 			*flgp |= Bmod;
262*01a344a2SDavid du Colombier 		}
263*01a344a2SDavid du Colombier 		a = 0;
264*01a344a2SDavid du Colombier 	}
265*01a344a2SDavid du Colombier 	return a;
266*01a344a2SDavid du Colombier }
267*01a344a2SDavid du Colombier 
268*01a344a2SDavid du Colombier /*
269*01a344a2SDavid du Colombier  * if a block address within a Dentry, *blkp, is already allocated
270*01a344a2SDavid du Colombier  * and Cbad is set, zero it.
271*01a344a2SDavid du Colombier  * stores 0 into *resp if already allocated, else stores *blkp.
272*01a344a2SDavid du Colombier  * returns dmod count.
273*01a344a2SDavid du Colombier  */
274*01a344a2SDavid du Colombier static int
daddrck(Off * blkp,Off * resp)275*01a344a2SDavid du Colombier daddrck(Off *blkp, Off *resp)
276*01a344a2SDavid du Colombier {
277*01a344a2SDavid du Colombier 	int dmod = 0;
278*01a344a2SDavid du Colombier 
279*01a344a2SDavid du Colombier 	if(amark(*blkp)) {
280*01a344a2SDavid du Colombier 		if(flags & Cbad) {
281*01a344a2SDavid du Colombier 			*blkp = 0;
282*01a344a2SDavid du Colombier 			dmod++;
283*01a344a2SDavid du Colombier 		}
284*01a344a2SDavid du Colombier 		*resp = 0;
285*01a344a2SDavid du Colombier 	} else
286*01a344a2SDavid du Colombier 		*resp = *blkp;
287*01a344a2SDavid du Colombier 	return dmod;
288*01a344a2SDavid du Colombier }
289*01a344a2SDavid du Colombier 
290*01a344a2SDavid du Colombier /*
291*01a344a2SDavid du Colombier  * under Ctouch, read block `a' if it's in range.
292*01a344a2SDavid du Colombier  * returns dmod count.
293*01a344a2SDavid du Colombier  */
294*01a344a2SDavid du Colombier static int
touch(Off a)295*01a344a2SDavid du Colombier touch(Off a)
296*01a344a2SDavid du Colombier {
297*01a344a2SDavid du Colombier 	if((flags&Ctouch) && a < oldblock) {
298*01a344a2SDavid du Colombier 		Iobuf *pd = getbuf(dev, a, Brd|Bmod);
299*01a344a2SDavid du Colombier 
300*01a344a2SDavid du Colombier 		if(pd)
301*01a344a2SDavid du Colombier 			putbuf(pd);
302*01a344a2SDavid du Colombier 		return 1;
303*01a344a2SDavid du Colombier 	}
304*01a344a2SDavid du Colombier 	return 0;
305*01a344a2SDavid du Colombier }
306*01a344a2SDavid du Colombier 
307*01a344a2SDavid du Colombier /*
308*01a344a2SDavid du Colombier  * if d is a directory, touch it and check all its entries in block a.
309*01a344a2SDavid du Colombier  * if not, under Crdall, read a.
310*01a344a2SDavid du Colombier  * returns dmod count.
311*01a344a2SDavid du Colombier  */
312*01a344a2SDavid du Colombier static int
dirck(Extdentry * ed,Off a)313*01a344a2SDavid du Colombier dirck(Extdentry *ed, Off a)
314*01a344a2SDavid du Colombier {
315*01a344a2SDavid du Colombier 	int k, dmod = 0;
316*01a344a2SDavid du Colombier 
317*01a344a2SDavid du Colombier 	if(ed->d->mode & DDIR) {
318*01a344a2SDavid du Colombier 		dmod += touch(a);
319*01a344a2SDavid du Colombier 		for(k=0; k<DIRPERBUF; k++) {
320*01a344a2SDavid du Colombier 			Dentry *nd = maked(a, k, ed->qpath);
321*01a344a2SDavid du Colombier 
322*01a344a2SDavid du Colombier 			if(nd == nil)
323*01a344a2SDavid du Colombier 				break;
324*01a344a2SDavid du Colombier 			if(fsck(nd)) {
325*01a344a2SDavid du Colombier 				modd(a, k, nd);
326*01a344a2SDavid du Colombier 				dmod++;
327*01a344a2SDavid du Colombier 			}
328*01a344a2SDavid du Colombier 			chkfree(nd);
329*01a344a2SDavid du Colombier 			depth--;
330*01a344a2SDavid du Colombier 			name[ed->ns] = 0;
331*01a344a2SDavid du Colombier 		}
332*01a344a2SDavid du Colombier 	} else if(flags & Crdall)
333*01a344a2SDavid du Colombier 		xread(a, ed->qpath);
334*01a344a2SDavid du Colombier 	return dmod;
335*01a344a2SDavid du Colombier }
336*01a344a2SDavid du Colombier 
337*01a344a2SDavid du Colombier /*
338*01a344a2SDavid du Colombier  * touch a, check a's tag for Tind1, Tind2, etc.
339*01a344a2SDavid du Colombier  * if the tag is right, validate each block number in the indirect block,
340*01a344a2SDavid du Colombier  * and check each block (mostly in case we are reading a huge directory).
341*01a344a2SDavid du Colombier  */
342*01a344a2SDavid du Colombier static int
indirck(Extdentry * ed,Off a,int tag)343*01a344a2SDavid du Colombier indirck(Extdentry *ed, Off a, int tag)
344*01a344a2SDavid du Colombier {
345*01a344a2SDavid du Colombier 	int i, dmod = 0;
346*01a344a2SDavid du Colombier 	Iobuf *p1;
347*01a344a2SDavid du Colombier 
348*01a344a2SDavid du Colombier 	if (a == 0)
349*01a344a2SDavid du Colombier 		return dmod;
350*01a344a2SDavid du Colombier 	dmod = touch(a);
351*01a344a2SDavid du Colombier 	if (p1 = xtag(a, tag, ed->qpath)) {
352*01a344a2SDavid du Colombier 		for(i=0; i<INDPERBUF; i++) {
353*01a344a2SDavid du Colombier 			a = blkck(&((Off *)p1->iobuf)[i], &p1->flags);
354*01a344a2SDavid du Colombier 			if (a)
355*01a344a2SDavid du Colombier 				/*
356*01a344a2SDavid du Colombier 				 * check each block named in this
357*01a344a2SDavid du Colombier 				 * indirect(^n) block (a).
358*01a344a2SDavid du Colombier 				 */
359*01a344a2SDavid du Colombier 				if (tag == Tind1)
360*01a344a2SDavid du Colombier 					dmod +=   dirck(ed, a);
361*01a344a2SDavid du Colombier 				else
362*01a344a2SDavid du Colombier 					dmod += indirck(ed, a, tag-1);
363*01a344a2SDavid du Colombier 		}
364*01a344a2SDavid du Colombier 		putbuf(p1);
365*01a344a2SDavid du Colombier 	}
366*01a344a2SDavid du Colombier 	return dmod;
367*01a344a2SDavid du Colombier }
368*01a344a2SDavid du Colombier 
369*01a344a2SDavid du Colombier static int
indiraddrck(Extdentry * ed,Off * indirp,int tag)370*01a344a2SDavid du Colombier indiraddrck(Extdentry *ed, Off *indirp, int tag)
371*01a344a2SDavid du Colombier {
372*01a344a2SDavid du Colombier 	int dmod;
373*01a344a2SDavid du Colombier 	Off a;
374*01a344a2SDavid du Colombier 
375*01a344a2SDavid du Colombier 	dmod = daddrck(indirp, &a);
376*01a344a2SDavid du Colombier 	return dmod + indirck(ed, a, tag);
377*01a344a2SDavid du Colombier }
378*01a344a2SDavid du Colombier 
379*01a344a2SDavid du Colombier /* if result is true, *d was modified */
380*01a344a2SDavid du Colombier static int
fsck(Dentry * d)381*01a344a2SDavid du Colombier fsck(Dentry *d)
382*01a344a2SDavid du Colombier {
383*01a344a2SDavid du Colombier 	int i, dmod;
384*01a344a2SDavid du Colombier 	Extdentry edent;
385*01a344a2SDavid du Colombier 
386*01a344a2SDavid du Colombier 	depth++;
387*01a344a2SDavid du Colombier 	if(depth >= maxdepth)
388*01a344a2SDavid du Colombier 		maxdepth = depth;
389*01a344a2SDavid du Colombier 	if (lowstack == nil)
390*01a344a2SDavid du Colombier 		startstack = lowstack = (uchar *)&edent;
391*01a344a2SDavid du Colombier 	/* more precise check, assumes downward-growing stack */
392*01a344a2SDavid du Colombier 	if ((uchar *)&edent < lowstack)
393*01a344a2SDavid du Colombier 		lowstack = (uchar *)&edent;
394*01a344a2SDavid du Colombier 
395*01a344a2SDavid du Colombier 	/* check that entry is allocated */
396*01a344a2SDavid du Colombier 	if(!(d->mode & DALLOC))
397*01a344a2SDavid du Colombier 		return 0;
398*01a344a2SDavid du Colombier 	nfiles++;
399*01a344a2SDavid du Colombier 
400*01a344a2SDavid du Colombier 	/* we stash qpath & ns in an Extdentry for eventual use by dirck() */
401*01a344a2SDavid du Colombier 	memset(&edent, 0, sizeof edent);
402*01a344a2SDavid du Colombier 	edent.d = d;
403*01a344a2SDavid du Colombier 
404*01a344a2SDavid du Colombier 	/* check name */
405*01a344a2SDavid du Colombier 	edent.ns = strlen(name);
406*01a344a2SDavid du Colombier 	i = strlen(d->name);
407*01a344a2SDavid du Colombier 	if(i >= NAMELEN) {
408*01a344a2SDavid du Colombier 		d->name[NAMELEN-1] = 0;
409*01a344a2SDavid du Colombier 		print("%s->name (%s) not terminated\n", name, d->name);
410*01a344a2SDavid du Colombier 		return 0;
411*01a344a2SDavid du Colombier 	}
412*01a344a2SDavid du Colombier 	edent.ns += i;
413*01a344a2SDavid du Colombier 	if(edent.ns >= sizname) {
414*01a344a2SDavid du Colombier 		print("%s->name (%s) name too large\n", name, d->name);
415*01a344a2SDavid du Colombier 		return 0;
416*01a344a2SDavid du Colombier 	}
417*01a344a2SDavid du Colombier 	strcat(name, d->name);
418*01a344a2SDavid du Colombier 
419*01a344a2SDavid du Colombier 	if(d->mode & DDIR) {
420*01a344a2SDavid du Colombier 		if(edent.ns > 1) {
421*01a344a2SDavid du Colombier 			strcat(name, "/");
422*01a344a2SDavid du Colombier 			edent.ns++;
423*01a344a2SDavid du Colombier 		}
424*01a344a2SDavid du Colombier 		if(flags & Cpdir) {
425*01a344a2SDavid du Colombier 			print("%s\n", name);
426*01a344a2SDavid du Colombier 			prflush();
427*01a344a2SDavid du Colombier 		}
428*01a344a2SDavid du Colombier 	} else if(flags & Cpfile) {
429*01a344a2SDavid du Colombier 		print("%s\n", name);
430*01a344a2SDavid du Colombier 		prflush();
431*01a344a2SDavid du Colombier 	}
432*01a344a2SDavid du Colombier 
433*01a344a2SDavid du Colombier 	/* check qid */
434*01a344a2SDavid du Colombier 	edent.qpath = d->qid.path & ~QPDIR;
435*01a344a2SDavid du Colombier 	qmark(edent.qpath);
436*01a344a2SDavid du Colombier 	if(edent.qpath > maxq)
437*01a344a2SDavid du Colombier 		maxq = edent.qpath;
438*01a344a2SDavid du Colombier 
439*01a344a2SDavid du Colombier 	/* check direct blocks (the common case) */
440*01a344a2SDavid du Colombier 	dmod = 0;
441*01a344a2SDavid du Colombier 	{
442*01a344a2SDavid du Colombier 		Off a;
443*01a344a2SDavid du Colombier 
444*01a344a2SDavid du Colombier 		for(i=0; i<NDBLOCK; i++) {
445*01a344a2SDavid du Colombier 			dmod += daddrck(&d->dblock[i], &a);
446*01a344a2SDavid du Colombier 			if (a)
447*01a344a2SDavid du Colombier 				dmod += dirck(&edent, a);
448*01a344a2SDavid du Colombier 		}
449*01a344a2SDavid du Colombier 	}
450*01a344a2SDavid du Colombier 	/* check indirect^n blocks, if any */
451*01a344a2SDavid du Colombier 	for (i = 0; i < NIBLOCK; i++)
452*01a344a2SDavid du Colombier 		dmod += indiraddrck(&edent, &d->iblocks[i], Tind1+i);
453*01a344a2SDavid du Colombier 	return dmod;
454*01a344a2SDavid du Colombier }
455*01a344a2SDavid du Colombier 
456*01a344a2SDavid du Colombier enum { XFEN = FEPERBUF + 6 };
457*01a344a2SDavid du Colombier 
458*01a344a2SDavid du Colombier typedef struct {
459*01a344a2SDavid du Colombier 	int	flag;
460*01a344a2SDavid du Colombier 	int	count;
461*01a344a2SDavid du Colombier 	int	next;
462*01a344a2SDavid du Colombier 	Off	addr[XFEN];
463*01a344a2SDavid du Colombier } Xfree;
464*01a344a2SDavid du Colombier 
465*01a344a2SDavid du Colombier static void
xaddfree(Device * dev,Off a,Superb * sb,Iobuf * p)466*01a344a2SDavid du Colombier xaddfree(Device *dev, Off a, Superb *sb, Iobuf *p)
467*01a344a2SDavid du Colombier {
468*01a344a2SDavid du Colombier 	Xfree *x;
469*01a344a2SDavid du Colombier 
470*01a344a2SDavid du Colombier 	x = (Xfree*)p->iobuf;
471*01a344a2SDavid du Colombier 	if(x->count < XFEN) {
472*01a344a2SDavid du Colombier 		x->addr[x->count] = a;
473*01a344a2SDavid du Colombier 		x->count++;
474*01a344a2SDavid du Colombier 		return;
475*01a344a2SDavid du Colombier 	}
476*01a344a2SDavid du Colombier 	if(!x->flag) {
477*01a344a2SDavid du Colombier 		memset(&sb->fbuf, 0, sizeof(sb->fbuf));
478*01a344a2SDavid du Colombier 		sb->fbuf.free[0] = 0L;
479*01a344a2SDavid du Colombier 		sb->fbuf.nfree = 1;
480*01a344a2SDavid du Colombier 		sb->tfree = 0;
481*01a344a2SDavid du Colombier 		x->flag = 1;
482*01a344a2SDavid du Colombier 	}
483*01a344a2SDavid du Colombier 	addfree(dev, a, sb);
484*01a344a2SDavid du Colombier }
485*01a344a2SDavid du Colombier 
486*01a344a2SDavid du Colombier static void
xflush(Device * dev,Superb * sb,Iobuf * p)487*01a344a2SDavid du Colombier xflush(Device *dev, Superb *sb, Iobuf *p)
488*01a344a2SDavid du Colombier {
489*01a344a2SDavid du Colombier 	int i;
490*01a344a2SDavid du Colombier 	Xfree *x;
491*01a344a2SDavid du Colombier 
492*01a344a2SDavid du Colombier 	x = (Xfree*)p->iobuf;
493*01a344a2SDavid du Colombier 	if(!x->flag) {
494*01a344a2SDavid du Colombier 		memset(&sb->fbuf, 0, sizeof(sb->fbuf));
495*01a344a2SDavid du Colombier 		sb->fbuf.free[0] = 0L;
496*01a344a2SDavid du Colombier 		sb->fbuf.nfree = 1;
497*01a344a2SDavid du Colombier 		sb->tfree = 0;
498*01a344a2SDavid du Colombier 	}
499*01a344a2SDavid du Colombier 	for(i=0; i<x->count; i++)
500*01a344a2SDavid du Colombier 		addfree(dev, x->addr[i], sb);
501*01a344a2SDavid du Colombier }
502*01a344a2SDavid du Colombier 
503*01a344a2SDavid du Colombier /*
504*01a344a2SDavid du Colombier  * make freelist
505*01a344a2SDavid du Colombier  * from existing freelist
506*01a344a2SDavid du Colombier  * (cw devices)
507*01a344a2SDavid du Colombier  */
508*01a344a2SDavid du Colombier static void
trfreelist(Superb * sb)509*01a344a2SDavid du Colombier trfreelist(Superb *sb)
510*01a344a2SDavid du Colombier {
511*01a344a2SDavid du Colombier 	Off a, n;
512*01a344a2SDavid du Colombier 	int i;
513*01a344a2SDavid du Colombier 	Iobuf *p, *xp;
514*01a344a2SDavid du Colombier 	Fbuf *fb;
515*01a344a2SDavid du Colombier 
516*01a344a2SDavid du Colombier 
517*01a344a2SDavid du Colombier 	xp = getbuf(devnone, Cckbuf, 0);
518*01a344a2SDavid du Colombier 	memset(xp->iobuf, 0, BUFSIZE);
519*01a344a2SDavid du Colombier 	fb = &sb->fbuf;
520*01a344a2SDavid du Colombier 	p = 0;
521*01a344a2SDavid du Colombier 	for(;;) {
522*01a344a2SDavid du Colombier 		n = fb->nfree;
523*01a344a2SDavid du Colombier 		if(n < 0 || n > FEPERBUF)
524*01a344a2SDavid du Colombier 			break;
525*01a344a2SDavid du Colombier 		for(i=1; i<n; i++) {
526*01a344a2SDavid du Colombier 			a = fb->free[i];
527*01a344a2SDavid du Colombier 			if(a && !ftest(a))
528*01a344a2SDavid du Colombier 				xaddfree(dev, a, sb, xp);
529*01a344a2SDavid du Colombier 		}
530*01a344a2SDavid du Colombier 		a = fb->free[0];
531*01a344a2SDavid du Colombier 		if(!a)
532*01a344a2SDavid du Colombier 			break;
533*01a344a2SDavid du Colombier 		if(ftest(a))
534*01a344a2SDavid du Colombier 			break;
535*01a344a2SDavid du Colombier 		xaddfree(dev, a, sb, xp);
536*01a344a2SDavid du Colombier 		if(p)
537*01a344a2SDavid du Colombier 			putbuf(p);
538*01a344a2SDavid du Colombier 		p = xtag(a, Tfree, QPNONE);
539*01a344a2SDavid du Colombier 		if(!p)
540*01a344a2SDavid du Colombier 			break;
541*01a344a2SDavid du Colombier 		fb = (Fbuf*)p->iobuf;
542*01a344a2SDavid du Colombier 	}
543*01a344a2SDavid du Colombier 	if(p)
544*01a344a2SDavid du Colombier 		putbuf(p);
545*01a344a2SDavid du Colombier 	xflush(dev, sb, xp);
546*01a344a2SDavid du Colombier 	putbuf(xp);
547*01a344a2SDavid du Colombier 	mod++;
548*01a344a2SDavid du Colombier 	print("%lld blocks free\n", (Wideoff)sb->tfree);
549*01a344a2SDavid du Colombier }
550*01a344a2SDavid du Colombier 
551*01a344a2SDavid du Colombier static void
ckfreelist(Superb * sb)552*01a344a2SDavid du Colombier ckfreelist(Superb *sb)
553*01a344a2SDavid du Colombier {
554*01a344a2SDavid du Colombier 	Off a, lo, hi;
555*01a344a2SDavid du Colombier 	int n, i;
556*01a344a2SDavid du Colombier 	Iobuf *p;
557*01a344a2SDavid du Colombier 	Fbuf *fb;
558*01a344a2SDavid du Colombier 
559*01a344a2SDavid du Colombier 	strcpy(name, "free list");
560*01a344a2SDavid du Colombier 	print("check %s\n", name);
561*01a344a2SDavid du Colombier 	fb = &sb->fbuf;
562*01a344a2SDavid du Colombier 	a = sbaddr;
563*01a344a2SDavid du Colombier 	p = 0;
564*01a344a2SDavid du Colombier 	lo = 0;
565*01a344a2SDavid du Colombier 	hi = 0;
566*01a344a2SDavid du Colombier 	for(;;) {
567*01a344a2SDavid du Colombier 		n = fb->nfree;
568*01a344a2SDavid du Colombier 		if(n < 0 || n > FEPERBUF) {
569*01a344a2SDavid du Colombier 			print("check: nfree bad %lld\n", (Wideoff)a);
570*01a344a2SDavid du Colombier 			break;
571*01a344a2SDavid du Colombier 		}
572*01a344a2SDavid du Colombier 		for(i=1; i<n; i++) {
573*01a344a2SDavid du Colombier 			a = fb->free[i];
574*01a344a2SDavid du Colombier 			if(a && !fmark(a)) {
575*01a344a2SDavid du Colombier 				if(!lo || lo > a)
576*01a344a2SDavid du Colombier 					lo = a;
577*01a344a2SDavid du Colombier 				if(!hi || hi < a)
578*01a344a2SDavid du Colombier 					hi = a;
579*01a344a2SDavid du Colombier 			}
580*01a344a2SDavid du Colombier 		}
581*01a344a2SDavid du Colombier 		a = fb->free[0];
582*01a344a2SDavid du Colombier 		if(!a)
583*01a344a2SDavid du Colombier 			break;
584*01a344a2SDavid du Colombier 		if(fmark(a))
585*01a344a2SDavid du Colombier 			break;
586*01a344a2SDavid du Colombier 		if(!lo || lo > a)
587*01a344a2SDavid du Colombier 			lo = a;
588*01a344a2SDavid du Colombier 		if(!hi || hi < a)
589*01a344a2SDavid du Colombier 			hi = a;
590*01a344a2SDavid du Colombier 		if(p)
591*01a344a2SDavid du Colombier 			putbuf(p);
592*01a344a2SDavid du Colombier 		p = xtag(a, Tfree, QPNONE);
593*01a344a2SDavid du Colombier 		if(!p)
594*01a344a2SDavid du Colombier 			break;
595*01a344a2SDavid du Colombier 		fb = (Fbuf*)p->iobuf;
596*01a344a2SDavid du Colombier 	}
597*01a344a2SDavid du Colombier 	if(p)
598*01a344a2SDavid du Colombier 		putbuf(p);
599*01a344a2SDavid du Colombier 	if (flags & Ctrim) {
600*01a344a2SDavid du Colombier 		fsize = hi--;		/* fsize = hi + 1 */
601*01a344a2SDavid du Colombier 		sb->fsize = fsize;
602*01a344a2SDavid du Colombier 		mod++;
603*01a344a2SDavid du Colombier 		print("set fsize to %lld\n", (Wideoff)fsize);
604*01a344a2SDavid du Colombier 	}
605*01a344a2SDavid du Colombier 	print("lo = %lld; hi = %lld\n", (Wideoff)lo, (Wideoff)hi);
606*01a344a2SDavid du Colombier }
607*01a344a2SDavid du Colombier 
608*01a344a2SDavid du Colombier /*
609*01a344a2SDavid du Colombier  * make freelist from scratch
610*01a344a2SDavid du Colombier  */
611*01a344a2SDavid du Colombier static void
mkfreelist(Superb * sb)612*01a344a2SDavid du Colombier mkfreelist(Superb *sb)
613*01a344a2SDavid du Colombier {
614*01a344a2SDavid du Colombier 	Off a;
615*01a344a2SDavid du Colombier 	int i, b;
616*01a344a2SDavid du Colombier 
617*01a344a2SDavid du Colombier 	if(ronly) {
618*01a344a2SDavid du Colombier 		print("cant make freelist on ronly device\n");
619*01a344a2SDavid du Colombier 		return;
620*01a344a2SDavid du Colombier 	}
621*01a344a2SDavid du Colombier 	strcpy(name, "free list");
622*01a344a2SDavid du Colombier 	memset(&sb->fbuf, 0, sizeof(sb->fbuf));
623*01a344a2SDavid du Colombier 	sb->fbuf.free[0] = 0L;
624*01a344a2SDavid du Colombier 	sb->fbuf.nfree = 1;
625*01a344a2SDavid du Colombier 	sb->tfree = 0;
626*01a344a2SDavid du Colombier 	for(a=fsize-fstart-1; a >= 0; a--) {
627*01a344a2SDavid du Colombier 		i = a/8;
628*01a344a2SDavid du Colombier 		if(i < 0 || i >= sizabits)
629*01a344a2SDavid du Colombier 			continue;
630*01a344a2SDavid du Colombier 		b = 1 << (a&7);
631*01a344a2SDavid du Colombier 		if(abits[i] & b)
632*01a344a2SDavid du Colombier 			continue;
633*01a344a2SDavid du Colombier 		addfree(dev, fstart+a, sb);
634*01a344a2SDavid du Colombier 	}
635*01a344a2SDavid du Colombier 	print("%lld blocks free\n", (Wideoff)sb->tfree);
636*01a344a2SDavid du Colombier 	mod++;
637*01a344a2SDavid du Colombier }
638*01a344a2SDavid du Colombier 
639*01a344a2SDavid du Colombier static Dentry*
maked(Off a,int s,Off qpath)640*01a344a2SDavid du Colombier maked(Off a, int s, Off qpath)
641*01a344a2SDavid du Colombier {
642*01a344a2SDavid du Colombier 	Iobuf *p;
643*01a344a2SDavid du Colombier 	Dentry *d, *d1;
644*01a344a2SDavid du Colombier 
645*01a344a2SDavid du Colombier 	p = xtag(a, Tdir, qpath);
646*01a344a2SDavid du Colombier 	if(!p)
647*01a344a2SDavid du Colombier 		return 0;
648*01a344a2SDavid du Colombier 	d = getdir(p, s);
649*01a344a2SDavid du Colombier 	d1 = chkalloc(sizeof(Dentry));
650*01a344a2SDavid du Colombier 	memmove(d1, d, sizeof(Dentry));
651*01a344a2SDavid du Colombier 	putbuf(p);
652*01a344a2SDavid du Colombier 	return d1;
653*01a344a2SDavid du Colombier }
654*01a344a2SDavid du Colombier 
655*01a344a2SDavid du Colombier static void
modd(Off a,int s,Dentry * d1)656*01a344a2SDavid du Colombier modd(Off a, int s, Dentry *d1)
657*01a344a2SDavid du Colombier {
658*01a344a2SDavid du Colombier 	Iobuf *p;
659*01a344a2SDavid du Colombier 	Dentry *d;
660*01a344a2SDavid du Colombier 
661*01a344a2SDavid du Colombier 	if(!(flags & Cbad))
662*01a344a2SDavid du Colombier 		return;
663*01a344a2SDavid du Colombier 	p = getbuf(dev, a, Brd);
664*01a344a2SDavid du Colombier 	d = getdir(p, s);
665*01a344a2SDavid du Colombier 	if(!d) {
666*01a344a2SDavid du Colombier 		if(p)
667*01a344a2SDavid du Colombier 			putbuf(p);
668*01a344a2SDavid du Colombier 		return;
669*01a344a2SDavid du Colombier 	}
670*01a344a2SDavid du Colombier 	memmove(d, d1, sizeof(Dentry));
671*01a344a2SDavid du Colombier 	p->flags |= Bmod;
672*01a344a2SDavid du Colombier 	putbuf(p);
673*01a344a2SDavid du Colombier }
674*01a344a2SDavid du Colombier 
675*01a344a2SDavid du Colombier static void
xread(Off a,Off qpath)676*01a344a2SDavid du Colombier xread(Off a, Off qpath)
677*01a344a2SDavid du Colombier {
678*01a344a2SDavid du Colombier 	Iobuf *p;
679*01a344a2SDavid du Colombier 
680*01a344a2SDavid du Colombier 	p = xtag(a, Tfile, qpath);
681*01a344a2SDavid du Colombier 	if(p)
682*01a344a2SDavid du Colombier 		putbuf(p);
683*01a344a2SDavid du Colombier }
684*01a344a2SDavid du Colombier 
685*01a344a2SDavid du Colombier static Iobuf*
xtag(Off a,int tag,Off qpath)686*01a344a2SDavid du Colombier xtag(Off a, int tag, Off qpath)
687*01a344a2SDavid du Colombier {
688*01a344a2SDavid du Colombier 	Iobuf *p;
689*01a344a2SDavid du Colombier 
690*01a344a2SDavid du Colombier 	if(a == 0)
691*01a344a2SDavid du Colombier 		return 0;
692*01a344a2SDavid du Colombier 	p = getbuf(dev, a, Brd);
693*01a344a2SDavid du Colombier 	if(!p) {
694*01a344a2SDavid du Colombier 		print("check: \"%s\": xtag: p null\n", name);
695*01a344a2SDavid du Colombier 		if(flags & (Cream|Ctag)) {
696*01a344a2SDavid du Colombier 			p = getbuf(dev, a, Bmod);
697*01a344a2SDavid du Colombier 			if(p) {
698*01a344a2SDavid du Colombier 				memset(p->iobuf, 0, RBUFSIZE);
699*01a344a2SDavid du Colombier 				settag(p, tag, qpath);
700*01a344a2SDavid du Colombier 				mod++;
701*01a344a2SDavid du Colombier 				return p;
702*01a344a2SDavid du Colombier 			}
703*01a344a2SDavid du Colombier 		}
704*01a344a2SDavid du Colombier 		return 0;
705*01a344a2SDavid du Colombier 	}
706*01a344a2SDavid du Colombier 	if(checktag(p, tag, qpath)) {
707*01a344a2SDavid du Colombier 		print("check: \"%s\": xtag: checktag\n", name);
708*01a344a2SDavid du Colombier 		if(flags & (Cream|Ctag)) {
709*01a344a2SDavid du Colombier 			if(flags & Cream)
710*01a344a2SDavid du Colombier 				memset(p->iobuf, 0, RBUFSIZE);
711*01a344a2SDavid du Colombier 			settag(p, tag, qpath);
712*01a344a2SDavid du Colombier 			mod++;
713*01a344a2SDavid du Colombier 			return p;
714*01a344a2SDavid du Colombier 		}
715*01a344a2SDavid du Colombier 		return p;
716*01a344a2SDavid du Colombier 	}
717*01a344a2SDavid du Colombier 	return p;
718*01a344a2SDavid du Colombier }
719*01a344a2SDavid du Colombier 
720*01a344a2SDavid du Colombier static int
amark(Off a)721*01a344a2SDavid du Colombier amark(Off a)
722*01a344a2SDavid du Colombier {
723*01a344a2SDavid du Colombier 	Off i;
724*01a344a2SDavid du Colombier 	int b;
725*01a344a2SDavid du Colombier 
726*01a344a2SDavid du Colombier 	if(a < fstart || a >= fsize) {
727*01a344a2SDavid du Colombier 		if(a == 0)
728*01a344a2SDavid du Colombier 			return 0;
729*01a344a2SDavid du Colombier 		print("check: \"%s\": range %lld\n",
730*01a344a2SDavid du Colombier 			name, (Wideoff)a);
731*01a344a2SDavid du Colombier 		nbad++;
732*01a344a2SDavid du Colombier 		return 1;
733*01a344a2SDavid du Colombier 	}
734*01a344a2SDavid du Colombier 	a -= fstart;
735*01a344a2SDavid du Colombier 	i = a/8;
736*01a344a2SDavid du Colombier 	b = 1 << (a&7);
737*01a344a2SDavid du Colombier 	if(abits[i] & b) {
738*01a344a2SDavid du Colombier 		if(!ronly)
739*01a344a2SDavid du Colombier 			if(ndup < 10)
740*01a344a2SDavid du Colombier 				print("check: \"%s\": address dup %lld\n",
741*01a344a2SDavid du Colombier 					name, (Wideoff)fstart+a);
742*01a344a2SDavid du Colombier 			else if(ndup == 10)
743*01a344a2SDavid du Colombier 				print("...");
744*01a344a2SDavid du Colombier 		ndup++;
745*01a344a2SDavid du Colombier 		return 1;
746*01a344a2SDavid du Colombier 	}
747*01a344a2SDavid du Colombier 	abits[i] |= b;
748*01a344a2SDavid du Colombier 	nused++;
749*01a344a2SDavid du Colombier 	return 0;
750*01a344a2SDavid du Colombier }
751*01a344a2SDavid du Colombier 
752*01a344a2SDavid du Colombier static int
fmark(Off a)753*01a344a2SDavid du Colombier fmark(Off a)
754*01a344a2SDavid du Colombier {
755*01a344a2SDavid du Colombier 	Off i;
756*01a344a2SDavid du Colombier 	int b;
757*01a344a2SDavid du Colombier 
758*01a344a2SDavid du Colombier 	if(a < fstart || a >= fsize) {
759*01a344a2SDavid du Colombier 		print("check: \"%s\": range %lld\n",
760*01a344a2SDavid du Colombier 			name, (Wideoff)a);
761*01a344a2SDavid du Colombier 		nbad++;
762*01a344a2SDavid du Colombier 		return 1;
763*01a344a2SDavid du Colombier 	}
764*01a344a2SDavid du Colombier 	a -= fstart;
765*01a344a2SDavid du Colombier 	i = a/8;
766*01a344a2SDavid du Colombier 	b = 1 << (a&7);
767*01a344a2SDavid du Colombier 	if(abits[i] & b) {
768*01a344a2SDavid du Colombier 		print("check: \"%s\": address dup %lld\n",
769*01a344a2SDavid du Colombier 			name, (Wideoff)fstart+a);
770*01a344a2SDavid du Colombier 		nfdup++;
771*01a344a2SDavid du Colombier 		return 1;
772*01a344a2SDavid du Colombier 	}
773*01a344a2SDavid du Colombier 	abits[i] |= b;
774*01a344a2SDavid du Colombier 	nfree++;
775*01a344a2SDavid du Colombier 	return 0;
776*01a344a2SDavid du Colombier }
777*01a344a2SDavid du Colombier 
778*01a344a2SDavid du Colombier static int
ftest(Off a)779*01a344a2SDavid du Colombier ftest(Off a)
780*01a344a2SDavid du Colombier {
781*01a344a2SDavid du Colombier 	Off i;
782*01a344a2SDavid du Colombier 	int b;
783*01a344a2SDavid du Colombier 
784*01a344a2SDavid du Colombier 	if(a < fstart || a >= fsize)
785*01a344a2SDavid du Colombier 		return 1;
786*01a344a2SDavid du Colombier 	a -= fstart;
787*01a344a2SDavid du Colombier 	i = a/8;
788*01a344a2SDavid du Colombier 	b = 1 << (a&7);
789*01a344a2SDavid du Colombier 	if(abits[i] & b)
790*01a344a2SDavid du Colombier 		return 1;
791*01a344a2SDavid du Colombier 	abits[i] |= b;
792*01a344a2SDavid du Colombier 	return 0;
793*01a344a2SDavid du Colombier }
794*01a344a2SDavid du Colombier 
795*01a344a2SDavid du Colombier static void
missing(void)796*01a344a2SDavid du Colombier missing(void)
797*01a344a2SDavid du Colombier {
798*01a344a2SDavid du Colombier 	Off a, i;
799*01a344a2SDavid du Colombier 	int b, n;
800*01a344a2SDavid du Colombier 
801*01a344a2SDavid du Colombier 	n = 0;
802*01a344a2SDavid du Colombier 	for(a=fsize-fstart-1; a>=0; a--) {
803*01a344a2SDavid du Colombier 		i = a/8;
804*01a344a2SDavid du Colombier 		b = 1 << (a&7);
805*01a344a2SDavid du Colombier 		if(!(abits[i] & b)) {
806*01a344a2SDavid du Colombier 			print("missing: %lld\n", (Wideoff)fstart+a);
807*01a344a2SDavid du Colombier 			n++;
808*01a344a2SDavid du Colombier 		}
809*01a344a2SDavid du Colombier 		if(n > 10) {
810*01a344a2SDavid du Colombier 			print(" ...\n");
811*01a344a2SDavid du Colombier 			break;
812*01a344a2SDavid du Colombier 		}
813*01a344a2SDavid du Colombier 	}
814*01a344a2SDavid du Colombier }
815*01a344a2SDavid du Colombier 
816*01a344a2SDavid du Colombier static void
qmark(Off qpath)817*01a344a2SDavid du Colombier qmark(Off qpath)
818*01a344a2SDavid du Colombier {
819*01a344a2SDavid du Colombier 	int b;
820*01a344a2SDavid du Colombier 	Off i;
821*01a344a2SDavid du Colombier 
822*01a344a2SDavid du Colombier 	i = qpath/8;
823*01a344a2SDavid du Colombier 	b = 1 << (qpath&7);
824*01a344a2SDavid du Colombier 	if(i < 0 || i >= sizqbits) {
825*01a344a2SDavid du Colombier 		nqbad++;
826*01a344a2SDavid du Colombier 		if(nqbad < 20)
827*01a344a2SDavid du Colombier 			print("check: \"%s\": qid out of range %llux\n",
828*01a344a2SDavid du Colombier 				name, (Wideoff)qpath);
829*01a344a2SDavid du Colombier 		return;
830*01a344a2SDavid du Colombier 	}
831*01a344a2SDavid du Colombier 	if((qbits[i] & b) && !ronly) {
832*01a344a2SDavid du Colombier 		nqbad++;
833*01a344a2SDavid du Colombier 		if(nqbad < 20)
834*01a344a2SDavid du Colombier 			print("check: \"%s\": qid dup %llux\n", name,
835*01a344a2SDavid du Colombier 				(Wideoff)qpath);
836*01a344a2SDavid du Colombier 	}
837*01a344a2SDavid du Colombier 	qbits[i] |= b;
838*01a344a2SDavid du Colombier }
839