xref: /csrg-svn/sbin/icheck/icheck.c (revision 4255)
1 static	char *sccsid = "@(#)icheck.c	1.3 (Berkeley) 08/28/81";
2 /*
3  * icheck
4  */
5 #define	NB	500
6 #define	BITS	8
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	sflg;
33 int	mflg;
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 long	szfrag;
48 daddr_t	nindir;
49 long	szindir;
50 daddr_t	niindir;
51 
52 daddr_t	nffree;
53 long	szffree;
54 daddr_t	nbfree;
55 
56 daddr_t	ndup;
57 
58 int	nerror;
59 
60 long	atol();
61 daddr_t	alloc();
62 #ifndef STANDALONE
63 char	*malloc();
64 #endif
65 
66 main(argc, argv)
67 char *argv[];
68 {
69 	register i;
70 	long n;
71 
72 	blist[0] = -1;
73 #ifndef STANDALONE
74 	while (--argc) {
75 		argv++;
76 		if (**argv=='-')
77 		switch ((*argv)[1]) {
78 		case 'd':
79 			dflg++;
80 			continue;
81 
82 		case 'm':
83 			mflg++;
84 			continue;
85 
86 		case 's':
87 			sflg++;
88 			continue;
89 
90 		case 'b':
91 			for(i=0; i<NB; i++) {
92 				n = atol(argv[1]);
93 				if(n == 0)
94 					break;
95 				blist[i] = n;
96 				argv++;
97 				argc--;
98 			}
99 			blist[i] = -1;
100 			continue;
101 
102 		default:
103 			printf("Bad flag\n");
104 		}
105 		check(*argv);
106 	}
107 #else
108 	{
109 		static char fname[128];
110 
111 		printf("File: ");
112 		gets(fname);
113 		check(fname);
114 	}
115 #endif
116 	return(nerror);
117 }
118 
119 check(file)
120 char *file;
121 {
122 	register i, j, c;
123 	daddr_t d, cgd, cbase, b;
124 	long n;
125 
126 	fi = open(file, sflg?2:0);
127 	if (fi < 0) {
128 		printf("cannot open %s\n", file);
129 		nerror |= 04;
130 		return;
131 	}
132 	printf("%s:\n", file);
133 	nrfile = 0;
134 	ndfile = 0;
135 	ncfile = 0;
136 	nbfile = 0;
137 	nmcfile = 0;
138 
139 	nblock = 0;
140 	nfrag = 0;
141 	szfrag = 0;
142 	nindir = 0;
143 	szindir = 0;
144 	niindir = 0;
145 
146 	ndup = 0;
147 #ifndef STANDALONE
148 	sync();
149 #endif
150 	bread(SBLOCK, (char *)&sblock, BSIZE);
151 	if (sblock.fs_magic != FS_MAGIC) {
152 		printf("%s: bad magic number\n", file);
153 		nerror |= 04;
154 		return;
155 	}
156 	sblock.fs_cs =
157 	    (struct csum *)calloc(howmany(cssize(&sblock), BSIZE), BSIZE);
158 	lseek(fi, csaddr(&sblock)*FSIZE, 0);
159 	read(fi, (char *)sblock.fs_cs, cssize(&sblock));
160 	ino = 0;
161 	n = (sblock.fs_size*FRAG + BITS-1) / BITS;
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 		sflg = 0;
171 	}
172 	ino = 0;
173 	cginit = 1;
174 	if(!dflg) {
175 		for (i=0; i<(unsigned)n; i++)
176 			bmap[i] = 0;
177 		for (c=0; c < sblock.fs_ncg; c++) {
178 			cgd = cgtod(c, &sblock);
179 			for (d = cgbase(c, &sblock); d < cgd; d++)
180 				chk(d, "badcg");
181 			d = cgimin(c, &sblock);
182 			while (cgd < d) {
183 				chk(cgd, "cg");
184 				cgd++;
185 			}
186 			d = cgdmin(c, &sblock);
187 			for (; cgd < d; cgd++)
188 				chk(cgd, "inode");
189 			if (c == 0) {
190 				d += howmany(cssize(&sblock), BSIZE) * FRAG;
191 				for (; cgd < d; cgd++)
192 					chk(cgd, "csum");
193 			}
194 		}
195 	}
196 	cginit = 0;
197 	for (c = 0; c < sblock.fs_ncg; c++) {
198 		bread(cgimin(c,&sblock), (char *)itab,
199 		    sblock.fs_ipg * sizeof (struct dinode));
200 		for (j=0; j < sblock.fs_ipg; j++) {
201 			pass1(&itab[j]);
202 			ino++;
203 		}
204 	}
205 	ino = 0;
206 #ifndef STANDALONE
207 	sync();
208 #endif
209 	bread(SBLOCK, (char *)&sblock, sizeof(sblock));
210 	if (sflg) {
211 		makecg();
212 		close(fi);
213 #ifndef STANDALONE
214 		if (bmap)
215 			free(bmap);
216 #endif
217 		return;
218 	}
219 	nffree = 0;
220 	szffree = 0;
221 	nbfree = 0;
222 	for (c = 0; c < sblock.fs_ncg; c++) {
223 		cbase = cgbase(c,&sblock);
224 		bread(cgtod(c,&sblock), (char *)&cgrp, sblock.fs_cgsize);
225 		for (b = 0; b < sblock.fs_fpg; b += FRAG) {
226 			if (isblock(cgrp.cg_free, b / FRAG)) {
227 				nbfree++;
228 				for (d = 0; d < FRAG; d++)
229 					chk(cbase+b+d, "block");
230 			} else {
231 				for (d = 0; d < FRAG; d++)
232 					if (isset(cgrp.cg_free, b+d)) {
233 						chk(cbase+b+d, "frag");
234 						nffree++;
235 						szffree++;
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 + niindir) * FRAG + szfrag + szindir;
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", szffree + 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", szffree + 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)) {
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 	register i, j;
284 	int k, l, sz, ni, nib, ndb;
285 
286 	i = ip->di_mode & IFMT;
287 	if(i == 0) {
288 		sblock.fs_nifree++;
289 		return;
290 	}
291 	switch (i) {
292 	case IFCHR:
293 		ncfile++;
294 		return;
295 	case IFBLK:
296 		nbfile++;
297 		return;
298 	case IFDIR:
299 		ndfile++;
300 		break;
301 	case IFREG:
302 		nrfile++;
303 		break;
304 	default:
305 		printf("bad mode %u\n", ino);
306 		return;
307 	}
308 	ndb = howmany(ip->di_size, BSIZE)-1;
309 	for(i=0; i<NDADDR; i++) {
310 		if(ip->di_db[i] == 0)
311 			continue;
312 		if (i==ndb && (ip->di_size&BMASK)) {
313 			sz = howmany(ip->di_size - i * BSIZE, FSIZE);
314 			for (l = 0; l < sz; l++)
315 				chk(ip->di_db[i]+l, "data (frag)");
316 			szfrag += sz;
317 			nfrag++;
318 		} else {
319 			for (l = 0; l < FRAG; l++)
320 				chk(ip->di_db[i]+l, "data (block)");
321 			nblock++;
322 		}
323 	}
324 	for(i=NDADDR; i<NDADDR+NIADDR;i++) {
325 		if(ip->di_ib[i] == 0)
326 			continue;
327 		nindir++;
328 		if (i==NDADDR) {
329 			sz = howmany((ip->di_size-NDADDR*BSIZE),
330 			    (NINDIR/FRAG) * BSIZE);
331 			if (sz > FRAG)
332 				sz = FRAG;
333 		} else
334 			sz = FRAG;
335 		for (j = 0; j < FRAG; j++)
336 			if (chk(ip->di_ib[i]+j, "1st indirect"))
337 				continue;
338 		bread(ip->di_ib[i], (char *)ind1, sz*FSIZE);
339 		nib = sz * (NINDIR/FRAG);
340 		for(j=0; j<nib; j++) {
341 			if(ind1[j] == 0)
342 				continue;
343 			if(i == NDADDR) {
344 				for (l = 0; l < FRAG; l++)
345 					chk(ind1[j]+l, "data (large)");
346 				nblock++;
347 				continue;
348 			}
349 			niindir++;
350 			for (l = 0; l < FRAG; l++)
351 				if(chk(ind1[j], "2nd indirect"))
352 					goto skip;
353 			bread(ind1[j], (char *)ind2, BSIZE);
354 			for(k=0; k<NINDIR; k++) {
355 				if(ind2[k] == 0)
356 					continue;
357 				for (l = 0; l < FRAG; l++)
358 					chk(ind1[j]+l, "data (huge)");
359 				nblock++;
360 				continue;
361 			}
362 skip:
363 			;
364 		}
365 	}
366 }
367 
368 chk(bno, s)
369 daddr_t bno;
370 char *s;
371 {
372 	register n, cg;
373 
374 	cg = dtog(bno, &sblock);
375 	if (cginit==0 && bno<cgdmin(cg,&sblock) || bno>=FRAG*sblock.fs_size) {
376 		printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
377 		return(1);
378 	}
379 	if (duped(bno)) {
380 		printf("%ld dup; inode=%u, class=%s\n", bno, ino, s);
381 		ndup++;
382 	}
383 	for (n=0; blist[n] != -1; n++)
384 		if (bno == blist[n])
385 			printf("%ld arg; inode=%u, class=%s\n", bno, ino, s);
386 	return(0);
387 }
388 
389 duped(bno)
390 daddr_t bno;
391 {
392 	daddr_t d;
393 	register m, n;
394 
395 	if(dflg)
396 		return(0);
397 	m = 1 << (bno%BITS);
398 	n = (bno/BITS);
399 	if(bmap[n] & m)
400 		return(1);
401 	bmap[n] |= m;
402 	return(0);
403 }
404 
405 bread(bno, buf, cnt)
406 daddr_t bno;
407 char *buf;
408 {
409 	register i;
410 
411 	lseek(fi, bno*FSIZE, 0);
412 	if ((i = read(fi, buf, cnt)) != cnt) {
413 		if (sflg) {
414 			printf("No update\n");
415 			sflg = 0;
416 		}
417 		for(i=0; i<BSIZE; i++)
418 			buf[i] = 0;
419 	}
420 }
421 
422 bwrite(bno, buf, cnt)
423 daddr_t bno;
424 char *buf;
425 {
426 	register i;
427 
428 	lseek(fi, bno*FSIZE, 0);
429 	if (write(fi, buf, cnt) != cnt)
430 		printf("write error %d\n", tell(fi)/BSIZE);
431 }
432 
433 makecg()
434 {
435 	int c;
436 	daddr_t dbase, d, dmin, dmax;
437 	long i, j, s;
438 	register struct csum *cs;
439 
440 	sblock.fs_nbfree = 0;
441 	sblock.fs_nffree = 0;
442 	for (c = 0; c < sblock.fs_ncg; c++) {
443 		bread(cgimin(c,&sblock), (char *)itab,
444 		    sblock.fs_ipg * sizeof (struct dinode));
445 		dbase = cgbase(c, &sblock);
446 		dmax = dbase + sblock.fs_fpg;
447 		if (dmax > sblock.fs_size)
448 			dmax = sblock.fs_size;
449 		cs = &sblock.fs_cs[c];
450 		cgrp.cg_time = time(0);
451 		cgrp.cg_magic = CG_MAGIC;
452 		cgrp.cg_cgx = c;
453 		cgrp.cg_ncyl = sblock.fs_cpg;
454 		cgrp.cg_niblk = sblock.fs_ipg;
455 		cgrp.cg_ndblk = dmax - dbase;
456 		cgrp.cg_ndir = 0;
457 		cgrp.cg_nffree = 0;
458 		cgrp.cg_nbfree = 0;
459 		cgrp.cg_nifree = 0;
460 		for (i = 0; i < sblock.fs_ipg; i++)
461 		switch (itab[i].di_mode&IFMT) {
462 
463 		case 0:
464 			cgrp.cg_nifree++;
465 			clrbit(cgrp.cg_iused, i);
466 			continue;
467 
468 		case IFDIR:
469 			cgrp.cg_ndir++;
470 			/* fall into ... */
471 
472 		default:
473 			setbit(cgrp.cg_iused, i);
474 			continue;
475 		}
476 		while (i < MAXIPG) {
477 			clrbit(cgrp.cg_iused, i);
478 			i++;
479 		}
480 		for (s = 0; s < MAXCPG; s++)
481 			for (i = 0; i < NRPOS; i++)
482 				cgrp.cg_b[s][i] = 0;
483 		dmin = cgdmin(c, &sblock) - dbase;
484 		if (c == 0)
485 			dmin += howmany(cssize(&sblock), BSIZE) * FRAG;
486 		for (d = 0; d < dmin; d++)
487 			clrbit(cgrp.cg_free, d);
488 #define	getbmap(i) isset(bmap, i)
489 		for (; (d + FRAG) <= dmax - dbase; d += FRAG) {
490 			j = 0;
491 			for (i = 0; i < FRAG; i++) {
492 				if (!getbmap(dbase+d+i)) {
493 					setbit(cgrp.cg_free, d+i);
494 					j++;
495 				} else
496 					clrbit(cgrp.cg_free, d+i);
497 			}
498 			if (j == FRAG) {
499 				cgrp.cg_nbfree++;
500 				s = d * NSPF;
501 				cgrp.cg_b[s/sblock.fs_spc]
502 				  [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
503 			} else
504 				cgrp.cg_nffree += j;
505 		}
506 		for (; d < dmax - dbase; d++) {
507 			if (!getbmap(dbase+d)) {
508 				setbit(cgrp.cg_free, d);
509 				cgrp.cg_nffree++;
510 			} else
511 				clrbit(cgrp.cg_free, d);
512 		}
513 		for (; d < MAXBPG; d++)
514 			clrbit(cgrp.cg_free, d);
515 		sblock.fs_nffree += cgrp.cg_nffree;
516 		sblock.fs_nbfree += cgrp.cg_nbfree;
517 		cs->cs_ndir = cgrp.cg_ndir;
518 		cs->cs_nifree = cgrp.cg_nifree;
519 		cs->cs_nbfree = cgrp.cg_nbfree;
520 		bwrite(cgtod(c, &sblock), (char *)&cgrp, sblock.fs_cgsize);
521 	}
522 	sblock.fs_ronly = 0;
523 	sblock.fs_fmod = 0;
524 	bwrite(SBLOCK, (char *)&sblock, sizeof (sblock));
525 	lseek(fi, csaddr(&sblock)*FSIZE, 0);
526 	if (write(fi,(char *)sblock.fs_cs,cssize(&sblock)) != cssize(&sblock))
527 		printf("write error %d\n", tell(fi)/BSIZE);
528 }
529