1 static char *sccsid = "@(#)icheck.c 1.21 (Berkeley) 03/23/82"; 2 3 /* 4 * icheck 5 */ 6 #define NB 500 7 #define MAXFN 500 8 #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 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[MAXBSIZE]; 20 } sbun; 21 #define sblock sbun.sb 22 23 union { 24 struct cg cg; 25 char pad[MAXBSIZE]; 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 sflg; 35 int dflg; 36 int fi; 37 ino_t ino; 38 int cginit; 39 40 ino_t nrfile; 41 ino_t ndfile; 42 ino_t nbfile; 43 ino_t ncfile; 44 ino_t nlfile; 45 46 daddr_t nblock; 47 daddr_t nfrag; 48 daddr_t nindir; 49 daddr_t niindir; 50 51 daddr_t nffree; 52 daddr_t nbfree; 53 54 daddr_t ndup; 55 56 int nerror; 57 58 extern int inside[], around[]; 59 extern unsigned char *fragtbl[]; 60 61 long atol(); 62 #ifndef STANDALONE 63 char *malloc(); 64 char *calloc(); 65 #endif 66 67 main(argc, argv) 68 int argc; 69 char *argv[]; 70 { 71 register i; 72 long n; 73 74 blist[0] = -1; 75 #ifndef STANDALONE 76 while (--argc) { 77 argv++; 78 if (**argv=='-') 79 switch ((*argv)[1]) { 80 case 'd': 81 dflg++; 82 continue; 83 84 case 'm': 85 mflg++; 86 continue; 87 88 case 's': 89 sflg++; 90 continue; 91 92 case 'b': 93 for(i=0; i<NB; i++) { 94 n = atol(argv[1]); 95 if(n == 0) 96 break; 97 blist[i] = n; 98 argv++; 99 argc--; 100 } 101 blist[i] = -1; 102 continue; 103 104 default: 105 printf("Bad flag\n"); 106 } 107 check(*argv); 108 } 109 #else 110 { 111 static char fname[128]; 112 113 printf("File: "); 114 gets(fname); 115 check(fname); 116 } 117 #endif 118 return(nerror); 119 } 120 121 check(file) 122 char *file; 123 { 124 register i, j, c; 125 daddr_t d, cgd, cbase, b; 126 long n; 127 128 fi = open(file, sflg ? 2 : 0); 129 if (fi < 0) { 130 perror(file); 131 nerror |= 04; 132 return; 133 } 134 printf("%s:\n", file); 135 nrfile = 0; 136 ndfile = 0; 137 ncfile = 0; 138 nbfile = 0; 139 nlfile = 0; 140 141 nblock = 0; 142 nfrag = 0; 143 nindir = 0; 144 niindir = 0; 145 146 ndup = 0; 147 #ifndef STANDALONE 148 sync(); 149 #endif 150 getsb(&sblock, file); 151 if (nerror) 152 return; 153 ino = 0; 154 n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short)); 155 #ifdef STANDALONE 156 bmap = NULL; 157 #else 158 bmap = malloc((unsigned)n); 159 #endif 160 if (bmap==NULL) { 161 printf("Not enough core; duplicates unchecked\n"); 162 dflg++; 163 if (sflg) { 164 printf("No Updates\n"); 165 sflg = 0; 166 } 167 } 168 ino = 0; 169 cginit = 1; 170 if(!dflg) { 171 for (i=0; i<(unsigned)n; i++) 172 bmap[i] = 0; 173 for (c=0; c < sblock.fs_ncg; c++) { 174 cgd = cgtod(&sblock, c); 175 for (d = cgbase(&sblock, c); d < cgd; d += sblock.fs_frag) 176 chk(d, "badcg", sblock.fs_bsize); 177 d = cgimin(&sblock, c); 178 while (cgd < d) { 179 chk(cgd, "cg", sblock.fs_bsize); 180 cgd += sblock.fs_frag; 181 } 182 d = cgdmin(&sblock, c); 183 for (; cgd < d; cgd += sblock.fs_frag) 184 chk(cgd, "inode", sblock.fs_bsize); 185 if (c == 0) { 186 d += howmany(sblock.fs_cssize, sblock.fs_bsize) 187 * sblock.fs_frag; 188 for (; cgd < d; cgd += sblock.fs_frag) 189 chk(cgd, "csum", sblock.fs_bsize); 190 } 191 } 192 } 193 cginit = 0; 194 for (c = 0; c < sblock.fs_ncg; c++) { 195 bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 196 sblock.fs_ipg * sizeof (struct dinode)); 197 for (j=0; j < sblock.fs_ipg; j++) { 198 pass1(&itab[j]); 199 ino++; 200 } 201 } 202 ino = 0; 203 #ifndef STANDALONE 204 sync(); 205 #endif 206 if (sflg) { 207 makecg(); 208 close(fi); 209 #ifndef STANDALONE 210 if (bmap) 211 free(bmap); 212 #endif 213 return; 214 } 215 nffree = 0; 216 nbfree = 0; 217 for (c = 0; c < sblock.fs_ncg; c++) { 218 cbase = cgbase(&sblock, c); 219 bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp, 220 sblock.fs_cgsize); 221 for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 222 if (isblock(&sblock, cgrp.cg_free, 223 b / sblock.fs_frag)) { 224 nbfree++; 225 chk(cbase+b, "block", sblock.fs_bsize); 226 } else { 227 for (d = 0; d < sblock.fs_frag; d++) 228 if (isset(cgrp.cg_free, b+d)) { 229 chk(cbase+b+d, "frag", sblock.fs_fsize); 230 nffree++; 231 } 232 } 233 } 234 } 235 close(fi); 236 #ifndef STANDALONE 237 if (bmap) 238 free(bmap); 239 #endif 240 241 i = nrfile + ndfile + ncfile + nbfile + nlfile; 242 #ifndef STANDALONE 243 printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n", 244 i, nrfile, ndfile, nbfile, ncfile, nlfile); 245 #else 246 printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u)\n", 247 i, nrfile, ndfile, nbfile, ncfile, nlfile); 248 #endif 249 n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag; 250 #ifdef STANDALONE 251 printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 252 n, nindir, niindir, nblock, nfrag); 253 printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 254 nbfree, nffree); 255 #else 256 printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 257 n, nindir, niindir, nblock, nfrag); 258 printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 259 nbfree, nffree); 260 #endif 261 if(!dflg) { 262 n = 0; 263 for (d = 0; d < sblock.fs_size; d++) 264 if(!duped(d, sblock.fs_fsize)) { 265 if(mflg) 266 printf("%ld missing\n", d); 267 n++; 268 } 269 printf("missing%5ld\n", n); 270 } 271 } 272 273 pass1(ip) 274 register struct dinode *ip; 275 { 276 daddr_t ind1[MAXNINDIR]; 277 daddr_t ind2[MAXNINDIR]; 278 daddr_t db, ib; 279 register int i, j, k, siz; 280 281 i = ip->di_mode & IFMT; 282 if(i == 0) 283 return; 284 switch (i) { 285 case IFCHR: 286 ncfile++; 287 return; 288 case IFBLK: 289 nbfile++; 290 return; 291 case IFDIR: 292 ndfile++; 293 break; 294 case IFREG: 295 nrfile++; 296 break; 297 case IFLNK: 298 nlfile++; 299 break; 300 default: 301 printf("bad mode %u\n", ino); 302 return; 303 } 304 for (i = 0; i < NDADDR; i++) { 305 db = ip->di_db[i]; 306 if (db == 0) 307 continue; 308 siz = dblksize(&sblock, ip, i); 309 chk(db, "data (block)", siz); 310 if (siz == sblock.fs_bsize) 311 nblock++; 312 else 313 nfrag += howmany(siz, sblock.fs_fsize); 314 } 315 for(i = 0; i < NIADDR; i++) { 316 ib = ip->di_ib[i]; 317 if(ib == 0) 318 continue; 319 if (chk(ib, "1st indirect", sblock.fs_bsize)) 320 continue; 321 bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); 322 nindir++; 323 for (j = 0; j < NINDIR(&sblock); j++) { 324 ib = ind1[j]; 325 if (ib == 0) 326 continue; 327 if (i == 0) { 328 siz = dblksize(&sblock, ip, NDADDR + j); 329 chk(ib, "data (large)", siz); 330 if (siz == sblock.fs_bsize) 331 nblock++; 332 else 333 nfrag += howmany(siz, sblock.fs_fsize); 334 continue; 335 } 336 if (chk(ib, "2nd indirect", sblock.fs_bsize)) 337 continue; 338 bread(fsbtodb(&sblock, ib), (char *)ind2, 339 sblock.fs_bsize); 340 niindir++; 341 for (k = 0; k < NINDIR(&sblock); k++) { 342 ib = ind2[k]; 343 if (ib == 0) 344 continue; 345 siz = dblksize(&sblock, ip, 346 NDADDR + NINDIR(&sblock) * (i + j) + k); 347 chk(ib, "data (huge)", siz); 348 if (siz == sblock.fs_bsize) 349 nblock++; 350 else 351 nfrag += howmany(siz, sblock.fs_fsize); 352 } 353 } 354 } 355 } 356 357 chk(bno, s, size) 358 daddr_t bno; 359 char *s; 360 int size; 361 { 362 register n, cg; 363 int frags; 364 365 cg = dtog(&sblock, bno); 366 if (cginit==0 && 367 bno<cgdmin(&sblock, cg) || bno >= sblock.fs_frag * sblock.fs_size) { 368 printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 369 return(1); 370 } 371 if (size == sblock.fs_bsize) { 372 if (duped(bno, size)) { 373 printf("%ld dup block; inode=%u, class=%s\n", 374 bno, ino, s); 375 ndup += sblock.fs_frag; 376 } 377 } else { 378 frags = numfrags(&sblock, size); 379 for (n = 0; n < frags; n++) { 380 if (duped(bno + n, sblock.fs_fsize)) { 381 printf("%ld dup frag; inode=%u, class=%s\n", 382 bno, ino, s); 383 ndup++; 384 } 385 } 386 } 387 for (n=0; blist[n] != -1; n++) 388 if (bno == blist[n]) 389 printf("%ld arg; inode=%u, class=%s\n", bno, ino, s); 390 return(0); 391 } 392 393 duped(bno, size) 394 daddr_t bno; 395 int size; 396 { 397 if(dflg) 398 return(0); 399 if (size != sblock.fs_fsize && size != sblock.fs_bsize) 400 printf("bad size %d to duped\n", size); 401 if (size == sblock.fs_fsize) { 402 if (isset(bmap, bno)) 403 return(1); 404 setbit(bmap, bno); 405 return (0); 406 } 407 if (bno % sblock.fs_frag != 0) 408 printf("bad bno %d to duped\n", bno); 409 if (isblock(&sblock, bmap, bno/sblock.fs_frag)) 410 return (1); 411 setblock(&sblock, bmap, bno/sblock.fs_frag); 412 return(0); 413 } 414 415 makecg() 416 { 417 int c, blk; 418 daddr_t dbase, d, dmin, dmax; 419 long i, j, s; 420 register struct csum *cs; 421 register struct dinode *dp; 422 423 sblock.fs_cstotal.cs_nbfree = 0; 424 sblock.fs_cstotal.cs_nffree = 0; 425 sblock.fs_cstotal.cs_nifree = 0; 426 sblock.fs_cstotal.cs_ndir = 0; 427 for (c = 0; c < sblock.fs_ncg; c++) { 428 dbase = cgbase(&sblock, c); 429 dmax = dbase + sblock.fs_fpg; 430 if (dmax > sblock.fs_size) { 431 for ( ; dmax >= sblock.fs_size; dmax--) 432 clrbit(cgrp.cg_free, dmax - dbase); 433 dmax++; 434 } 435 dmin = sblock.fs_dblkno; 436 cs = &sblock.fs_cs(&sblock, c); 437 cgrp.cg_time = time(0); 438 cgrp.cg_magic = CG_MAGIC; 439 cgrp.cg_cgx = c; 440 cgrp.cg_ncyl = sblock.fs_cpg; 441 cgrp.cg_niblk = sblock.fs_ipg; 442 cgrp.cg_ndblk = dmax - dbase; 443 cgrp.cg_cs.cs_ndir = 0; 444 cgrp.cg_cs.cs_nffree = 0; 445 cgrp.cg_cs.cs_nbfree = 0; 446 cgrp.cg_cs.cs_nifree = 0; 447 cgrp.cg_rotor = dmin; 448 cgrp.cg_frotor = dmin; 449 cgrp.cg_irotor = 0; 450 for (i = 0; i < sblock.fs_frag; i++) 451 cgrp.cg_frsum[i] = 0; 452 bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 453 sblock.fs_ipg * sizeof(struct dinode)); 454 for (i = 0; i < sblock.fs_ipg; i++) { 455 cgrp.cg_cs.cs_nifree++; 456 clrbit(cgrp.cg_iused, i); 457 dp = &itab[i]; 458 if ((dp->di_mode & IFMT) != 0) { 459 if ((dp->di_mode & IFMT) == IFDIR) 460 cgrp.cg_cs.cs_ndir++; 461 cgrp.cg_cs.cs_nifree--; 462 setbit(cgrp.cg_iused, i); 463 continue; 464 } 465 } 466 while (i < MAXIPG) { 467 clrbit(cgrp.cg_iused, i); 468 i++; 469 } 470 if (c == 0) 471 for (i = 0; i < ROOTINO; i++) { 472 setbit(cgrp.cg_iused, i); 473 cgrp.cg_cs.cs_nifree--; 474 } 475 for (s = 0; s < MAXCPG; s++) { 476 cgrp.cg_btot[s] = 0; 477 for (i = 0; i < NRPOS; i++) 478 cgrp.cg_b[s][i] = 0; 479 } 480 if (c == 0) { 481 dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) * 482 sblock.fs_frag; 483 } 484 for (d = 0; d < dmin; d++) 485 clrbit(cgrp.cg_free, d); 486 for (; (d + sblock.fs_frag) <= dmax - dbase; d += sblock.fs_frag) { 487 j = 0; 488 for (i = 0; i < sblock.fs_frag; i++) { 489 if (!isset(bmap, dbase+d+i)) { 490 setbit(cgrp.cg_free, d+i); 491 j++; 492 } else 493 clrbit(cgrp.cg_free, d+i); 494 } 495 if (j == sblock.fs_frag) { 496 cgrp.cg_cs.cs_nbfree++; 497 cgrp.cg_btot[cbtocylno(&sblock, d)]++; 498 cgrp.cg_b[cbtocylno(&sblock, d)] 499 [cbtorpos(&sblock, d)]++; 500 } else if (j > 0) { 501 cgrp.cg_cs.cs_nffree += j; 502 blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) & 503 (0xff >> (NBBY - sblock.fs_frag))); 504 fragacct(&sblock, blk, cgrp.cg_frsum, 1); 505 } 506 } 507 for (j = d; d < dmax - dbase; d++) { 508 if (!isset(bmap, dbase+d)) { 509 setbit(cgrp.cg_free, d); 510 cgrp.cg_cs.cs_nffree++; 511 } else 512 clrbit(cgrp.cg_free, d); 513 } 514 if (j != d) { 515 blk = ((cgrp.cg_free[j / NBBY] >> (j % NBBY)) & 516 (0xff >> (NBBY - sblock.fs_frag))); 517 fragacct(&sblock, blk, cgrp.cg_frsum, 1); 518 } 519 for (; d < MAXBPG(&sblock); d++) 520 clrbit(cgrp.cg_free, d); 521 sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree; 522 sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree; 523 sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree; 524 sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir; 525 *cs = cgrp.cg_cs; 526 bwrite(fsbtodb(&sblock, cgtod(&sblock, c)), &cgrp, 527 sblock.fs_cgsize); 528 } 529 for (i = 0; i < howmany(sblock.fs_cssize, sblock.fs_bsize); i++) { 530 bwrite(fsbtodb(&sblock, 531 sblock.fs_csaddr + (i * sblock.fs_frag)), 532 (char *)sblock.fs_csp[i], sblock.fs_bsize); 533 } 534 sblock.fs_ronly = 0; 535 sblock.fs_fmod = 0; 536 bwrite(SBLOCK, (char *)&sblock, SBSIZE); 537 } 538 539 /* 540 * update the frsum fields to reflect addition or deletion 541 * of some frags 542 */ 543 fragacct(fs, fragmap, fraglist, cnt) 544 struct fs *fs; 545 int fragmap; 546 long fraglist[]; 547 int cnt; 548 { 549 int inblk; 550 register int field, subfield; 551 register int siz, pos; 552 553 inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1); 554 fragmap <<= 1; 555 for (siz = 1; siz < fs->fs_frag; siz++) { 556 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 557 continue; 558 field = around[siz]; 559 subfield = inside[siz]; 560 for (pos = siz; pos <= fs->fs_frag; pos++) { 561 if ((fragmap & field) == subfield) { 562 fraglist[siz] += cnt; 563 pos += siz; 564 field <<= siz; 565 subfield <<= siz; 566 } 567 field <<= 1; 568 subfield <<= 1; 569 } 570 } 571 } 572 573 getsb(fs, file) 574 register struct fs *fs; 575 char *file; 576 { 577 int i; 578 579 if (bread(SBLOCK, fs, SBSIZE)) { 580 printf("bad super block"); 581 perror(file); 582 nerror |= 04; 583 return; 584 } 585 if (fs->fs_magic != FS_MAGIC) { 586 printf("%s: bad magic number\n", file); 587 nerror |= 04; 588 return; 589 } 590 for (i = 0; i < howmany(fs->fs_cssize, fs->fs_bsize); i++) { 591 fs->fs_csp[i] = (struct csum *)calloc(1, fs->fs_bsize); 592 bread(fsbtodb(fs, fs->fs_csaddr + (i * fs->fs_frag)), 593 (char *)fs->fs_csp[i], fs->fs_bsize); 594 } 595 } 596 597 bwrite(blk, buf, size) 598 char *buf; 599 daddr_t blk; 600 register size; 601 { 602 if (lseek(fi, blk * DEV_BSIZE, 0) < 0) { 603 perror("FS SEEK"); 604 return(1); 605 } 606 if (write(fi, buf, size) != size) { 607 perror("FS WRITE"); 608 return(1); 609 } 610 return (0); 611 } 612 613 bread(bno, buf, cnt) 614 daddr_t bno; 615 char *buf; 616 { 617 register i; 618 619 lseek(fi, bno * DEV_BSIZE, 0); 620 if ((i = read(fi, buf, cnt)) != cnt) { 621 if (sflg) { 622 printf("No Update\n"); 623 sflg = 0; 624 } 625 for(i=0; i<sblock.fs_bsize; i++) 626 buf[i] = 0; 627 return (1); 628 } 629 return (0); 630 } 631 632 /* 633 * block operations 634 */ 635 636 isblock(fs, cp, h) 637 struct fs *fs; 638 unsigned char *cp; 639 int h; 640 { 641 unsigned char mask; 642 643 switch (fs->fs_frag) { 644 case 8: 645 return (cp[h] == 0xff); 646 case 4: 647 mask = 0x0f << ((h & 0x1) << 2); 648 return ((cp[h >> 1] & mask) == mask); 649 case 2: 650 mask = 0x03 << ((h & 0x3) << 1); 651 return ((cp[h >> 2] & mask) == mask); 652 case 1: 653 mask = 0x01 << (h & 0x7); 654 return ((cp[h >> 3] & mask) == mask); 655 default: 656 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 657 return; 658 } 659 } 660 661 setblock(fs, cp, h) 662 struct fs *fs; 663 unsigned char *cp; 664 int h; 665 { 666 switch (fs->fs_frag) { 667 case 8: 668 cp[h] = 0xff; 669 return; 670 case 4: 671 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 672 return; 673 case 2: 674 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 675 return; 676 case 1: 677 cp[h >> 3] |= (0x01 << (h & 0x7)); 678 return; 679 default: 680 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 681 return; 682 } 683 } 684