xref: /original-bsd/sbin/icheck/icheck.c (revision fbed46ce)
1 static	char *sccsid = "@(#)icheck.c	2.2 (Berkeley) 04/11/82";
2 
3 /*
4  * icheck
5  */
6 #define	NB	500
7 #define	MAXFN	500
8 #define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
9 
10 #ifndef STANDALONE
11 #include <stdio.h>
12 #endif
13 #ifndef SIMFS
14 #include <sys/param.h>
15 #include <sys/inode.h>
16 #include <sys/fs.h>
17 #else
18 #include "../h/param.h"
19 #include "../h/inode.h"
20 #include "../h/fs.h"
21 #endif
22 
23 union {
24 	struct	fs sb;
25 	char pad[MAXBSIZE];
26 } sbun;
27 #define	sblock sbun.sb
28 
29 union {
30 	struct	cg cg;
31 	char pad[MAXBSIZE];
32 } cgun;
33 #define	cgrp cgun.cg
34 
35 struct	dinode	itab[MAXIPG];
36 daddr_t	blist[NB];
37 char	*bmap;
38 
39 int	mflg;
40 int	sflg;
41 int	dflg;
42 int	fi;
43 ino_t	ino;
44 int	cginit;
45 
46 ino_t	nrfile;
47 ino_t	ndfile;
48 ino_t	nbfile;
49 ino_t	ncfile;
50 ino_t	nlfile;
51 
52 daddr_t	nblock;
53 daddr_t	nfrag;
54 daddr_t	nindir;
55 daddr_t	niindir;
56 
57 daddr_t	nffree;
58 daddr_t	nbfree;
59 
60 daddr_t	ndup;
61 
62 int	nerror;
63 
64 extern int inside[], around[];
65 extern unsigned char *fragtbl[];
66 
67 long	atol();
68 #ifndef STANDALONE
69 char	*malloc();
70 char	*calloc();
71 #endif
72 
73 main(argc, argv)
74 	int argc;
75 	char *argv[];
76 {
77 	register i;
78 	long n;
79 
80 	blist[0] = -1;
81 #ifndef STANDALONE
82 	while (--argc) {
83 		argv++;
84 		if (**argv=='-')
85 		switch ((*argv)[1]) {
86 		case 'd':
87 			dflg++;
88 			continue;
89 
90 		case 'm':
91 			mflg++;
92 			continue;
93 
94 		case 's':
95 			sflg++;
96 			continue;
97 
98 		case 'b':
99 			for(i=0; i<NB; i++) {
100 				n = atol(argv[1]);
101 				if(n == 0)
102 					break;
103 				blist[i] = n;
104 				argv++;
105 				argc--;
106 			}
107 			blist[i] = -1;
108 			continue;
109 
110 		default:
111 			printf("Bad flag\n");
112 		}
113 		check(*argv);
114 	}
115 #else
116 	{
117 		static char fname[128];
118 
119 		printf("File: ");
120 		gets(fname);
121 		check(fname);
122 	}
123 #endif
124 	return(nerror);
125 }
126 
127 check(file)
128 	char *file;
129 {
130 	register i, j, c;
131 	daddr_t d, cgd, cbase, b;
132 	long n;
133 
134 	fi = open(file, sflg ? 2 : 0);
135 	if (fi < 0) {
136 		perror(file);
137 		nerror |= 04;
138 		return;
139 	}
140 	printf("%s:\n", file);
141 	nrfile = 0;
142 	ndfile = 0;
143 	ncfile = 0;
144 	nbfile = 0;
145 	nlfile = 0;
146 
147 	nblock = 0;
148 	nfrag = 0;
149 	nindir = 0;
150 	niindir = 0;
151 
152 	ndup = 0;
153 #ifndef STANDALONE
154 	sync();
155 #endif
156 	getsb(&sblock, file);
157 	if (nerror)
158 		return;
159 	ino = 0;
160 	n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short));
161 #ifdef STANDALONE
162 	bmap = NULL;
163 #else
164 	bmap = malloc((unsigned)n);
165 #endif
166 	if (bmap==NULL) {
167 		printf("Not enough core; duplicates unchecked\n");
168 		dflg++;
169 		if (sflg) {
170 			printf("No Updates\n");
171 			sflg = 0;
172 		}
173 	}
174 	ino = 0;
175 	cginit = 1;
176 	if (!dflg) {
177 		for (i = 0; i < (unsigned)n; i++)
178 			bmap[i] = 0;
179 		for (c = 0; c < sblock.fs_ncg; c++) {
180 			cgd = cgtod(&sblock, c);
181 			if (c == 0)
182 				d = cgbase(&sblock, c);
183 			else
184 				d = cgsblock(&sblock, c);
185 			for (; d < cgd; d += sblock.fs_frag)
186 				chk(d, "badcg", sblock.fs_bsize);
187 			d = cgimin(&sblock, c);
188 			while (cgd < d) {
189 				chk(cgd, "cg", sblock.fs_bsize);
190 				cgd += sblock.fs_frag;
191 			}
192 			d = cgdmin(&sblock, c);
193 			for (; cgd < d; cgd += sblock.fs_frag)
194 				chk(cgd, "inode", sblock.fs_bsize);
195 			if (c == 0) {
196 				d += howmany(sblock.fs_cssize, sblock.fs_fsize);
197 				for (; cgd < d; cgd++)
198 					chk(cgd, "csum", sblock.fs_fsize);
199 			}
200 		}
201 	}
202 	cginit = 0;
203 	for (c = 0; c < sblock.fs_ncg; c++) {
204 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
205 		    sblock.fs_ipg * sizeof (struct dinode));
206 		for (j=0; j < sblock.fs_ipg; j++) {
207 			pass1(&itab[j]);
208 			ino++;
209 		}
210 	}
211 	ino = 0;
212 #ifndef STANDALONE
213 	sync();
214 #endif
215 	if (sflg) {
216 		makecg();
217 		close(fi);
218 #ifndef STANDALONE
219 		if (bmap)
220 			free(bmap);
221 #endif
222 		return;
223 	}
224 	nffree = 0;
225 	nbfree = 0;
226 	for (c = 0; c < sblock.fs_ncg; c++) {
227 		cbase = cgbase(&sblock, c);
228 		bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp,
229 			sblock.fs_cgsize);
230 		if (cgrp.cg_magic != CG_MAGIC)
231 			printf("cg %d: bad magic number\n", c);
232 		for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
233 			if (isblock(&sblock, cgrp.cg_free,
234 			    b / sblock.fs_frag)) {
235 				nbfree++;
236 				chk(cbase+b, "block", sblock.fs_bsize);
237 			} else {
238 				for (d = 0; d < sblock.fs_frag; d++)
239 					if (isset(cgrp.cg_free, b+d)) {
240 						chk(cbase+b+d, "frag", sblock.fs_fsize);
241 						nffree++;
242 					}
243 			}
244 		}
245 	}
246 	close(fi);
247 #ifndef STANDALONE
248 	if (bmap)
249 		free(bmap);
250 #endif
251 
252 	i = nrfile + ndfile + ncfile + nbfile + nlfile;
253 #ifndef STANDALONE
254 	printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n",
255 		i, nrfile, ndfile, nbfile, ncfile, nlfile);
256 #else
257 	printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n",
258 		i, nrfile, ndfile, nbfile, ncfile, nlfile);
259 #endif
260 	n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag;
261 #ifdef STANDALONE
262 	printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
263 		n, nindir, niindir, nblock, nfrag);
264 	printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree,
265 	    nbfree, nffree);
266 #else
267 	printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
268 		n, nindir, niindir, nblock, nfrag);
269 	printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree,
270 	    nbfree, nffree);
271 #endif
272 	if(!dflg) {
273 		n = 0;
274 		for (d = 0; d < sblock.fs_size; d++)
275 			if(!duped(d, sblock.fs_fsize)) {
276 				if(mflg)
277 					printf("%ld missing\n", d);
278 				n++;
279 			}
280 		printf("missing%5ld\n", n);
281 	}
282 }
283 
284 pass1(ip)
285 	register struct dinode *ip;
286 {
287 	daddr_t ind1[MAXNINDIR];
288 	daddr_t ind2[MAXNINDIR];
289 	daddr_t db, ib;
290 	register int i, j, k, siz;
291 
292 	i = ip->di_mode & IFMT;
293 	if(i == 0)
294 		return;
295 	switch (i) {
296 	case IFCHR:
297 		ncfile++;
298 		return;
299 	case IFBLK:
300 		nbfile++;
301 		return;
302 	case IFDIR:
303 		ndfile++;
304 		break;
305 	case IFREG:
306 		nrfile++;
307 		break;
308 	case IFLNK:
309 		nlfile++;
310 		break;
311 	default:
312 		printf("bad mode %u\n", ino);
313 		return;
314 	}
315 	for (i = 0; i < NDADDR; i++) {
316 		db = ip->di_db[i];
317 		if (db == 0)
318 			continue;
319 		siz = dblksize(&sblock, ip, i);
320 		chk(db, "data (block)", siz);
321 		if (siz == sblock.fs_bsize)
322 			nblock++;
323 		else
324 			nfrag += howmany(siz, sblock.fs_fsize);
325 	}
326 	for(i = 0; i < NIADDR; i++) {
327 		ib = ip->di_ib[i];
328 		if(ib == 0)
329 			continue;
330 		if (chk(ib, "1st indirect", sblock.fs_bsize))
331 			continue;
332 		bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize);
333 		nindir++;
334 		for (j = 0; j < NINDIR(&sblock); j++) {
335 			ib = ind1[j];
336 			if (ib == 0)
337 				continue;
338 			if (i == 0) {
339 				siz = dblksize(&sblock, ip, NDADDR + j);
340 				chk(ib, "data (large)", siz);
341 				if (siz == sblock.fs_bsize)
342 					nblock++;
343 				else
344 					nfrag += howmany(siz, sblock.fs_fsize);
345 				continue;
346 			}
347 			if (chk(ib, "2nd indirect", sblock.fs_bsize))
348 				continue;
349 			bread(fsbtodb(&sblock, ib), (char *)ind2,
350 				sblock.fs_bsize);
351 			niindir++;
352 			for (k = 0; k < NINDIR(&sblock); k++) {
353 				ib = ind2[k];
354 				if (ib == 0)
355 					continue;
356 				siz = dblksize(&sblock, ip,
357 				    NDADDR + NINDIR(&sblock) * (i + j) + k);
358 				chk(ib, "data (huge)", siz);
359 				if (siz == sblock.fs_bsize)
360 					nblock++;
361 				else
362 					nfrag += howmany(siz, sblock.fs_fsize);
363 			}
364 		}
365 	}
366 }
367 
368 chk(bno, s, size)
369 	daddr_t bno;
370 	char *s;
371 	int size;
372 {
373 	register n, cg;
374 	int frags;
375 
376 	cg = dtog(&sblock, bno);
377 	if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) {
378 		printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
379 		return(1);
380 	}
381 	if (size == sblock.fs_bsize) {
382 		if (duped(bno, size)) {
383 			printf("%ld dup block; inode=%u, class=%s\n",
384 			    bno, ino, s);
385 			ndup += sblock.fs_frag;
386 		}
387 	} else {
388 		frags = numfrags(&sblock, size);
389 		for (n = 0; n < frags; n++) {
390 			if (duped(bno + n, sblock.fs_fsize)) {
391 				printf("%ld dup frag; inode=%u, class=%s\n",
392 				    bno, ino, s);
393 				ndup++;
394 			}
395 		}
396 	}
397 	for (n=0; blist[n] != -1; n++)
398 		if (bno == blist[n])
399 			printf("%ld arg; inode=%u, class=%s\n", bno, ino, s);
400 	return(0);
401 }
402 
403 duped(bno, size)
404 	daddr_t bno;
405 	int size;
406 {
407 	if(dflg)
408 		return(0);
409 	if (size != sblock.fs_fsize && size != sblock.fs_bsize)
410 		printf("bad size %d to duped\n", size);
411 	if (size == sblock.fs_fsize) {
412 		if (isset(bmap, bno))
413 			return(1);
414 		setbit(bmap, bno);
415 		return (0);
416 	}
417 	if (bno % sblock.fs_frag != 0)
418 		printf("bad bno %d to duped\n", bno);
419 	if (isblock(&sblock, bmap, bno/sblock.fs_frag))
420 		return (1);
421 	setblock(&sblock, bmap, bno/sblock.fs_frag);
422 	return(0);
423 }
424 
425 makecg()
426 {
427 	int c, blk;
428 	daddr_t dbase, d, dlower, dupper, dmax;
429 	long i, j, s;
430 	register struct csum *cs;
431 	register struct dinode *dp;
432 
433 	sblock.fs_cstotal.cs_nbfree = 0;
434 	sblock.fs_cstotal.cs_nffree = 0;
435 	sblock.fs_cstotal.cs_nifree = 0;
436 	sblock.fs_cstotal.cs_ndir = 0;
437 	for (c = 0; c < sblock.fs_ncg; c++) {
438 		dbase = cgbase(&sblock, c);
439 		dmax = dbase + sblock.fs_fpg;
440 		if (dmax > sblock.fs_size) {
441 			for ( ; dmax >= sblock.fs_size; dmax--)
442 				clrbit(cgrp.cg_free, dmax - dbase);
443 			dmax++;
444 		}
445 		dlower = cgsblock(&sblock, c) - dbase;
446 		dupper = cgdmin(&sblock, c) - dbase;
447 		cs = &sblock.fs_cs(&sblock, c);
448 		cgrp.cg_time = time(0);
449 		cgrp.cg_magic = CG_MAGIC;
450 		cgrp.cg_cgx = c;
451 		cgrp.cg_ncyl = sblock.fs_cpg;
452 		cgrp.cg_niblk = sblock.fs_ipg;
453 		cgrp.cg_ndblk = dmax - dbase;
454 		cgrp.cg_cs.cs_ndir = 0;
455 		cgrp.cg_cs.cs_nffree = 0;
456 		cgrp.cg_cs.cs_nbfree = 0;
457 		cgrp.cg_cs.cs_nifree = 0;
458 		cgrp.cg_rotor = 0;
459 		cgrp.cg_frotor = 0;
460 		cgrp.cg_irotor = 0;
461 		for (i = 0; i < sblock.fs_frag; i++)
462 			cgrp.cg_frsum[i] = 0;
463 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
464 		      sblock.fs_ipg * sizeof(struct dinode));
465 		for (i = 0; i < sblock.fs_ipg; i++) {
466 			cgrp.cg_cs.cs_nifree++;
467 			clrbit(cgrp.cg_iused, i);
468 			dp = &itab[i];
469 			if ((dp->di_mode & IFMT) != 0) {
470 				if ((dp->di_mode & IFMT) == IFDIR)
471 					cgrp.cg_cs.cs_ndir++;
472 				cgrp.cg_cs.cs_nifree--;
473 				setbit(cgrp.cg_iused, i);
474 				continue;
475 			}
476 		}
477 		while (i < MAXIPG) {
478 			clrbit(cgrp.cg_iused, i);
479 			i++;
480 		}
481 		if (c == 0)
482 			for (i = 0; i < ROOTINO; i++) {
483 				setbit(cgrp.cg_iused, i);
484 				cgrp.cg_cs.cs_nifree--;
485 			}
486 		for (s = 0; s < MAXCPG; s++) {
487 			cgrp.cg_btot[s] = 0;
488 			for (i = 0; i < NRPOS; i++)
489 				cgrp.cg_b[s][i] = 0;
490 		}
491 		if (c == 0) {
492 			dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
493 		}
494 		for (d = dlower; d < dupper; d++)
495 			clrbit(cgrp.cg_free, d);
496 		for (d = 0; (d + sblock.fs_frag) <= dmax - dbase;
497 		    d += sblock.fs_frag) {
498 			j = 0;
499 			for (i = 0; i < sblock.fs_frag; i++) {
500 				if (!isset(bmap, dbase + d + i)) {
501 					setbit(cgrp.cg_free, d + i);
502 					j++;
503 				} else
504 					clrbit(cgrp.cg_free, d+i);
505 			}
506 			if (j == sblock.fs_frag) {
507 				cgrp.cg_cs.cs_nbfree++;
508 				cgrp.cg_btot[cbtocylno(&sblock, d)]++;
509 				cgrp.cg_b[cbtocylno(&sblock, d)]
510 				    [cbtorpos(&sblock, d)]++;
511 			} else if (j > 0) {
512 				cgrp.cg_cs.cs_nffree += j;
513 				blk = blkmap(&sblock, cgrp.cg_free, d);
514 				fragacct(&sblock, blk, cgrp.cg_frsum, 1);
515 			}
516 		}
517 		for (j = d; d < dmax - dbase; d++) {
518 			if (!isset(bmap, dbase + d)) {
519 				setbit(cgrp.cg_free, d);
520 				cgrp.cg_cs.cs_nffree++;
521 			} else
522 				clrbit(cgrp.cg_free, d);
523 		}
524 		if (j != d) {
525 			blk = blkmap(&sblock, cgrp.cg_free, j);
526 			fragacct(&sblock, blk, cgrp.cg_frsum, 1);
527 		}
528 		for (; d < MAXBPG(&sblock); d++)
529 			clrbit(cgrp.cg_free, d);
530 		sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
531 		sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
532 		sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
533 		sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
534 		*cs = cgrp.cg_cs;
535 		bwrite(fsbtodb(&sblock, cgtod(&sblock, c)), &cgrp,
536 			sblock.fs_cgsize);
537 	}
538 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
539 		bwrite(fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
540 		    (char *)sblock.fs_csp[j],
541 		    sblock.fs_cssize - i < sblock.fs_bsize ?
542 		    sblock.fs_cssize - i : sblock.fs_bsize);
543 	}
544 	sblock.fs_ronly = 0;
545 	sblock.fs_fmod = 0;
546 	bwrite(SBLOCK, (char *)&sblock, SBSIZE);
547 }
548 
549 /*
550  * update the frsum fields to reflect addition or deletion
551  * of some frags
552  */
553 fragacct(fs, fragmap, fraglist, cnt)
554 	struct fs *fs;
555 	int fragmap;
556 	long fraglist[];
557 	int cnt;
558 {
559 	int inblk;
560 	register int field, subfield;
561 	register int siz, pos;
562 
563 	inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1);
564 	fragmap <<= 1;
565 	for (siz = 1; siz < fs->fs_frag; siz++) {
566 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
567 			continue;
568 		field = around[siz];
569 		subfield = inside[siz];
570 		for (pos = siz; pos <= fs->fs_frag; pos++) {
571 			if ((fragmap & field) == subfield) {
572 				fraglist[siz] += cnt;
573 				pos += siz;
574 				field <<= siz;
575 				subfield <<= siz;
576 			}
577 			field <<= 1;
578 			subfield <<= 1;
579 		}
580 	}
581 }
582 
583 getsb(fs, file)
584 	register struct fs *fs;
585 	char *file;
586 {
587 	int i, j, size;
588 
589 	if (bread(SBLOCK, fs, SBSIZE)) {
590 		printf("bad super block");
591 		perror(file);
592 		nerror |= 04;
593 		return;
594 	}
595 	if (fs->fs_magic != FS_MAGIC) {
596 		printf("%s: bad magic number\n", file);
597 		nerror |= 04;
598 		return;
599 	}
600 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
601 		size = sblock.fs_cssize - i < sblock.fs_bsize ?
602 		    sblock.fs_cssize - i : sblock.fs_bsize;
603 		sblock.fs_csp[j] = (struct csum *)calloc(1, size);
604 		bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)),
605 		      (char *)fs->fs_csp[j], size);
606 	}
607 }
608 
609 bwrite(blk, buf, size)
610 	char *buf;
611 	daddr_t blk;
612 	register size;
613 {
614 	if (lseek(fi, blk * DEV_BSIZE, 0) < 0) {
615 		perror("FS SEEK");
616 		return(1);
617 	}
618 	if (write(fi, buf, size) != size) {
619 		perror("FS WRITE");
620 		return(1);
621 	}
622 	return (0);
623 }
624 
625 bread(bno, buf, cnt)
626 	daddr_t bno;
627 	char *buf;
628 {
629 	register i;
630 
631 	lseek(fi, bno * DEV_BSIZE, 0);
632 	if ((i = read(fi, buf, cnt)) != cnt) {
633 		if (sflg) {
634 			printf("No Update\n");
635 			sflg = 0;
636 		}
637 		for(i=0; i<sblock.fs_bsize; i++)
638 			buf[i] = 0;
639 		return (1);
640 	}
641 	return (0);
642 }
643 
644 /*
645  * block operations
646  */
647 
648 isblock(fs, cp, h)
649 	struct fs *fs;
650 	unsigned char *cp;
651 	int h;
652 {
653 	unsigned char mask;
654 
655 	switch (fs->fs_frag) {
656 	case 8:
657 		return (cp[h] == 0xff);
658 	case 4:
659 		mask = 0x0f << ((h & 0x1) << 2);
660 		return ((cp[h >> 1] & mask) == mask);
661 	case 2:
662 		mask = 0x03 << ((h & 0x3) << 1);
663 		return ((cp[h >> 2] & mask) == mask);
664 	case 1:
665 		mask = 0x01 << (h & 0x7);
666 		return ((cp[h >> 3] & mask) == mask);
667 	default:
668 		fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
669 		return;
670 	}
671 }
672 
673 setblock(fs, cp, h)
674 	struct fs *fs;
675 	unsigned char *cp;
676 	int h;
677 {
678 	switch (fs->fs_frag) {
679 	case 8:
680 		cp[h] = 0xff;
681 		return;
682 	case 4:
683 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
684 		return;
685 	case 2:
686 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
687 		return;
688 	case 1:
689 		cp[h >> 3] |= (0x01 << (h & 0x7));
690 		return;
691 	default:
692 		fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
693 		return;
694 	}
695 }
696 
697 /*	tables.c	4.1	82/03/25	*/
698 
699 /* merged into kernel:	tables.c 2.1 3/25/82 */
700 
701 /* last monet version:	partab.c	4.2	81/03/08	*/
702 
703 /*
704  * bit patterns for identifying fragments in the block map
705  * used as ((map & around) == inside)
706  */
707 int around[9] = {
708 	0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
709 };
710 int inside[9] = {
711 	0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
712 };
713 
714 /*
715  * given a block map bit pattern, the frag tables tell whether a
716  * particular size fragment is available.
717  *
718  * used as:
719  * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] {
720  *	at least one fragment of the indicated size is available
721  * }
722  *
723  * These tables are used by the scanc instruction on the VAX to
724  * quickly find an appropriate fragment.
725  */
726 
727 unsigned char fragtbl124[256] = {
728 	0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e,
729 	0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a,
730 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
731 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
732 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
733 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
734 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
735 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
736 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
737 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
738 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
739 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
740 	0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e,
741 	0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae,
742 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
743 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
744 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
745 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
746 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
747 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
748 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
749 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
750 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
751 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
752 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
753 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
754 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
755 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
756 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
757 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
758 	0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce,
759 	0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a,
760 };
761 
762 unsigned char fragtbl8[256] = {
763 	0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04,
764 	0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
765 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
766 	0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
767 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
768 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
769 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
770 	0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
771 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
772 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
773 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
774 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
775 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
776 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
777 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
778 	0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40,
779 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
780 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
781 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
782 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
783 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
784 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
785 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
786 	0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
787 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
788 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
789 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
790 	0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12,
791 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
792 	0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c,
793 	0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c,
794 	0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
795 };
796 
797 /*
798  * the actual fragtbl array
799  */
800 unsigned char *fragtbl[MAXFRAG + 1] = {
801 	0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8,
802 };
803