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 8 static char sccsid[] = "@(#)icheck.c 5.4 (Berkeley) 05/02/88"; 9 #endif not lint 10 11 /* 12 * icheck 13 */ 14 #define NB 500 15 #define MAXFN 500 16 #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 17 18 #ifndef STANDALONE 19 #include <stdio.h> 20 #endif 21 #include <sys/param.h> 22 #include <sys/inode.h> 23 #include <sys/fs.h> 24 25 union { 26 struct fs sb; 27 char pad[SBSIZE]; 28 } sbun; 29 #define sblock sbun.sb 30 31 union { 32 struct cg cg; 33 char pad[MAXBSIZE]; 34 } cgun; 35 #define cgrp cgun.cg 36 37 struct dinode itab[MAXBSIZE / sizeof(struct dinode)]; 38 39 daddr_t blist[NB]; 40 daddr_t fsblist[NB]; 41 char *bmap; 42 43 int mflg; 44 int dflg; 45 int fi; 46 ino_t ino; 47 int cginit; 48 49 ino_t nrfile; 50 ino_t ndfile; 51 ino_t nbfile; 52 ino_t ncfile; 53 ino_t nlfile; 54 ino_t nsfile; 55 56 daddr_t nblock; 57 daddr_t nfrag; 58 daddr_t nindir; 59 daddr_t niindir; 60 61 daddr_t nffree; 62 daddr_t nbfree; 63 64 daddr_t ndup; 65 66 int nerror; 67 long dev_bsize = 1; 68 69 long atol(); 70 #ifndef STANDALONE 71 char *malloc(); 72 char *calloc(); 73 #endif 74 75 main(argc, argv) 76 int argc; 77 char *argv[]; 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 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 125 check(file) 126 char *file; 127 { 128 register i, j, c; 129 daddr_t d, cgd, cbase, b; 130 long n; 131 char buf[BUFSIZ]; 132 133 fi = open(file, 0); 134 if (fi < 0) { 135 perror(file); 136 nerror |= 04; 137 return; 138 } 139 printf("%s:\n", file); 140 nrfile = 0; 141 ndfile = 0; 142 ncfile = 0; 143 nbfile = 0; 144 nlfile = 0; 145 nsfile = 0; 146 147 nblock = 0; 148 nfrag = 0; 149 nindir = 0; 150 niindir = 0; 151 152 ndup = 0; 153 #ifndef STANDALONE 154 sync(); 155 #endif 156 getsb(&sblock, file); 157 if (nerror) 158 return; 159 for (n=0; blist[n] != -1; n++) 160 fsblist[n] = dbtofsb(&sblock, blist[n]); 161 ino = 0; 162 n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short)); 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++; 171 } 172 ino = 0; 173 cginit = 1; 174 if (!dflg) { 175 for (i = 0; i < (unsigned)n; i++) 176 bmap[i] = 0; 177 for (c = 0; c < sblock.fs_ncg; c++) { 178 cgd = cgtod(&sblock, c); 179 if (c == 0) 180 d = cgbase(&sblock, c); 181 else 182 d = cgsblock(&sblock, c); 183 (void)sprintf(buf, "spare super block %d", c); 184 for (; d < cgd; d += sblock.fs_frag) 185 chk(d, buf, sblock.fs_bsize); 186 d = cgimin(&sblock, c); 187 (void)sprintf(buf, "cylinder group %d", c); 188 while (cgd < d) { 189 chk(cgd, buf, sblock.fs_bsize); 190 cgd += sblock.fs_frag; 191 } 192 d = cgdmin(&sblock, c); 193 i = INOPB(&sblock); 194 for (; cgd < d; cgd += sblock.fs_frag) { 195 (void)sprintf(buf, "inodes %d-%d", ino, ino + i); 196 chk(cgd, buf, sblock.fs_bsize); 197 ino += i; 198 } 199 if (c == 0) { 200 d += howmany(sblock.fs_cssize, sblock.fs_fsize); 201 for (; cgd < d; cgd++) 202 chk(cgd, "csum", sblock.fs_fsize); 203 } 204 } 205 } 206 ino = 0; 207 cginit = 0; 208 for (c = 0; c < sblock.fs_ncg; c++) { 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 } 218 } 219 } 220 ino = 0; 221 #ifndef STANDALONE 222 sync(); 223 #endif 224 nffree = 0; 225 nbfree = 0; 226 for (c = 0; c < sblock.fs_ncg; c++) { 227 cbase = cgbase(&sblock, c); 228 bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp, 229 sblock.fs_cgsize); 230 if (!cg_chkmagic(&cgrp)) 231 printf("cg %d: bad magic number\n", c); 232 for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 233 if (isblock(&sblock, cg_blksfree(&cgrp), 234 b / sblock.fs_frag)) { 235 nbfree++; 236 chk(cbase+b, "free block", sblock.fs_bsize); 237 } else { 238 for (d = 0; d < sblock.fs_frag; d++) 239 if (isset(cg_blksfree(&cgrp), b+d)) { 240 chk(cbase+b+d, "free frag", sblock.fs_fsize); 241 nffree++; 242 } 243 } 244 } 245 } 246 close(fi); 247 #ifndef STANDALONE 248 if (bmap) 249 free(bmap); 250 #endif 251 252 i = nrfile + ndfile + ncfile + nbfile + nlfile + nsfile; 253 #ifndef STANDALONE 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); 256 #else 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); 259 #endif 260 n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag; 261 #ifdef STANDALONE 262 printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 263 n, nindir, niindir, nblock, nfrag); 264 printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 265 nbfree, nffree); 266 #else 267 printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 268 n, nindir, niindir, nblock, nfrag); 269 printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 270 nbfree, nffree); 271 #endif 272 if(!dflg) { 273 n = 0; 274 for (d = 0; d < sblock.fs_size; d++) 275 if(!duped(d, sblock.fs_fsize)) { 276 if(mflg) 277 printf("%ld missing\n", d); 278 n++; 279 } 280 printf("missing%5ld\n", n); 281 } 282 } 283 284 pass1(ip) 285 register struct dinode *ip; 286 { 287 daddr_t ind1[MAXNINDIR]; 288 daddr_t ind2[MAXNINDIR]; 289 daddr_t db, ib; 290 register int i, j, k, siz; 291 int lbn; 292 char buf[BUFSIZ]; 293 294 i = ip->di_mode & IFMT; 295 if(i == 0) 296 return; 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; 310 case IFSOCK: 311 nsfile++; 312 break; 313 case IFLNK: 314 nlfile++; 315 break; 316 default: 317 printf("bad mode %u\n", ino); 318 return; 319 } 320 for (i = 0; i < NDADDR; i++) { 321 db = ip->di_db[i]; 322 if (db == 0) 323 continue; 324 siz = dblksize(&sblock, ip, i); 325 (void)sprintf(buf, "logical data block %d", i); 326 chk(db, buf, siz); 327 if (siz == sblock.fs_bsize) 328 nblock++; 329 else 330 nfrag += howmany(siz, sblock.fs_fsize); 331 } 332 for(i = 0; i < NIADDR; i++) { 333 ib = ip->di_ib[i]; 334 if (ib == 0) 335 continue; 336 if (chk(ib, "1st indirect", sblock.fs_bsize)) 337 continue; 338 bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); 339 nindir++; 340 for (j = 0; j < NINDIR(&sblock); j++) { 341 ib = ind1[j]; 342 if (ib == 0) 343 continue; 344 if (i == 0) { 345 lbn = NDADDR + j; 346 siz = dblksize(&sblock, ip, lbn); 347 (void)sprintf(buf, "logical data block %d", lbn); 348 chk(ib, buf, siz); 349 if (siz == sblock.fs_bsize) 350 nblock++; 351 else 352 nfrag += howmany(siz, sblock.fs_fsize); 353 continue; 354 } 355 if (chk(ib, "2nd indirect", sblock.fs_bsize)) 356 continue; 357 bread(fsbtodb(&sblock, ib), (char *)ind2, 358 sblock.fs_bsize); 359 niindir++; 360 for (k = 0; k < NINDIR(&sblock); k++) { 361 ib = ind2[k]; 362 if (ib == 0) 363 continue; 364 lbn = NDADDR + NINDIR(&sblock) * (i + j) + k; 365 siz = dblksize(&sblock, ip, lbn); 366 (void)sprintf(buf, "logical data block %d", lbn); 367 chk(ib, buf, siz); 368 if (siz == sblock.fs_bsize) 369 nblock++; 370 else 371 nfrag += howmany(siz, sblock.fs_fsize); 372 } 373 } 374 } 375 } 376 377 chk(bno, s, size) 378 daddr_t bno; 379 char *s; 380 int size; 381 { 382 register n, cg; 383 int frags; 384 385 cg = dtog(&sblock, bno); 386 if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) { 387 printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 388 return(1); 389 } 390 frags = numfrags(&sblock, size); 391 if (frags == sblock.fs_frag) { 392 if (duped(bno, size)) { 393 printf("%ld dup block; inode=%u, class=%s\n", 394 bno, ino, s); 395 ndup += sblock.fs_frag; 396 } 397 } else { 398 for (n = 0; n < frags; n++) { 399 if (duped(bno + n, sblock.fs_fsize)) { 400 printf("%ld dup frag; inode=%u, class=%s\n", 401 bno, ino, s); 402 ndup++; 403 } 404 } 405 } 406 for (n=0; blist[n] != -1; n++) 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); 410 return(0); 411 } 412 413 duped(bno, size) 414 daddr_t bno; 415 int size; 416 { 417 if(dflg) 418 return(0); 419 if (size != sblock.fs_fsize && size != sblock.fs_bsize) 420 printf("bad size %d to duped\n", size); 421 if (size == sblock.fs_fsize) { 422 if (isset(bmap, bno)) 423 return(1); 424 setbit(bmap, bno); 425 return (0); 426 } 427 if (bno % sblock.fs_frag != 0) 428 printf("bad bno %d to duped\n", bno); 429 if (isblock(&sblock, bmap, bno/sblock.fs_frag)) 430 return (1); 431 setblock(&sblock, bmap, bno/sblock.fs_frag); 432 return(0); 433 } 434 435 getsb(fs, file) 436 register struct fs *fs; 437 char *file; 438 { 439 int i, j, size; 440 441 if (bread(SBOFF, fs, SBSIZE)) { 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 } 452 dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 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); 459 } 460 } 461 462 bread(bno, buf, cnt) 463 daddr_t bno; 464 char *buf; 465 { 466 register i; 467 468 lseek(fi, bno * dev_bsize, 0); 469 if ((i = read(fi, buf, cnt)) != cnt) { 470 for(i=0; i<sblock.fs_bsize; i++) 471 buf[i] = 0; 472 return (1); 473 } 474 return (0); 475 } 476 477 /* 478 * check if a block is available 479 */ 480 isblock(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: 500 #ifdef STANDALONE 501 printf("isblock bad fs_frag %d\n", fs->fs_frag); 502 #else 503 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 504 #endif 505 return; 506 } 507 } 508 509 /* 510 * put a block into the map 511 */ 512 setblock(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: 531 #ifdef STANDALONE 532 printf("setblock bad fs_frag %d\n", fs->fs_frag); 533 #else 534 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 535 #endif 536 return; 537 } 538 } 539