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