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