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