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