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