xref: /csrg-svn/sbin/icheck/icheck.c (revision 4410)
1 static	char *sccsid = "@(#)icheck.c	1.4 (Berkeley) 09/19/81";
2 
3 /*
4  * icheck
5  */
6 #define	NB	500
7 #define	BITS	8
8 #define	MAXFN	500
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[BSIZE];
20 } sbun;
21 #define	sblock sbun.sb
22 
23 union {
24 	struct	cg cg;
25 	char pad[BSIZE];
26 } cgun;
27 #define	cgrp cgun.cg
28 
29 struct	dinode	itab[MAXIPG];
30 daddr_t	blist[NB];
31 char	*bmap;
32 
33 int	sflg;
34 int	mflg;
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	nmcfile;
45 
46 daddr_t	nblock;
47 daddr_t	nfrag;
48 long	szfrag;
49 daddr_t	nindir;
50 long	szindir;
51 daddr_t	niindir;
52 
53 daddr_t	nffree;
54 long	szffree;
55 daddr_t	nbfree;
56 
57 daddr_t	ndup;
58 
59 int	nerror;
60 
61 long	atol();
62 daddr_t	alloc();
63 #ifndef STANDALONE
64 char	*malloc();
65 #endif
66 
67 main(argc, argv)
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 		printf("cannot open %s\n", 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 	szfrag = 0;
143 	nindir = 0;
144 	szindir = 0;
145 	niindir = 0;
146 
147 	ndup = 0;
148 #ifndef STANDALONE
149 	sync();
150 #endif
151 	bread(SBLOCK, (char *)&sblock, BSIZE);
152 	if (sblock.fs_magic != FS_MAGIC) {
153 		printf("%s: bad magic number\n", file);
154 		nerror |= 04;
155 		return;
156 	}
157 	sblock.fs_cs =
158 	    (struct csum *)calloc(howmany(cssize(&sblock), BSIZE), BSIZE);
159 	lseek(fi, csaddr(&sblock)*FSIZE, 0);
160 	read(fi, (char *)sblock.fs_cs, cssize(&sblock));
161 	ino = 0;
162 	n = (sblock.fs_size*FRAG + BITS-1) / BITS;
163 #ifdef STANDALONE
164 	bmap = NULL;
165 #else
166 	bmap = malloc((unsigned)n);
167 #endif
168 	if (bmap==NULL) {
169 		printf("Not enough core; duplicates unchecked\n");
170 		dflg++;
171 		sflg = 0;
172 	}
173 	ino = 0;
174 	cginit = 1;
175 	if(!dflg) {
176 		for (i=0; i<(unsigned)n; i++)
177 			bmap[i] = 0;
178 		for (c=0; c < sblock.fs_ncg; c++) {
179 			cgd = cgtod(c, &sblock);
180 			for (d = cgbase(c, &sblock); d < cgd; d += FRAG)
181 				chk(d, "badcg", 0);
182 			d = cgimin(c, &sblock);
183 			while (cgd < d) {
184 				chk(cgd, "cg", 0);
185 				cgd += FRAG;
186 			}
187 			d = cgdmin(c, &sblock);
188 			for (; cgd < d; cgd += FRAG)
189 				chk(cgd, "inode", 0);
190 			if (c == 0) {
191 				d += howmany(cssize(&sblock), FSIZE);
192 				for (; cgd < d; cgd += FRAG)
193 					chk(cgd, "csum", 0);
194 			}
195 		}
196 	}
197 	cginit = 0;
198 	for (c = 0; c < sblock.fs_ncg; c++) {
199 		bread(cgimin(c,&sblock), (char *)itab,
200 		    sblock.fs_ipg * sizeof (struct dinode));
201 		for (j=0; j < sblock.fs_ipg; j++) {
202 			pass1(&itab[j]);
203 			ino++;
204 		}
205 	}
206 	ino = 0;
207 #ifndef STANDALONE
208 	sync();
209 #endif
210 	bread(SBLOCK, (char *)&sblock, sizeof(sblock));
211 	if (sflg) {
212 		makecg();
213 		close(fi);
214 #ifndef STANDALONE
215 		if (bmap)
216 			free(bmap);
217 #endif
218 		return;
219 	}
220 	nffree = 0;
221 	szffree = 0;
222 	nbfree = 0;
223 	for (c = 0; c < sblock.fs_ncg; c++) {
224 		cbase = cgbase(c,&sblock);
225 		bread(cgtod(c,&sblock), (char *)&cgrp, sblock.fs_cgsize);
226 		for (b = 0; b < sblock.fs_fpg; b += FRAG) {
227 			if (isblock(cgrp.cg_free, b / FRAG)) {
228 				nbfree++;
229 				chk(cbase+b, "block", 0);
230 			} else {
231 				for (d = 0; d < FRAG; d++)
232 					if (isset(cgrp.cg_free, b+d)) {
233 						chk(cbase+b+d, "frag", 1);
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 + nindir + 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, 1)) {
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 	fsbaddr_t ind1[NINDIR];
282 	fsbaddr_t ind2[NINDIR];
283 	fsbaddr_t db, ib;
284 	register i, j, k;
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 	for (i = 0; i < NDADDR; i++) {
309 		db = ip->di_db[i];
310 		if (db == 0)
311 			continue;
312 		chk(fsbtodb(db), "data (block)", isfrag(db));
313 		nblock++;
314 	}
315 	for(i = 0; i < NIADDR; i++) {
316 		ib = ip->di_ib[i];
317 		if(ib == 0)
318 			continue;
319 		if (chk(fsbtodb(ib), "1st indirect", 0))
320 			continue;
321 		bread(fsbtodb(ib), (char *)ind1, BSIZE);
322 		nindir++;
323 		for (j = 0; j < NINDIR; j++) {
324 			ib = ind1[j];
325 			if (ib == 0)
326 				continue;
327 			if (i == 0) {
328 				chk(fsbtodb(ib), "data (large)", isfrag(ib));
329 				nblock++;
330 				continue;
331 			}
332 			if (chk(fsbtodb(ib), "2nd indirect", 0))
333 				continue;
334 			bread(fsbtodb(ib), (char *)ind2, BSIZE);
335 			niindir++;
336 			for (k = 0; k < NINDIR; k++) {
337 				ib = ind2[k];
338 				if (ib == 0)
339 					continue;
340 				chk(fsbtodb(ib), "data (huge)", isfrag(ib));
341 				nblock++;
342 			}
343 		}
344 	}
345 }
346 
347 chk(bno, s, fragflg)
348 	daddr_t bno;
349 	char *s;
350 	int fragflg;
351 {
352 	register n, cg;
353 
354 	cg = dtog(bno, &sblock);
355 	if (cginit==0 && bno<cgdmin(cg,&sblock) || bno>=FRAG*sblock.fs_size) {
356 		printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
357 		return(1);
358 	}
359 	if (duped(bno, fragflg)) {
360 		printf("%ld dup; inode=%u, class=%s\n", bno, ino, s);
361 		ndup++;
362 	}
363 	for (n=0; blist[n] != -1; n++)
364 		if (bno == blist[n])
365 			printf("%ld arg; inode=%u, class=%s\n", bno, ino, s);
366 	return(0);
367 }
368 
369 duped(bno, fragflg)
370 	daddr_t bno;
371 	int fragflg;
372 {
373 	if(dflg)
374 		return(0);
375 	if (fragflg) {
376 		if (isset(bmap, bno))
377 			return(1);
378 		setbit(bmap, bno);
379 		return (0);
380 	}
381 	if (bno % FRAG != 0)
382 		printf("bad bno %d to duped\n", bno);
383 	if (isblock(bmap, bno/FRAG))
384 		return (1);
385 	setblock(bmap, bno/FRAG);
386 	return(0);
387 }
388 
389 bread(bno, buf, cnt)
390 	daddr_t bno;
391 	char *buf;
392 {
393 	register i;
394 
395 	lseek(fi, bno*FSIZE, 0);
396 	if ((i = read(fi, buf, cnt)) != cnt) {
397 		if (sflg) {
398 			printf("No update\n");
399 			sflg = 0;
400 		}
401 		for(i=0; i<BSIZE; i++)
402 			buf[i] = 0;
403 	}
404 }
405 
406 bwrite(bno, buf, cnt)
407 	daddr_t bno;
408 	char *buf;
409 {
410 	lseek(fi, bno*FSIZE, 0);
411 	if (write(fi, buf, cnt) != cnt)
412 		printf("write error %d\n", tell(fi)/BSIZE);
413 }
414 
415 makecg()
416 {
417 	int c;
418 	daddr_t dbase, d, dmin, dmax;
419 	long i, j, s;
420 	register struct csum *cs;
421 
422 	sblock.fs_nbfree = 0;
423 	sblock.fs_nffree = 0;
424 	for (c = 0; c < sblock.fs_ncg; c++) {
425 		bread(cgimin(c,&sblock), (char *)itab,
426 		    sblock.fs_ipg * sizeof (struct dinode));
427 		dbase = cgbase(c, &sblock);
428 		dmax = dbase + sblock.fs_fpg;
429 		if (dmax > sblock.fs_size)
430 			dmax = sblock.fs_size;
431 		cs = &sblock.fs_cs[c];
432 		cgrp.cg_time = time((long)0);
433 		cgrp.cg_magic = CG_MAGIC;
434 		cgrp.cg_cgx = c;
435 		cgrp.cg_ncyl = sblock.fs_cpg;
436 		cgrp.cg_niblk = sblock.fs_ipg;
437 		cgrp.cg_ndblk = dmax - dbase;
438 		cgrp.cg_ndir = 0;
439 		cgrp.cg_nffree = 0;
440 		cgrp.cg_nbfree = 0;
441 		cgrp.cg_nifree = 0;
442 		for (i = 0; i < sblock.fs_ipg; i++)
443 		switch (itab[i].di_mode&IFMT) {
444 
445 		case 0:
446 			cgrp.cg_nifree++;
447 			clrbit(cgrp.cg_iused, i);
448 			continue;
449 
450 		case IFDIR:
451 			cgrp.cg_ndir++;
452 			/* fall into ... */
453 
454 		default:
455 			setbit(cgrp.cg_iused, i);
456 			continue;
457 		}
458 		while (i < MAXIPG) {
459 			clrbit(cgrp.cg_iused, i);
460 			i++;
461 		}
462 		for (s = 0; s < MAXCPG; s++)
463 			for (i = 0; i < NRPOS; i++)
464 				cgrp.cg_b[s][i] = 0;
465 		dmin = cgdmin(c, &sblock) - dbase;
466 		if (c == 0)
467 			dmin += howmany(cssize(&sblock), BSIZE) * FRAG;
468 		for (d = 0; d < dmin; d++)
469 			clrbit(cgrp.cg_free, d);
470 #define	getbmap(i) isset(bmap, i)
471 		for (; (d + FRAG) <= dmax - dbase; d += FRAG) {
472 			j = 0;
473 			for (i = 0; i < FRAG; i++) {
474 				if (!getbmap(dbase+d+i)) {
475 					setbit(cgrp.cg_free, d+i);
476 					j++;
477 				} else
478 					clrbit(cgrp.cg_free, d+i);
479 			}
480 			if (j == FRAG) {
481 				cgrp.cg_nbfree++;
482 				s = d * NSPF;
483 				cgrp.cg_b[s/sblock.fs_spc]
484 				  [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
485 			} else
486 				cgrp.cg_nffree += j;
487 		}
488 		for (; d < dmax - dbase; d++) {
489 			if (!getbmap(dbase+d)) {
490 				setbit(cgrp.cg_free, d);
491 				cgrp.cg_nffree++;
492 			} else
493 				clrbit(cgrp.cg_free, d);
494 		}
495 		for (; d < MAXBPG; d++)
496 			clrbit(cgrp.cg_free, d);
497 		sblock.fs_nffree += cgrp.cg_nffree;
498 		sblock.fs_nbfree += cgrp.cg_nbfree;
499 		cs->cs_ndir = cgrp.cg_ndir;
500 		cs->cs_nifree = cgrp.cg_nifree;
501 		cs->cs_nbfree = cgrp.cg_nbfree;
502 		bwrite(cgtod(c, &sblock), (char *)&cgrp, sblock.fs_cgsize);
503 	}
504 	sblock.fs_ronly = 0;
505 	sblock.fs_fmod = 0;
506 	bwrite(SBLOCK, (char *)&sblock, sizeof (sblock));
507 	lseek(fi, csaddr(&sblock) * FSIZE, 0);
508 	if (write(fi,(char *)sblock.fs_cs,cssize(&sblock)) != cssize(&sblock))
509 		printf("write error %d\n", tell(fi)/BSIZE);
510 }
511