1 /*-
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1988, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)icheck.c 8.1 (Berkeley) 06/05/93";
16 #endif /* not lint */
17
18 /*
19 * icheck
20 */
21 #define NB 500
22 #define MAXFN 500
23 #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t))
24
25 #include <sys/param.h>
26 #include <sys/time.h>
27 #include <ufs/ufs/dinode.h>
28 #include <ufs/ffs/fs.h>
29 #ifndef STANDALONE
30 #include <unistd.h>
31 #include <stdio.h>
32 #endif
33
34 union {
35 struct fs sb;
36 char pad[SBSIZE];
37 } sbun;
38 #define sblock sbun.sb
39
40 union {
41 struct cg cg;
42 char pad[MAXBSIZE];
43 } cgun;
44 #define cgrp cgun.cg
45
46 struct dinode itab[MAXBSIZE / sizeof(struct dinode)];
47
48 daddr_t blist[NB];
49 daddr_t fsblist[NB];
50 char *bmap;
51
52 int mflg;
53 int dflg;
54 int fi;
55 ino_t ino;
56 int cginit;
57
58 ino_t nrfile;
59 ino_t ndfile;
60 ino_t nbfile;
61 ino_t ncfile;
62 ino_t nlfile;
63 ino_t nsfile;
64
65 daddr_t nblock;
66 daddr_t nfrag;
67 daddr_t nindir;
68 daddr_t niindir;
69
70 daddr_t nffree;
71 daddr_t nbfree;
72
73 daddr_t ndup;
74
75 int nerror;
76 long dev_bsize = 1;
77
78 int bread __P((daddr_t, char *, ssize_t));
79 long atol();
80 #ifndef STANDALONE
81 char *malloc();
82 char *calloc();
83 #endif
84
main(argc,argv)85 main(argc, argv)
86 int argc;
87 char *argv[];
88 {
89 register i;
90 long n;
91
92 blist[0] = -1;
93 #ifndef STANDALONE
94 while (--argc) {
95 argv++;
96 if (**argv=='-')
97 switch ((*argv)[1]) {
98 case 'd':
99 dflg++;
100 continue;
101
102 case 'm':
103 mflg++;
104 continue;
105
106 case 'b':
107 for(i=0; i<NB && argc >= 2; i++) {
108 n = atol(argv[1]);
109 if(n == 0)
110 break;
111 blist[i] = n;
112 argv++;
113 argc--;
114 }
115 blist[i] = -1;
116 continue;
117
118 default:
119 printf("Bad flag\n");
120 }
121 check(*argv);
122 }
123 #else
124 {
125 static char fname[128];
126
127 printf("File: ");
128 gets(fname);
129 check(fname);
130 }
131 #endif
132 return(nerror);
133 }
134
check(file)135 check(file)
136 char *file;
137 {
138 register i, j, c;
139 daddr_t d, cgd, cbase, b;
140 long n;
141 char buf[BUFSIZ];
142
143 fi = open(file, 0);
144 if (fi < 0) {
145 perror(file);
146 nerror |= 04;
147 return;
148 }
149 printf("%s:\n", file);
150 nrfile = 0;
151 ndfile = 0;
152 ncfile = 0;
153 nbfile = 0;
154 nlfile = 0;
155 nsfile = 0;
156
157 nblock = 0;
158 nfrag = 0;
159 nindir = 0;
160 niindir = 0;
161
162 ndup = 0;
163 #ifndef STANDALONE
164 sync();
165 #endif
166 getsb(&sblock, file);
167 if (nerror)
168 return;
169 for (n=0; blist[n] != -1; n++)
170 fsblist[n] = dbtofsb(&sblock, blist[n]);
171 ino = 0;
172 n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short));
173 #ifdef STANDALONE
174 bmap = NULL;
175 #else
176 bmap = malloc((unsigned)n);
177 #endif
178 if (bmap==NULL) {
179 printf("Not enough core; duplicates unchecked\n");
180 dflg++;
181 }
182 ino = 0;
183 cginit = 1;
184 if (!dflg) {
185 for (i = 0; i < (unsigned)n; i++)
186 bmap[i] = 0;
187 for (c = 0; c < sblock.fs_ncg; c++) {
188 cgd = cgtod(&sblock, c);
189 if (c == 0)
190 d = cgbase(&sblock, c);
191 else
192 d = cgsblock(&sblock, c);
193 (void)sprintf(buf, "spare super block %d", c);
194 for (; d < cgd; d += sblock.fs_frag)
195 chk(d, buf, sblock.fs_bsize);
196 d = cgimin(&sblock, c);
197 (void)sprintf(buf, "cylinder group %d", c);
198 while (cgd < d) {
199 chk(cgd, buf, sblock.fs_bsize);
200 cgd += sblock.fs_frag;
201 }
202 d = cgdmin(&sblock, c);
203 i = INOPB(&sblock);
204 for (; cgd < d; cgd += sblock.fs_frag) {
205 (void)sprintf(buf, "inodes %d-%d", ino, ino + i);
206 chk(cgd, buf, sblock.fs_bsize);
207 ino += i;
208 }
209 if (c == 0) {
210 d += howmany(sblock.fs_cssize, sblock.fs_fsize);
211 for (; cgd < d; cgd++)
212 chk(cgd, "csum", sblock.fs_fsize);
213 }
214 }
215 }
216 ino = 0;
217 cginit = 0;
218 for (c = 0; c < sblock.fs_ncg; c++) {
219 for (i = 0;
220 i < sblock.fs_ipg / INOPF(&sblock);
221 i += sblock.fs_frag) {
222 bread(fsbtodb(&sblock, cgimin(&sblock, c) + i),
223 (char *)itab, sblock.fs_bsize);
224 for (j = 0; j < INOPB(&sblock); j++) {
225 pass1(&itab[j]);
226 ino++;
227 }
228 }
229 }
230 ino = 0;
231 #ifndef STANDALONE
232 sync();
233 #endif
234 nffree = 0;
235 nbfree = 0;
236 for (c = 0; c < sblock.fs_ncg; c++) {
237 cbase = cgbase(&sblock, c);
238 bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp,
239 sblock.fs_cgsize);
240 if (!cg_chkmagic(&cgrp))
241 printf("cg %d: bad magic number\n", c);
242 for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
243 if (isblock(&sblock, cg_blksfree(&cgrp),
244 b / sblock.fs_frag)) {
245 nbfree++;
246 chk(cbase+b, "free block", sblock.fs_bsize);
247 } else {
248 for (d = 0; d < sblock.fs_frag; d++)
249 if (isset(cg_blksfree(&cgrp), b+d)) {
250 chk(cbase+b+d, "free frag", sblock.fs_fsize);
251 nffree++;
252 }
253 }
254 }
255 }
256 close(fi);
257 #ifndef STANDALONE
258 if (bmap)
259 free(bmap);
260 #endif
261
262 i = nrfile + ndfile + ncfile + nbfile + nlfile + nsfile;
263 #ifndef STANDALONE
264 printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n",
265 i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile);
266 #else
267 printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n",
268 i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile);
269 #endif
270 n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag;
271 #ifdef STANDALONE
272 printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
273 n, nindir, niindir, nblock, nfrag);
274 printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree,
275 nbfree, nffree);
276 #else
277 printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n",
278 n, nindir, niindir, nblock, nfrag);
279 printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree,
280 nbfree, nffree);
281 #endif
282 if(!dflg) {
283 n = 0;
284 for (d = 0; d < sblock.fs_size; d++)
285 if(!duped(d, sblock.fs_fsize)) {
286 if(mflg)
287 printf("%ld missing\n", d);
288 n++;
289 }
290 printf("missing%5ld\n", n);
291 }
292 }
293
pass1(ip)294 pass1(ip)
295 register struct dinode *ip;
296 {
297 daddr_t ind1[MAXNINDIR];
298 daddr_t ind2[MAXNINDIR];
299 daddr_t db, ib;
300 register int i, j, k, siz;
301 int lbn;
302 char buf[BUFSIZ];
303
304 i = ip->di_mode & IFMT;
305 if(i == 0)
306 return;
307 switch (i) {
308 case IFCHR:
309 ncfile++;
310 return;
311 case IFBLK:
312 nbfile++;
313 return;
314 case IFDIR:
315 ndfile++;
316 break;
317 case IFREG:
318 nrfile++;
319 break;
320 case IFSOCK:
321 nsfile++;
322 break;
323 case IFLNK:
324 nlfile++;
325 break;
326 default:
327 printf("bad mode %u\n", ino);
328 return;
329 }
330 for (i = 0; i < NDADDR; i++) {
331 db = ip->di_db[i];
332 if (db == 0)
333 continue;
334 siz = dblksize(&sblock, ip, i);
335 (void)sprintf(buf, "logical data block %d", i);
336 chk(db, buf, siz);
337 if (siz == sblock.fs_bsize)
338 nblock++;
339 else
340 nfrag += howmany(siz, sblock.fs_fsize);
341 }
342 for(i = 0; i < NIADDR; i++) {
343 ib = ip->di_ib[i];
344 if (ib == 0)
345 continue;
346 if (chk(ib, "1st indirect", sblock.fs_bsize))
347 continue;
348 bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize);
349 nindir++;
350 for (j = 0; j < NINDIR(&sblock); j++) {
351 ib = ind1[j];
352 if (ib == 0)
353 continue;
354 if (i == 0) {
355 lbn = NDADDR + j;
356 siz = dblksize(&sblock, ip, lbn);
357 (void)sprintf(buf, "logical data block %d", lbn);
358 chk(ib, buf, siz);
359 if (siz == sblock.fs_bsize)
360 nblock++;
361 else
362 nfrag += howmany(siz, sblock.fs_fsize);
363 continue;
364 }
365 if (chk(ib, "2nd indirect", sblock.fs_bsize))
366 continue;
367 bread(fsbtodb(&sblock, ib), (char *)ind2,
368 sblock.fs_bsize);
369 niindir++;
370 for (k = 0; k < NINDIR(&sblock); k++) {
371 ib = ind2[k];
372 if (ib == 0)
373 continue;
374 lbn = NDADDR + NINDIR(&sblock) * (i + j) + k;
375 siz = dblksize(&sblock, ip, lbn);
376 (void)sprintf(buf, "logical data block %d", lbn);
377 chk(ib, buf, siz);
378 if (siz == sblock.fs_bsize)
379 nblock++;
380 else
381 nfrag += howmany(siz, sblock.fs_fsize);
382 }
383 }
384 }
385 }
386
chk(bno,s,size)387 chk(bno, s, size)
388 daddr_t bno;
389 char *s;
390 int size;
391 {
392 register n, cg;
393 int frags;
394
395 cg = dtog(&sblock, bno);
396 if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) {
397 printf("%ld bad; inode=%u, class=%s\n", bno, ino, s);
398 return(1);
399 }
400 frags = numfrags(&sblock, size);
401 if (frags == sblock.fs_frag) {
402 if (duped(bno, size)) {
403 printf("%ld dup block; inode=%u, class=%s\n",
404 bno, ino, s);
405 ndup += sblock.fs_frag;
406 }
407 } else {
408 for (n = 0; n < frags; n++) {
409 if (duped(bno + n, sblock.fs_fsize)) {
410 printf("%ld dup frag; inode=%u, class=%s\n",
411 bno, ino, s);
412 ndup++;
413 }
414 }
415 }
416 for (n=0; blist[n] != -1; n++)
417 if (fsblist[n] >= bno && fsblist[n] < bno + frags)
418 printf("%ld arg; frag %d of %d, inode=%u, class=%s\n",
419 blist[n], fsblist[n] - bno, frags, ino, s);
420 return(0);
421 }
422
duped(bno,size)423 duped(bno, size)
424 daddr_t bno;
425 int size;
426 {
427 if(dflg)
428 return(0);
429 if (size != sblock.fs_fsize && size != sblock.fs_bsize)
430 printf("bad size %d to duped\n", size);
431 if (size == sblock.fs_fsize) {
432 if (isset(bmap, bno))
433 return(1);
434 setbit(bmap, bno);
435 return (0);
436 }
437 if (bno % sblock.fs_frag != 0)
438 printf("bad bno %d to duped\n", bno);
439 if (isblock(&sblock, bmap, bno/sblock.fs_frag))
440 return (1);
441 setblock(&sblock, bmap, bno/sblock.fs_frag);
442 return(0);
443 }
444
getsb(fs,file)445 getsb(fs, file)
446 register struct fs *fs;
447 char *file;
448 {
449 int i, j, size;
450
451 if (bread(SBOFF, (char *)fs, SBSIZE)) {
452 printf("bad super block");
453 perror(file);
454 nerror |= 04;
455 return;
456 }
457 if (fs->fs_magic != FS_MAGIC) {
458 printf("%s: bad magic number\n", file);
459 nerror |= 04;
460 return;
461 }
462 dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
463 for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
464 size = sblock.fs_cssize - i < sblock.fs_bsize ?
465 sblock.fs_cssize - i : sblock.fs_bsize;
466 sblock.fs_csp[j] = (struct csum *)calloc(1, size);
467 bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)),
468 (char *)fs->fs_csp[j], size);
469 }
470 }
471
bread(bno,buf,cnt)472 bread(bno, buf, cnt)
473 daddr_t bno;
474 char *buf;
475 ssize_t cnt;
476 {
477 register i;
478
479 lseek(fi, (off_t)bno * dev_bsize, SEEK_SET);
480 if ((i = read(fi, buf, cnt)) != cnt) {
481 for (i = 0; i < sblock.fs_bsize; i++)
482 buf[i] = 0;
483 return (1);
484 }
485 return (0);
486 }
487
488 /*
489 * check if a block is available
490 */
491 isblock(fs, cp, h)
492 struct fs *fs;
493 unsigned char *cp;
494 int h;
495 {
496 unsigned char mask;
497
498 switch (fs->fs_frag) {
499 case 8:
500 return (cp[h] == 0xff);
501 case 4:
502 mask = 0x0f << ((h & 0x1) << 2);
503 return ((cp[h >> 1] & mask) == mask);
504 case 2:
505 mask = 0x03 << ((h & 0x3) << 1);
506 return ((cp[h >> 2] & mask) == mask);
507 case 1:
508 mask = 0x01 << (h & 0x7);
509 return ((cp[h >> 3] & mask) == mask);
510 default:
511 #ifdef STANDALONE
512 printf("isblock bad fs_frag %d\n", fs->fs_frag);
513 #else
514 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
515 #endif
516 return;
517 }
518 }
519
520 /*
521 * put a block into the map
522 */
523 setblock(fs, cp, h)
524 struct fs *fs;
525 unsigned char *cp;
526 int h;
527 {
528 switch (fs->fs_frag) {
529 case 8:
530 cp[h] = 0xff;
531 return;
532 case 4:
533 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
534 return;
535 case 2:
536 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
537 return;
538 case 1:
539 cp[h >> 3] |= (0x01 << (h & 0x7));
540 return;
541 default:
542 #ifdef STANDALONE
543 printf("setblock bad fs_frag %d\n", fs->fs_frag);
544 #else
545 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
546 #endif
547 return;
548 }
549 }
550