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