1 static char *sccsid = "@(#)icheck.c 1.3 (Berkeley) 08/28/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/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 sflg; 33 int mflg; 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 long szfrag; 48 daddr_t nindir; 49 long szindir; 50 daddr_t niindir; 51 52 daddr_t nffree; 53 long szffree; 54 daddr_t nbfree; 55 56 daddr_t ndup; 57 58 int nerror; 59 60 long atol(); 61 daddr_t alloc(); 62 #ifndef STANDALONE 63 char *malloc(); 64 #endif 65 66 main(argc, argv) 67 char *argv[]; 68 { 69 register i; 70 long n; 71 72 blist[0] = -1; 73 #ifndef STANDALONE 74 while (--argc) { 75 argv++; 76 if (**argv=='-') 77 switch ((*argv)[1]) { 78 case 'd': 79 dflg++; 80 continue; 81 82 case 'm': 83 mflg++; 84 continue; 85 86 case 's': 87 sflg++; 88 continue; 89 90 case 'b': 91 for(i=0; i<NB; i++) { 92 n = atol(argv[1]); 93 if(n == 0) 94 break; 95 blist[i] = n; 96 argv++; 97 argc--; 98 } 99 blist[i] = -1; 100 continue; 101 102 default: 103 printf("Bad flag\n"); 104 } 105 check(*argv); 106 } 107 #else 108 { 109 static char fname[128]; 110 111 printf("File: "); 112 gets(fname); 113 check(fname); 114 } 115 #endif 116 return(nerror); 117 } 118 119 check(file) 120 char *file; 121 { 122 register i, j, c; 123 daddr_t d, cgd, cbase, b; 124 long n; 125 126 fi = open(file, sflg?2:0); 127 if (fi < 0) { 128 printf("cannot open %s\n", file); 129 nerror |= 04; 130 return; 131 } 132 printf("%s:\n", file); 133 nrfile = 0; 134 ndfile = 0; 135 ncfile = 0; 136 nbfile = 0; 137 nmcfile = 0; 138 139 nblock = 0; 140 nfrag = 0; 141 szfrag = 0; 142 nindir = 0; 143 szindir = 0; 144 niindir = 0; 145 146 ndup = 0; 147 #ifndef STANDALONE 148 sync(); 149 #endif 150 bread(SBLOCK, (char *)&sblock, BSIZE); 151 if (sblock.fs_magic != FS_MAGIC) { 152 printf("%s: bad magic number\n", file); 153 nerror |= 04; 154 return; 155 } 156 sblock.fs_cs = 157 (struct csum *)calloc(howmany(cssize(&sblock), BSIZE), BSIZE); 158 lseek(fi, csaddr(&sblock)*FSIZE, 0); 159 read(fi, (char *)sblock.fs_cs, cssize(&sblock)); 160 ino = 0; 161 n = (sblock.fs_size*FRAG + BITS-1) / BITS; 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 sflg = 0; 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(c, &sblock); 179 for (d = cgbase(c, &sblock); d < cgd; d++) 180 chk(d, "badcg"); 181 d = cgimin(c, &sblock); 182 while (cgd < d) { 183 chk(cgd, "cg"); 184 cgd++; 185 } 186 d = cgdmin(c, &sblock); 187 for (; cgd < d; cgd++) 188 chk(cgd, "inode"); 189 if (c == 0) { 190 d += howmany(cssize(&sblock), BSIZE) * FRAG; 191 for (; cgd < d; cgd++) 192 chk(cgd, "csum"); 193 } 194 } 195 } 196 cginit = 0; 197 for (c = 0; c < sblock.fs_ncg; c++) { 198 bread(cgimin(c,&sblock), (char *)itab, 199 sblock.fs_ipg * sizeof (struct dinode)); 200 for (j=0; j < sblock.fs_ipg; j++) { 201 pass1(&itab[j]); 202 ino++; 203 } 204 } 205 ino = 0; 206 #ifndef STANDALONE 207 sync(); 208 #endif 209 bread(SBLOCK, (char *)&sblock, sizeof(sblock)); 210 if (sflg) { 211 makecg(); 212 close(fi); 213 #ifndef STANDALONE 214 if (bmap) 215 free(bmap); 216 #endif 217 return; 218 } 219 nffree = 0; 220 szffree = 0; 221 nbfree = 0; 222 for (c = 0; c < sblock.fs_ncg; c++) { 223 cbase = cgbase(c,&sblock); 224 bread(cgtod(c,&sblock), (char *)&cgrp, sblock.fs_cgsize); 225 for (b = 0; b < sblock.fs_fpg; b += FRAG) { 226 if (isblock(cgrp.cg_free, b / FRAG)) { 227 nbfree++; 228 for (d = 0; d < FRAG; d++) 229 chk(cbase+b+d, "block"); 230 } else { 231 for (d = 0; d < FRAG; d++) 232 if (isset(cgrp.cg_free, b+d)) { 233 chk(cbase+b+d, "frag"); 234 nffree++; 235 szffree++; 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 + niindir) * FRAG + szfrag + szindir; 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", szffree + 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", szffree + 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)) { 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 register i, j; 284 int k, l, sz, ni, nib, ndb; 285 286 i = ip->di_mode & IFMT; 287 if(i == 0) { 288 sblock.fs_nifree++; 289 return; 290 } 291 switch (i) { 292 case IFCHR: 293 ncfile++; 294 return; 295 case IFBLK: 296 nbfile++; 297 return; 298 case IFDIR: 299 ndfile++; 300 break; 301 case IFREG: 302 nrfile++; 303 break; 304 default: 305 printf("bad mode %u\n", ino); 306 return; 307 } 308 ndb = howmany(ip->di_size, BSIZE)-1; 309 for(i=0; i<NDADDR; i++) { 310 if(ip->di_db[i] == 0) 311 continue; 312 if (i==ndb && (ip->di_size&BMASK)) { 313 sz = howmany(ip->di_size - i * BSIZE, FSIZE); 314 for (l = 0; l < sz; l++) 315 chk(ip->di_db[i]+l, "data (frag)"); 316 szfrag += sz; 317 nfrag++; 318 } else { 319 for (l = 0; l < FRAG; l++) 320 chk(ip->di_db[i]+l, "data (block)"); 321 nblock++; 322 } 323 } 324 for(i=NDADDR; i<NDADDR+NIADDR;i++) { 325 if(ip->di_ib[i] == 0) 326 continue; 327 nindir++; 328 if (i==NDADDR) { 329 sz = howmany((ip->di_size-NDADDR*BSIZE), 330 (NINDIR/FRAG) * BSIZE); 331 if (sz > FRAG) 332 sz = FRAG; 333 } else 334 sz = FRAG; 335 for (j = 0; j < FRAG; j++) 336 if (chk(ip->di_ib[i]+j, "1st indirect")) 337 continue; 338 bread(ip->di_ib[i], (char *)ind1, sz*FSIZE); 339 nib = sz * (NINDIR/FRAG); 340 for(j=0; j<nib; j++) { 341 if(ind1[j] == 0) 342 continue; 343 if(i == NDADDR) { 344 for (l = 0; l < FRAG; l++) 345 chk(ind1[j]+l, "data (large)"); 346 nblock++; 347 continue; 348 } 349 niindir++; 350 for (l = 0; l < FRAG; l++) 351 if(chk(ind1[j], "2nd indirect")) 352 goto skip; 353 bread(ind1[j], (char *)ind2, BSIZE); 354 for(k=0; k<NINDIR; k++) { 355 if(ind2[k] == 0) 356 continue; 357 for (l = 0; l < FRAG; l++) 358 chk(ind1[j]+l, "data (huge)"); 359 nblock++; 360 continue; 361 } 362 skip: 363 ; 364 } 365 } 366 } 367 368 chk(bno, s) 369 daddr_t bno; 370 char *s; 371 { 372 register n, cg; 373 374 cg = dtog(bno, &sblock); 375 if (cginit==0 && bno<cgdmin(cg,&sblock) || bno>=FRAG*sblock.fs_size) { 376 printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 377 return(1); 378 } 379 if (duped(bno)) { 380 printf("%ld dup; inode=%u, class=%s\n", bno, ino, s); 381 ndup++; 382 } 383 for (n=0; blist[n] != -1; n++) 384 if (bno == blist[n]) 385 printf("%ld arg; inode=%u, class=%s\n", bno, ino, s); 386 return(0); 387 } 388 389 duped(bno) 390 daddr_t bno; 391 { 392 daddr_t d; 393 register m, n; 394 395 if(dflg) 396 return(0); 397 m = 1 << (bno%BITS); 398 n = (bno/BITS); 399 if(bmap[n] & m) 400 return(1); 401 bmap[n] |= m; 402 return(0); 403 } 404 405 bread(bno, buf, cnt) 406 daddr_t bno; 407 char *buf; 408 { 409 register i; 410 411 lseek(fi, bno*FSIZE, 0); 412 if ((i = read(fi, buf, cnt)) != cnt) { 413 if (sflg) { 414 printf("No update\n"); 415 sflg = 0; 416 } 417 for(i=0; i<BSIZE; i++) 418 buf[i] = 0; 419 } 420 } 421 422 bwrite(bno, buf, cnt) 423 daddr_t bno; 424 char *buf; 425 { 426 register i; 427 428 lseek(fi, bno*FSIZE, 0); 429 if (write(fi, buf, cnt) != cnt) 430 printf("write error %d\n", tell(fi)/BSIZE); 431 } 432 433 makecg() 434 { 435 int c; 436 daddr_t dbase, d, dmin, dmax; 437 long i, j, s; 438 register struct csum *cs; 439 440 sblock.fs_nbfree = 0; 441 sblock.fs_nffree = 0; 442 for (c = 0; c < sblock.fs_ncg; c++) { 443 bread(cgimin(c,&sblock), (char *)itab, 444 sblock.fs_ipg * sizeof (struct dinode)); 445 dbase = cgbase(c, &sblock); 446 dmax = dbase + sblock.fs_fpg; 447 if (dmax > sblock.fs_size) 448 dmax = sblock.fs_size; 449 cs = &sblock.fs_cs[c]; 450 cgrp.cg_time = time(0); 451 cgrp.cg_magic = CG_MAGIC; 452 cgrp.cg_cgx = c; 453 cgrp.cg_ncyl = sblock.fs_cpg; 454 cgrp.cg_niblk = sblock.fs_ipg; 455 cgrp.cg_ndblk = dmax - dbase; 456 cgrp.cg_ndir = 0; 457 cgrp.cg_nffree = 0; 458 cgrp.cg_nbfree = 0; 459 cgrp.cg_nifree = 0; 460 for (i = 0; i < sblock.fs_ipg; i++) 461 switch (itab[i].di_mode&IFMT) { 462 463 case 0: 464 cgrp.cg_nifree++; 465 clrbit(cgrp.cg_iused, i); 466 continue; 467 468 case IFDIR: 469 cgrp.cg_ndir++; 470 /* fall into ... */ 471 472 default: 473 setbit(cgrp.cg_iused, i); 474 continue; 475 } 476 while (i < MAXIPG) { 477 clrbit(cgrp.cg_iused, i); 478 i++; 479 } 480 for (s = 0; s < MAXCPG; s++) 481 for (i = 0; i < NRPOS; i++) 482 cgrp.cg_b[s][i] = 0; 483 dmin = cgdmin(c, &sblock) - dbase; 484 if (c == 0) 485 dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 486 for (d = 0; d < dmin; d++) 487 clrbit(cgrp.cg_free, d); 488 #define getbmap(i) isset(bmap, i) 489 for (; (d + FRAG) <= dmax - dbase; d += FRAG) { 490 j = 0; 491 for (i = 0; i < FRAG; i++) { 492 if (!getbmap(dbase+d+i)) { 493 setbit(cgrp.cg_free, d+i); 494 j++; 495 } else 496 clrbit(cgrp.cg_free, d+i); 497 } 498 if (j == FRAG) { 499 cgrp.cg_nbfree++; 500 s = d * NSPF; 501 cgrp.cg_b[s/sblock.fs_spc] 502 [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 503 } else 504 cgrp.cg_nffree += j; 505 } 506 for (; d < dmax - dbase; d++) { 507 if (!getbmap(dbase+d)) { 508 setbit(cgrp.cg_free, d); 509 cgrp.cg_nffree++; 510 } else 511 clrbit(cgrp.cg_free, d); 512 } 513 for (; d < MAXBPG; d++) 514 clrbit(cgrp.cg_free, d); 515 sblock.fs_nffree += cgrp.cg_nffree; 516 sblock.fs_nbfree += cgrp.cg_nbfree; 517 cs->cs_ndir = cgrp.cg_ndir; 518 cs->cs_nifree = cgrp.cg_nifree; 519 cs->cs_nbfree = cgrp.cg_nbfree; 520 bwrite(cgtod(c, &sblock), (char *)&cgrp, sblock.fs_cgsize); 521 } 522 sblock.fs_ronly = 0; 523 sblock.fs_fmod = 0; 524 bwrite(SBLOCK, (char *)&sblock, sizeof (sblock)); 525 lseek(fi, csaddr(&sblock)*FSIZE, 0); 526 if (write(fi,(char *)sblock.fs_cs,cssize(&sblock)) != cssize(&sblock)) 527 printf("write error %d\n", tell(fi)/BSIZE); 528 } 529