xref: /csrg-svn/sbin/icheck/icheck.c (revision 4790)
1 static	char *sccsid = "@(#)icheck.c	1.8 (Berkeley) 11/07/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	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 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 long	atol();
58 daddr_t	alloc();
59 #ifndef STANDALONE
60 char	*malloc();
61 #endif
62 
63 main(argc, argv)
64 char *argv[];
65 {
66 	register i;
67 	long n;
68 
69 	blist[0] = -1;
70 #ifndef STANDALONE
71 	while (--argc) {
72 		argv++;
73 		if (**argv=='-')
74 		switch ((*argv)[1]) {
75 		case 'd':
76 			dflg++;
77 			continue;
78 
79 		case 'm':
80 			mflg++;
81 			continue;
82 
83 		case 'b':
84 			for(i=0; i<NB; i++) {
85 				n = atol(argv[1]);
86 				if(n == 0)
87 					break;
88 				blist[i] = n;
89 				argv++;
90 				argc--;
91 			}
92 			blist[i] = -1;
93 			continue;
94 
95 		default:
96 			printf("Bad flag\n");
97 		}
98 		check(*argv);
99 	}
100 #else
101 	{
102 		static char fname[128];
103 
104 		printf("File: ");
105 		gets(fname);
106 		check(fname);
107 	}
108 #endif
109 	return(nerror);
110 }
111 
112 check(file)
113 char *file;
114 {
115 	register i, j, c;
116 	daddr_t d, cgd, cbase, b;
117 	long n;
118 
119 	fi = open(file, 0);
120 	if (fi < 0) {
121 		printf("cannot open %s\n", file);
122 		nerror |= 04;
123 		return;
124 	}
125 	printf("%s:\n", file);
126 	nrfile = 0;
127 	ndfile = 0;
128 	ncfile = 0;
129 	nbfile = 0;
130 	nmcfile = 0;
131 
132 	nblock = 0;
133 	nfrag = 0;
134 	nindir = 0;
135 	niindir = 0;
136 
137 	ndup = 0;
138 #ifndef STANDALONE
139 	sync();
140 #endif
141 	bread(SBLOCK, (char *)&sblock, BSIZE);
142 	if (sblock.fs_magic != FS_MAGIC) {
143 		printf("%s: bad magic number\n", file);
144 		nerror |= 04;
145 		return;
146 	}
147 	for (n = 0; n < howmany(cssize(&sblock), BSIZE); n++) {
148 		sblock.fs_csp[n] = (struct csum *)calloc(1, BSIZE);
149 		bread(csaddr(&sblock) + (n * FRAG),
150 		      (char *)sblock.fs_csp[n], BSIZE);
151 	}
152 	ino = 0;
153 	n = (sblock.fs_size*FRAG + BITS-1) / BITS;
154 #ifdef STANDALONE
155 	bmap = NULL;
156 #else
157 	bmap = malloc((unsigned)n);
158 #endif
159 	if (bmap==NULL) {
160 		printf("Not enough core; duplicates unchecked\n");
161 		dflg++;
162 	}
163 	ino = 0;
164 	cginit = 1;
165 	if(!dflg) {
166 		for (i=0; i<(unsigned)n; i++)
167 			bmap[i] = 0;
168 		for (c=0; c < sblock.fs_ncg; c++) {
169 			cgd = cgtod(c, &sblock);
170 			for (d = cgbase(c, &sblock); d < cgd; d += FRAG)
171 				chk(d, "badcg", BSIZE);
172 			d = cgimin(c, &sblock);
173 			while (cgd < d) {
174 				chk(cgd, "cg", BSIZE);
175 				cgd += FRAG;
176 			}
177 			d = cgdmin(c, &sblock);
178 			for (; cgd < d; cgd += FRAG)
179 				chk(cgd, "inode", BSIZE);
180 			if (c == 0) {
181 				d += howmany(cssize(&sblock), FSIZE);
182 				for (; cgd < d; cgd += FRAG)
183 					chk(cgd, "csum", BSIZE);
184 			}
185 		}
186 	}
187 	cginit = 0;
188 	for (c = 0; c < sblock.fs_ncg; c++) {
189 		bread(cgimin(c,&sblock), (char *)itab,
190 		    sblock.fs_ipg * sizeof (struct dinode));
191 		for (j=0; j < sblock.fs_ipg; j++) {
192 			pass1(&itab[j]);
193 			ino++;
194 		}
195 	}
196 	ino = 0;
197 #ifndef STANDALONE
198 	sync();
199 #endif
200 	bread(SBLOCK, (char *)&sblock, sizeof(sblock));
201 	nffree = 0;
202 	nbfree = 0;
203 	for (c = 0; c < sblock.fs_ncg; c++) {
204 		cbase = cgbase(c,&sblock);
205 		bread(cgtod(c,&sblock), (char *)&cgrp, sblock.fs_cgsize);
206 		for (b = 0; b < sblock.fs_fpg; b += FRAG) {
207 			if (isblock(cgrp.cg_free, b / FRAG)) {
208 				nbfree++;
209 				chk(cbase+b, "block", BSIZE);
210 			} else {
211 				for (d = 0; d < FRAG; d++)
212 					if (isset(cgrp.cg_free, b+d)) {
213 						chk(cbase+b+d, "frag", FSIZE);
214 						nffree++;
215 					}
216 			}
217 		}
218 	}
219 	close(fi);
220 #ifndef STANDALONE
221 	if (bmap)
222 		free(bmap);
223 #endif
224 
225 	i = nrfile + ndfile + ncfile + nbfile + nmcfile;
226 #ifndef STANDALONE
227 	printf("files %6u (r=%u,d=%u,b=%u,c=%u,mc=%u)\n",
228 		i, nrfile, ndfile, nbfile, ncfile, nmcfile);
229 #else
230 	printf("files %u (r=%u,d=%u,b=%u,c=%u,mc=%u)\n",
231 		i, nrfile, ndfile, nbfile, ncfile, nmcfile);
232 #endif
233 	n = (nblock + nindir + niindir) * FRAG + nfrag;
234 #ifdef STANDALONE
235 	printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
236 		n, nindir, niindir, nblock, nfrag);
237 	printf("free %ld (b=%ld,f=%ld)\n", nffree + FRAG * nbfree,
238 	    nbfree, nffree);
239 #else
240 	printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
241 		n, nindir, niindir, nblock, nfrag);
242 	printf("free %7ld (b=%ld,f=%ld)\n", nffree + FRAG * nbfree,
243 	    nbfree, nffree);
244 #endif
245 	if(!dflg) {
246 		n = 0;
247 		for (d = 0; d < sblock.fs_size; d++)
248 			if(!duped(d, FSIZE)) {
249 				if(mflg)
250 					printf("%ld missing\n", d);
251 				n++;
252 			}
253 		printf("missing%5ld\n", n);
254 	}
255 }
256 
257 pass1(ip)
258 	register struct dinode *ip;
259 {
260 	daddr_t ind1[NINDIR];
261 	daddr_t ind2[NINDIR];
262 	daddr_t db, ib;
263 	register int i, j, k, siz;
264 
265 	i = ip->di_mode & IFMT;
266 	if(i == 0)
267 		return;
268 	switch (i) {
269 	case IFCHR:
270 		ncfile++;
271 		return;
272 	case IFBLK:
273 		nbfile++;
274 		return;
275 	case IFDIR:
276 		ndfile++;
277 		break;
278 	case IFREG:
279 		nrfile++;
280 		break;
281 	default:
282 		printf("bad mode %u\n", ino);
283 		return;
284 	}
285 	for (i = 0; i < NDADDR; i++) {
286 		db = ip->di_db[i];
287 		if (db == 0)
288 			continue;
289 		siz = dblksize(ip, i);
290 		chk(db, "data (block)", siz);
291 		if (siz == BSIZE)
292 			nblock++;
293 		else
294 			nfrag += howmany(siz, FSIZE);
295 	}
296 	for(i = 0; i < NIADDR; i++) {
297 		ib = ip->di_ib[i];
298 		if(ib == 0)
299 			continue;
300 		if (chk(ib, "1st indirect", BSIZE))
301 			continue;
302 		bread(ib, (char *)ind1, BSIZE);
303 		nindir++;
304 		for (j = 0; j < NINDIR; j++) {
305 			ib = ind1[j];
306 			if (ib == 0)
307 				continue;
308 			if (i == 0) {
309 				siz = dblksize(ip, NDADDR + j);
310 				chk(ib, "data (large)", siz);
311 				if (siz == BSIZE)
312 					nblock++;
313 				else
314 					nfrag += howmany(siz, FSIZE);
315 				continue;
316 			}
317 			if (chk(ib, "2nd indirect", BSIZE))
318 				continue;
319 			bread(ib, (char *)ind2, BSIZE);
320 			niindir++;
321 			for (k = 0; k < NINDIR; k++) {
322 				ib = ind2[k];
323 				if (ib == 0)
324 					continue;
325 				siz = dblksize(ip,
326 				    NDADDR + NINDIR * (i + j) + k);
327 				chk(ib, "data (huge)", siz);
328 				if (siz == BSIZE)
329 					nblock++;
330 				else
331 					nfrag += howmany(siz, FSIZE);
332 			}
333 		}
334 	}
335 }
336 
337 chk(bno, s, size)
338 	daddr_t bno;
339 	char *s;
340 	int size;
341 {
342 	register n, cg;
343 
344 	cg = dtog(bno, &sblock);
345 	if (cginit==0 &&
346 	    bno<cgdmin(cg,&sblock) || bno >= FRAG * sblock.fs_size) {
347 		printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
348 		return(1);
349 	}
350 	if (size == BSIZE) {
351 		if (duped(bno, size)) {
352 			printf("%ld dup block; inode=%u, class=%s\n",
353 			    bno, ino, s);
354 			ndup += FRAG;
355 		}
356 	} else {
357 		for (n = 0; n < size / FSIZE; n++) {
358 			if (duped(bno + n, FSIZE)) {
359 				printf("%ld dup frag; inode=%u, class=%s\n",
360 				    bno, ino, s);
361 				ndup++;
362 			}
363 		}
364 	}
365 	for (n=0; blist[n] != -1; n++)
366 		if (bno == blist[n])
367 			printf("%ld arg; inode=%u, class=%s\n", bno, ino, s);
368 	return(0);
369 }
370 
371 duped(bno, size)
372 	daddr_t bno;
373 	int size;
374 {
375 	if(dflg)
376 		return(0);
377 	if (size != FSIZE && size != BSIZE)
378 		printf("bad size %d to duped\n", size);
379 	if (size == FSIZE) {
380 		if (isset(bmap, bno))
381 			return(1);
382 		setbit(bmap, bno);
383 		return (0);
384 	}
385 	if (bno % FRAG != 0)
386 		printf("bad bno %d to duped\n", bno);
387 	if (isblock(bmap, bno/FRAG))
388 		return (1);
389 	setblock(bmap, bno/FRAG);
390 	return(0);
391 }
392 
393 bread(bno, buf, cnt)
394 	daddr_t bno;
395 	char *buf;
396 {
397 	register i;
398 
399 	lseek(fi, bno*FSIZE, 0);
400 	if ((i = read(fi, buf, cnt)) != cnt) {
401 		for(i=0; i<BSIZE; i++)
402 			buf[i] = 0;
403 	}
404 }
405