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