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