1 static char *sccsid = "@(#)icheck.c 1.1 (Berkeley) 08/26/81"; 2 /* 3 * icheck 4 */ 5 #define NB 500 6 #define BITS 8 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/ino.h" 15 #include "../h/fs.h" 16 17 #define setbit(a, i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) 18 #define clrbit(a, i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) 19 #define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) 20 21 union { 22 struct fs sb; 23 char pad[BSIZE]; 24 } sbun; 25 #define sblock sbun.sb 26 27 union { 28 struct cg cg; 29 char pad[BSIZE]; 30 } cgun; 31 #define cgrp cgun.cg 32 33 struct dinode itab[MAXIPG]; 34 daddr_t iaddr[NDADDR+NIADDR]; 35 daddr_t blist[NB]; 36 char *bmap; 37 38 int sflg; 39 int mflg; 40 int dflg; 41 int fi; 42 ino_t ino; 43 int cginit; 44 45 ino_t nrfile; 46 ino_t ndfile; 47 ino_t nbfile; 48 ino_t ncfile; 49 ino_t nmcfile; 50 51 daddr_t nblock; 52 daddr_t nfrag; 53 long szfrag; 54 daddr_t nindir; 55 long szindir; 56 daddr_t niindir; 57 58 daddr_t nffree; 59 long szffree; 60 daddr_t nbfree; 61 62 daddr_t ndup; 63 64 int nerror; 65 66 long atol(); 67 daddr_t alloc(); 68 #ifndef STANDALONE 69 char *malloc(); 70 #endif 71 72 main(argc, argv) 73 char *argv[]; 74 { 75 register i; 76 long n; 77 78 blist[0] = -1; 79 #ifndef STANDALONE 80 while (--argc) { 81 argv++; 82 if (**argv=='-') 83 switch ((*argv)[1]) { 84 case 'd': 85 dflg++; 86 continue; 87 88 case 'm': 89 mflg++; 90 continue; 91 92 case 's': 93 sflg++; 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 132 fi = open(file, sflg?2:0); 133 if (fi < 0) { 134 printf("cannot open %s\n", file); 135 nerror |= 04; 136 return; 137 } 138 printf("%s:\n", file); 139 nrfile = 0; 140 ndfile = 0; 141 ncfile = 0; 142 nbfile = 0; 143 nmcfile = 0; 144 145 nblock = 0; 146 nfrag = 0; 147 szfrag = 0; 148 nindir = 0; 149 szindir = 0; 150 niindir = 0; 151 152 ndup = 0; 153 #ifndef STANDALONE 154 sync(); 155 #endif 156 bread(SBLOCK, (char *)&sblock, BSIZE); 157 if (sblock.fs_magic != FS_MAGIC) { 158 printf("%s: bad magic number\n", file); 159 nerror |= 04; 160 return; 161 } 162 sblock.fs_cs = 163 (struct csum *)calloc(howmany(cssize(&sblock), BSIZE), BSIZE); 164 lseek(fi, csaddr(&sblock)*FSIZE, 0); 165 read(fi, (char *)sblock.fs_cs, cssize(&sblock)); 166 ino = 0; 167 n = (sblock.fs_size*FRAG + BITS-1) / BITS; 168 #ifdef STANDALONE 169 bmap = NULL; 170 #else 171 bmap = malloc((unsigned)n); 172 #endif 173 if (bmap==NULL) { 174 printf("Not enough core; duplicates unchecked\n"); 175 dflg++; 176 sflg = 0; 177 } 178 ino = 0; 179 cginit = 1; 180 if(!dflg) { 181 for (i=0; i<(unsigned)n; i++) 182 bmap[i] = 0; 183 for (c=0; c < sblock.fs_ncg; c++) { 184 cgd = cgtod(c, &sblock); 185 for (d = cgbase(c, &sblock); d < cgd; d++) 186 chk(d, "badcg"); 187 d = cgimin(c, &sblock); 188 while (cgd < d) { 189 chk(cgd, "cg"); 190 cgd++; 191 } 192 d = cgdmin(c, &sblock); 193 for (; cgd < d; cgd++) 194 chk(cgd, "inode"); 195 if (c == 0) { 196 d += howmany(cssize(&sblock), BSIZE) * FRAG; 197 for (; cgd < d; cgd++) 198 chk(cgd, "csum"); 199 } 200 } 201 } 202 cginit = 0; 203 for (c = 0; c < sblock.fs_ncg; c++) { 204 bread(cgimin(c,&sblock), (char *)itab, 205 sblock.fs_ipg * sizeof (struct dinode)); 206 for (j=0; j < sblock.fs_ipg; j++) { 207 pass1(&itab[j]); 208 ino++; 209 } 210 } 211 ino = 0; 212 #ifndef STANDALONE 213 sync(); 214 #endif 215 bread(SBLOCK, (char *)&sblock, sizeof(sblock)); 216 if (sflg) { 217 makecg(); 218 close(fi); 219 #ifndef STANDALONE 220 if (bmap) 221 free(bmap); 222 #endif 223 return; 224 } 225 nffree = 0; 226 szffree = 0; 227 nbfree = 0; 228 for (c = 0; c < sblock.fs_ncg; c++) { 229 cbase = cgbase(c,&sblock); 230 bread(cgtod(c,&sblock), (char *)&cgrp, sblock.fs_cgsize); 231 for (b = 0; b < sblock.fs_fpg; b += FRAG) { 232 if (isblock(cgrp.cg_free, b / FRAG)) { 233 nbfree++; 234 for (d = 0; d < FRAG; d++) 235 chk(cbase+b+d, "block"); 236 } else { 237 for (d = 0; d < FRAG; d++) 238 if (isset(cgrp.cg_free, b+d)) { 239 chk(cbase+b+d, "frag"); 240 nffree++; 241 szffree++; 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 + nmcfile; 253 #ifndef STANDALONE 254 printf("files %6u (r=%u,d=%u,b=%u,c=%u,mc=%u)\n", 255 i, nrfile, ndfile, nbfile, ncfile, nmcfile); 256 #else 257 printf("files %u (r=%u,d=%u,b=%u,c=%u,mc=%u)\n", 258 i, nrfile, ndfile, nbfile, ncfile, nmcfile); 259 #endif 260 n = (nblock + niindir) * FRAG + szfrag + szindir; 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", szffree + 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", szffree + 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)) { 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[NINDIR]; 288 daddr_t ind2[NINDIR]; 289 register i, j; 290 int k, l, sz, ni, nib, ndb; 291 292 i = ip->di_mode & IFMT; 293 if(i == 0) { 294 sblock.fs_nifree++; 295 return; 296 } 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 default: 311 printf("bad mode %u\n", ino); 312 return; 313 } 314 l3tol(iaddr, ip->di_addr, NDADDR+NIADDR); 315 ndb = howmany(ip->di_size, BSIZE)-1; 316 for(i=0; i<NDADDR; i++) { 317 if(iaddr[i] == 0) 318 continue; 319 if (i==ndb && (ip->di_size&BMASK)) { 320 sz = howmany(ip->di_size - i * BSIZE, FSIZE); 321 for (l = 0; l < sz; l++) 322 chk(iaddr[i]+l, "data (frag)"); 323 szfrag += sz; 324 nfrag++; 325 } else { 326 for (l = 0; l < FRAG; l++) 327 chk(iaddr[i]+l, "data (block)"); 328 nblock++; 329 } 330 } 331 for(i=NDADDR; i<NDADDR+NIADDR;i++) { 332 if(iaddr[i] == 0) 333 continue; 334 nindir++; 335 if (i==NDADDR) { 336 sz = howmany((ip->di_size-NDADDR*BSIZE), 337 (NINDIR/FRAG) * BSIZE); 338 if (sz > FRAG) 339 sz = FRAG; 340 } else 341 sz = FRAG; 342 for (j = 0; j < FRAG; j++) 343 if (chk(iaddr[i]+j, "1st indirect")) 344 continue; 345 bread(iaddr[i], (char *)ind1, sz*FSIZE); 346 nib = sz * (NINDIR/FRAG); 347 for(j=0; j<nib; j++) { 348 if(ind1[j] == 0) 349 continue; 350 if(i == NDADDR) { 351 for (l = 0; l < FRAG; l++) 352 chk(ind1[j]+l, "data (large)"); 353 nblock++; 354 continue; 355 } 356 niindir++; 357 for (l = 0; l < FRAG; l++) 358 if(chk(ind1[j], "2nd indirect")) 359 goto skip; 360 bread(ind1[j], (char *)ind2, BSIZE); 361 for(k=0; k<NINDIR; k++) { 362 if(ind2[k] == 0) 363 continue; 364 for (l = 0; l < FRAG; l++) 365 chk(ind1[j]+l, "data (huge)"); 366 nblock++; 367 continue; 368 } 369 skip: 370 ; 371 } 372 } 373 } 374 375 chk(bno, s) 376 daddr_t bno; 377 char *s; 378 { 379 register n, cg; 380 381 cg = dtog(bno, &sblock); 382 if (cginit==0 && bno<cgdmin(cg,&sblock) || bno>=FRAG*sblock.fs_size) { 383 printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 384 return(1); 385 } 386 if (duped(bno)) { 387 printf("%ld dup; inode=%u, class=%s\n", bno, ino, s); 388 ndup++; 389 } 390 for (n=0; blist[n] != -1; n++) 391 if (bno == blist[n]) 392 printf("%ld arg; inode=%u, class=%s\n", bno, ino, s); 393 return(0); 394 } 395 396 duped(bno) 397 daddr_t bno; 398 { 399 daddr_t d; 400 register m, n; 401 402 if(dflg) 403 return(0); 404 m = 1 << (bno%BITS); 405 n = (bno/BITS); 406 if(bmap[n] & m) 407 return(1); 408 bmap[n] |= m; 409 return(0); 410 } 411 412 bread(bno, buf, cnt) 413 daddr_t bno; 414 char *buf; 415 { 416 register i; 417 418 lseek(fi, bno*FSIZE, 0); 419 if ((i = read(fi, buf, cnt)) != cnt) { 420 if (sflg) { 421 printf("No update\n"); 422 sflg = 0; 423 } 424 for(i=0; i<BSIZE; i++) 425 buf[i] = 0; 426 } 427 } 428 429 bwrite(bno, buf, cnt) 430 daddr_t bno; 431 char *buf; 432 { 433 register i; 434 435 lseek(fi, bno*FSIZE, 0); 436 if (write(fi, buf, cnt) != cnt) 437 printf("write error %d\n", tell(fi)/BSIZE); 438 } 439 440 makecg() 441 { 442 int c; 443 daddr_t dbase, d, dmin, dmax; 444 long i, j, s; 445 register struct csum *cs; 446 447 sblock.fs_nbfree = 0; 448 sblock.fs_nffree = 0; 449 for (c = 0; c < sblock.fs_ncg; c++) { 450 bread(cgimin(c,&sblock), (char *)itab, 451 sblock.fs_ipg * sizeof (struct dinode)); 452 dbase = cgbase(c, &sblock); 453 dmax = dbase + sblock.fs_fpg; 454 if (dmax > sblock.fs_size) 455 dmax = sblock.fs_size; 456 cs = &sblock.fs_cs[c]; 457 cgrp.cg_time = time(0); 458 cgrp.cg_magic = CG_MAGIC; 459 cgrp.cg_cgx = c; 460 cgrp.cg_ncyl = sblock.fs_cpg; 461 cgrp.cg_niblk = sblock.fs_ipg; 462 cgrp.cg_ndblk = dmax - dbase; 463 cgrp.cg_ndir = 0; 464 cgrp.cg_nffree = 0; 465 cgrp.cg_nbfree = 0; 466 cgrp.cg_nifree = 0; 467 for (i = 0; i < sblock.fs_ipg; i++) 468 switch (itab[i].di_mode&IFMT) { 469 470 case 0: 471 cgrp.cg_nifree++; 472 clrbit(cgrp.cg_iused, i); 473 continue; 474 475 case IFDIR: 476 cgrp.cg_ndir++; 477 /* fall into ... */ 478 479 default: 480 setbit(cgrp.cg_iused, i); 481 continue; 482 } 483 while (i < MAXIPG) { 484 clrbit(cgrp.cg_iused, i); 485 i++; 486 } 487 for (s = 0; s < MAXCPG; s++) 488 for (i = 0; i < NRPOS; i++) 489 cgrp.cg_b[s][i] = 0; 490 dmin = cgdmin(c, &sblock) - dbase; 491 if (c == 0) 492 dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 493 for (d = 0; d < dmin; d++) 494 clrbit(cgrp.cg_free, d); 495 #define getbmap(i) isset(bmap, i) 496 for (; (d + FRAG) <= dmax - dbase; d += FRAG) { 497 j = 0; 498 for (i = 0; i < FRAG; i++) { 499 if (!getbmap(dbase+d+i)) { 500 setbit(cgrp.cg_free, d+i); 501 j++; 502 } else 503 clrbit(cgrp.cg_free, d+i); 504 } 505 if (j == FRAG) { 506 cgrp.cg_nbfree++; 507 s = d * NSPF; 508 cgrp.cg_b[s/sblock.fs_spc] 509 [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 510 } else 511 cgrp.cg_nffree += j; 512 } 513 for (; d < dmax - dbase; d++) { 514 if (!getbmap(dbase+d)) { 515 setbit(cgrp.cg_free, d); 516 cgrp.cg_nffree++; 517 } else 518 clrbit(cgrp.cg_free, d); 519 } 520 for (; d < MAXBPG; d++) 521 clrbit(cgrp.cg_free, d); 522 sblock.fs_nffree += cgrp.cg_nffree; 523 sblock.fs_nbfree += cgrp.cg_nbfree; 524 cs->cs_ndir = cgrp.cg_ndir; 525 cs->cs_nifree = cgrp.cg_nifree; 526 cs->cs_nbfree = cgrp.cg_nbfree; 527 bwrite(cgtod(c, &sblock), (char *)&cgrp, sblock.fs_cgsize); 528 } 529 sblock.fs_ronly = 0; 530 sblock.fs_fmod = 0; 531 bwrite(SBLOCK, (char *)&sblock, sizeof (sblock)); 532 lseek(fi, csaddr(&sblock)*FSIZE, 0); 533 if (write(fi,(char *)sblock.fs_cs,cssize(&sblock)) != cssize(&sblock)) 534 printf("write error %d\n", tell(fi)/BSIZE); 535 } 536