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