xref: /csrg-svn/sbin/icheck/icheck.c (revision 8143)
1 static	char *sccsid = "@(#)icheck.c	2.3 (Berkeley) 09/10/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 		if (c == sblock.fs_ncg - 1)
452 			cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
453 		else
454 			cgrp.cg_ncyl = sblock.fs_cpg;
455 		cgrp.cg_niblk = sblock.fs_ipg;
456 		cgrp.cg_ndblk = dmax - dbase;
457 		cgrp.cg_cs.cs_ndir = 0;
458 		cgrp.cg_cs.cs_nffree = 0;
459 		cgrp.cg_cs.cs_nbfree = 0;
460 		cgrp.cg_cs.cs_nifree = 0;
461 		cgrp.cg_rotor = 0;
462 		cgrp.cg_frotor = 0;
463 		cgrp.cg_irotor = 0;
464 		for (i = 0; i < sblock.fs_frag; i++)
465 			cgrp.cg_frsum[i] = 0;
466 		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
467 		      sblock.fs_ipg * sizeof(struct dinode));
468 		for (i = 0; i < sblock.fs_ipg; i++) {
469 			cgrp.cg_cs.cs_nifree++;
470 			clrbit(cgrp.cg_iused, i);
471 			dp = &itab[i];
472 			if ((dp->di_mode & IFMT) != 0) {
473 				if ((dp->di_mode & IFMT) == IFDIR)
474 					cgrp.cg_cs.cs_ndir++;
475 				cgrp.cg_cs.cs_nifree--;
476 				setbit(cgrp.cg_iused, i);
477 				continue;
478 			}
479 		}
480 		while (i < MAXIPG) {
481 			clrbit(cgrp.cg_iused, i);
482 			i++;
483 		}
484 		if (c == 0)
485 			for (i = 0; i < ROOTINO; i++) {
486 				setbit(cgrp.cg_iused, i);
487 				cgrp.cg_cs.cs_nifree--;
488 			}
489 		for (s = 0; s < MAXCPG; s++) {
490 			cgrp.cg_btot[s] = 0;
491 			for (i = 0; i < NRPOS; i++)
492 				cgrp.cg_b[s][i] = 0;
493 		}
494 		if (c == 0) {
495 			dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
496 		}
497 		for (d = dlower; d < dupper; d++)
498 			clrbit(cgrp.cg_free, d);
499 		for (d = 0; (d + sblock.fs_frag) <= dmax - dbase;
500 		    d += sblock.fs_frag) {
501 			j = 0;
502 			for (i = 0; i < sblock.fs_frag; i++) {
503 				if (!isset(bmap, dbase + d + i)) {
504 					setbit(cgrp.cg_free, d + i);
505 					j++;
506 				} else
507 					clrbit(cgrp.cg_free, d+i);
508 			}
509 			if (j == sblock.fs_frag) {
510 				cgrp.cg_cs.cs_nbfree++;
511 				cgrp.cg_btot[cbtocylno(&sblock, d)]++;
512 				cgrp.cg_b[cbtocylno(&sblock, d)]
513 				    [cbtorpos(&sblock, d)]++;
514 			} else if (j > 0) {
515 				cgrp.cg_cs.cs_nffree += j;
516 				blk = blkmap(&sblock, cgrp.cg_free, d);
517 				fragacct(&sblock, blk, cgrp.cg_frsum, 1);
518 			}
519 		}
520 		for (j = d; d < dmax - dbase; d++) {
521 			if (!isset(bmap, dbase + d)) {
522 				setbit(cgrp.cg_free, d);
523 				cgrp.cg_cs.cs_nffree++;
524 			} else
525 				clrbit(cgrp.cg_free, d);
526 		}
527 		for (; d % sblock.fs_frag != 0; d++)
528 			clrbit(cgrp.cg_free, d);
529 		if (j != d) {
530 			blk = blkmap(&sblock, cgrp.cg_free, j);
531 			fragacct(&sblock, blk, cgrp.cg_frsum, 1);
532 		}
533 		for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++)
534 			clrblock(&sblock, cgrp.cg_free, d);
535 		sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
536 		sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
537 		sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
538 		sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
539 		*cs = cgrp.cg_cs;
540 		bwrite(fsbtodb(&sblock, cgtod(&sblock, c)), &cgrp,
541 			sblock.fs_cgsize);
542 	}
543 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
544 		bwrite(fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
545 		    (char *)sblock.fs_csp[j],
546 		    sblock.fs_cssize - i < sblock.fs_bsize ?
547 		    sblock.fs_cssize - i : sblock.fs_bsize);
548 	}
549 	sblock.fs_ronly = 0;
550 	sblock.fs_fmod = 0;
551 	bwrite(SBLOCK, (char *)&sblock, SBSIZE);
552 }
553 
554 /*
555  * update the frsum fields to reflect addition or deletion
556  * of some frags
557  */
558 fragacct(fs, fragmap, fraglist, cnt)
559 	struct fs *fs;
560 	int fragmap;
561 	long fraglist[];
562 	int cnt;
563 {
564 	int inblk;
565 	register int field, subfield;
566 	register int siz, pos;
567 
568 	inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1);
569 	fragmap <<= 1;
570 	for (siz = 1; siz < fs->fs_frag; siz++) {
571 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
572 			continue;
573 		field = around[siz];
574 		subfield = inside[siz];
575 		for (pos = siz; pos <= fs->fs_frag; pos++) {
576 			if ((fragmap & field) == subfield) {
577 				fraglist[siz] += cnt;
578 				pos += siz;
579 				field <<= siz;
580 				subfield <<= siz;
581 			}
582 			field <<= 1;
583 			subfield <<= 1;
584 		}
585 	}
586 }
587 
588 getsb(fs, file)
589 	register struct fs *fs;
590 	char *file;
591 {
592 	int i, j, size;
593 
594 	if (bread(SBLOCK, fs, SBSIZE)) {
595 		printf("bad super block");
596 		perror(file);
597 		nerror |= 04;
598 		return;
599 	}
600 	if (fs->fs_magic != FS_MAGIC) {
601 		printf("%s: bad magic number\n", file);
602 		nerror |= 04;
603 		return;
604 	}
605 	for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
606 		size = sblock.fs_cssize - i < sblock.fs_bsize ?
607 		    sblock.fs_cssize - i : sblock.fs_bsize;
608 		sblock.fs_csp[j] = (struct csum *)calloc(1, size);
609 		bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)),
610 		      (char *)fs->fs_csp[j], size);
611 	}
612 }
613 
614 bwrite(blk, buf, size)
615 	char *buf;
616 	daddr_t blk;
617 	register size;
618 {
619 	if (lseek(fi, blk * DEV_BSIZE, 0) < 0) {
620 		perror("FS SEEK");
621 		return(1);
622 	}
623 	if (write(fi, buf, size) != size) {
624 		perror("FS WRITE");
625 		return(1);
626 	}
627 	return (0);
628 }
629 
630 bread(bno, buf, cnt)
631 	daddr_t bno;
632 	char *buf;
633 {
634 	register i;
635 
636 	lseek(fi, bno * DEV_BSIZE, 0);
637 	if ((i = read(fi, buf, cnt)) != cnt) {
638 		if (sflg) {
639 			printf("No Update\n");
640 			sflg = 0;
641 		}
642 		for(i=0; i<sblock.fs_bsize; i++)
643 			buf[i] = 0;
644 		return (1);
645 	}
646 	return (0);
647 }
648 
649 /*
650  * check if a block is available
651  */
652 isblock(fs, cp, h)
653 	struct fs *fs;
654 	unsigned char *cp;
655 	int h;
656 {
657 	unsigned char mask;
658 
659 	switch (fs->fs_frag) {
660 	case 8:
661 		return (cp[h] == 0xff);
662 	case 4:
663 		mask = 0x0f << ((h & 0x1) << 2);
664 		return ((cp[h >> 1] & mask) == mask);
665 	case 2:
666 		mask = 0x03 << ((h & 0x3) << 1);
667 		return ((cp[h >> 2] & mask) == mask);
668 	case 1:
669 		mask = 0x01 << (h & 0x7);
670 		return ((cp[h >> 3] & mask) == mask);
671 	default:
672 #ifdef STANDALONE
673 		printf("isblock bad fs_frag %d\n", fs->fs_frag);
674 #else
675 		fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
676 #endif
677 		return;
678 	}
679 }
680 
681 /*
682  * take a block out of the map
683  */
684 clrblock(fs, cp, h)
685 	struct fs *fs;
686 	unsigned char *cp;
687 	int h;
688 {
689 	switch ((fs)->fs_frag) {
690 	case 8:
691 		cp[h] = 0;
692 		return;
693 	case 4:
694 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
695 		return;
696 	case 2:
697 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
698 		return;
699 	case 1:
700 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
701 		return;
702 	default:
703 #ifdef STANDALONE
704 		printf("clrblock bad fs_frag %d\n", fs->fs_frag);
705 #else
706 		fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
707 #endif
708 		return;
709 	}
710 }
711 
712 /*
713  * put a block into the map
714  */
715 setblock(fs, cp, h)
716 	struct fs *fs;
717 	unsigned char *cp;
718 	int h;
719 {
720 	switch (fs->fs_frag) {
721 	case 8:
722 		cp[h] = 0xff;
723 		return;
724 	case 4:
725 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
726 		return;
727 	case 2:
728 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
729 		return;
730 	case 1:
731 		cp[h >> 3] |= (0x01 << (h & 0x7));
732 		return;
733 	default:
734 #ifdef STANDALONE
735 		printf("setblock bad fs_frag %d\n", fs->fs_frag);
736 #else
737 		fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
738 #endif
739 		return;
740 	}
741 }
742 
743 /*	tables.c	4.1	82/03/25	*/
744 
745 /* merged into kernel:	tables.c 2.1 3/25/82 */
746 
747 /* last monet version:	partab.c	4.2	81/03/08	*/
748 
749 /*
750  * bit patterns for identifying fragments in the block map
751  * used as ((map & around) == inside)
752  */
753 int around[9] = {
754 	0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
755 };
756 int inside[9] = {
757 	0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
758 };
759 
760 /*
761  * given a block map bit pattern, the frag tables tell whether a
762  * particular size fragment is available.
763  *
764  * used as:
765  * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] {
766  *	at least one fragment of the indicated size is available
767  * }
768  *
769  * These tables are used by the scanc instruction on the VAX to
770  * quickly find an appropriate fragment.
771  */
772 
773 unsigned char fragtbl124[256] = {
774 	0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e,
775 	0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a,
776 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
777 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
778 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
779 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
780 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
781 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
782 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
783 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
784 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
785 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
786 	0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e,
787 	0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae,
788 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
789 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
790 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
791 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
792 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
793 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
794 	0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
795 	0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
796 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
797 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
798 	0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
799 	0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
800 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
801 	0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
802 	0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
803 	0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
804 	0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce,
805 	0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a,
806 };
807 
808 unsigned char fragtbl8[256] = {
809 	0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04,
810 	0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
811 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
812 	0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
813 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
814 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
815 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
816 	0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
817 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
818 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
819 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
820 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
821 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
822 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
823 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
824 	0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40,
825 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
826 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
827 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
828 	0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
829 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
830 	0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
831 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
832 	0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
833 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
834 	0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
835 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
836 	0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12,
837 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
838 	0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c,
839 	0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c,
840 	0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
841 };
842 
843 /*
844  * the actual fragtbl array
845  */
846 unsigned char *fragtbl[MAXFRAG + 1] = {
847 	0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8,
848 };
849