1 static char *sccsid = "@(#)icheck.c 1.4 (Berkeley) 09/19/81"; 2 3 /* 4 * icheck 5 */ 6 #define NB 500 7 #define BITS 8 8 #define MAXFN 500 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[BSIZE]; 20 } sbun; 21 #define sblock sbun.sb 22 23 union { 24 struct cg cg; 25 char pad[BSIZE]; 26 } cgun; 27 #define cgrp cgun.cg 28 29 struct dinode itab[MAXIPG]; 30 daddr_t blist[NB]; 31 char *bmap; 32 33 int sflg; 34 int mflg; 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 nmcfile; 45 46 daddr_t nblock; 47 daddr_t nfrag; 48 long szfrag; 49 daddr_t nindir; 50 long szindir; 51 daddr_t niindir; 52 53 daddr_t nffree; 54 long szffree; 55 daddr_t nbfree; 56 57 daddr_t ndup; 58 59 int nerror; 60 61 long atol(); 62 daddr_t alloc(); 63 #ifndef STANDALONE 64 char *malloc(); 65 #endif 66 67 main(argc, argv) 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 printf("cannot open %s\n", 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 szfrag = 0; 143 nindir = 0; 144 szindir = 0; 145 niindir = 0; 146 147 ndup = 0; 148 #ifndef STANDALONE 149 sync(); 150 #endif 151 bread(SBLOCK, (char *)&sblock, BSIZE); 152 if (sblock.fs_magic != FS_MAGIC) { 153 printf("%s: bad magic number\n", file); 154 nerror |= 04; 155 return; 156 } 157 sblock.fs_cs = 158 (struct csum *)calloc(howmany(cssize(&sblock), BSIZE), BSIZE); 159 lseek(fi, csaddr(&sblock)*FSIZE, 0); 160 read(fi, (char *)sblock.fs_cs, cssize(&sblock)); 161 ino = 0; 162 n = (sblock.fs_size*FRAG + BITS-1) / BITS; 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 sflg = 0; 172 } 173 ino = 0; 174 cginit = 1; 175 if(!dflg) { 176 for (i=0; i<(unsigned)n; i++) 177 bmap[i] = 0; 178 for (c=0; c < sblock.fs_ncg; c++) { 179 cgd = cgtod(c, &sblock); 180 for (d = cgbase(c, &sblock); d < cgd; d += FRAG) 181 chk(d, "badcg", 0); 182 d = cgimin(c, &sblock); 183 while (cgd < d) { 184 chk(cgd, "cg", 0); 185 cgd += FRAG; 186 } 187 d = cgdmin(c, &sblock); 188 for (; cgd < d; cgd += FRAG) 189 chk(cgd, "inode", 0); 190 if (c == 0) { 191 d += howmany(cssize(&sblock), FSIZE); 192 for (; cgd < d; cgd += FRAG) 193 chk(cgd, "csum", 0); 194 } 195 } 196 } 197 cginit = 0; 198 for (c = 0; c < sblock.fs_ncg; c++) { 199 bread(cgimin(c,&sblock), (char *)itab, 200 sblock.fs_ipg * sizeof (struct dinode)); 201 for (j=0; j < sblock.fs_ipg; j++) { 202 pass1(&itab[j]); 203 ino++; 204 } 205 } 206 ino = 0; 207 #ifndef STANDALONE 208 sync(); 209 #endif 210 bread(SBLOCK, (char *)&sblock, sizeof(sblock)); 211 if (sflg) { 212 makecg(); 213 close(fi); 214 #ifndef STANDALONE 215 if (bmap) 216 free(bmap); 217 #endif 218 return; 219 } 220 nffree = 0; 221 szffree = 0; 222 nbfree = 0; 223 for (c = 0; c < sblock.fs_ncg; c++) { 224 cbase = cgbase(c,&sblock); 225 bread(cgtod(c,&sblock), (char *)&cgrp, sblock.fs_cgsize); 226 for (b = 0; b < sblock.fs_fpg; b += FRAG) { 227 if (isblock(cgrp.cg_free, b / FRAG)) { 228 nbfree++; 229 chk(cbase+b, "block", 0); 230 } else { 231 for (d = 0; d < FRAG; d++) 232 if (isset(cgrp.cg_free, b+d)) { 233 chk(cbase+b+d, "frag", 1); 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 + nindir + 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, 1)) { 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 fsbaddr_t ind1[NINDIR]; 282 fsbaddr_t ind2[NINDIR]; 283 fsbaddr_t db, ib; 284 register i, j, k; 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 for (i = 0; i < NDADDR; i++) { 309 db = ip->di_db[i]; 310 if (db == 0) 311 continue; 312 chk(fsbtodb(db), "data (block)", isfrag(db)); 313 nblock++; 314 } 315 for(i = 0; i < NIADDR; i++) { 316 ib = ip->di_ib[i]; 317 if(ib == 0) 318 continue; 319 if (chk(fsbtodb(ib), "1st indirect", 0)) 320 continue; 321 bread(fsbtodb(ib), (char *)ind1, BSIZE); 322 nindir++; 323 for (j = 0; j < NINDIR; j++) { 324 ib = ind1[j]; 325 if (ib == 0) 326 continue; 327 if (i == 0) { 328 chk(fsbtodb(ib), "data (large)", isfrag(ib)); 329 nblock++; 330 continue; 331 } 332 if (chk(fsbtodb(ib), "2nd indirect", 0)) 333 continue; 334 bread(fsbtodb(ib), (char *)ind2, BSIZE); 335 niindir++; 336 for (k = 0; k < NINDIR; k++) { 337 ib = ind2[k]; 338 if (ib == 0) 339 continue; 340 chk(fsbtodb(ib), "data (huge)", isfrag(ib)); 341 nblock++; 342 } 343 } 344 } 345 } 346 347 chk(bno, s, fragflg) 348 daddr_t bno; 349 char *s; 350 int fragflg; 351 { 352 register n, cg; 353 354 cg = dtog(bno, &sblock); 355 if (cginit==0 && bno<cgdmin(cg,&sblock) || bno>=FRAG*sblock.fs_size) { 356 printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 357 return(1); 358 } 359 if (duped(bno, fragflg)) { 360 printf("%ld dup; inode=%u, class=%s\n", bno, ino, s); 361 ndup++; 362 } 363 for (n=0; blist[n] != -1; n++) 364 if (bno == blist[n]) 365 printf("%ld arg; inode=%u, class=%s\n", bno, ino, s); 366 return(0); 367 } 368 369 duped(bno, fragflg) 370 daddr_t bno; 371 int fragflg; 372 { 373 if(dflg) 374 return(0); 375 if (fragflg) { 376 if (isset(bmap, bno)) 377 return(1); 378 setbit(bmap, bno); 379 return (0); 380 } 381 if (bno % FRAG != 0) 382 printf("bad bno %d to duped\n", bno); 383 if (isblock(bmap, bno/FRAG)) 384 return (1); 385 setblock(bmap, bno/FRAG); 386 return(0); 387 } 388 389 bread(bno, buf, cnt) 390 daddr_t bno; 391 char *buf; 392 { 393 register i; 394 395 lseek(fi, bno*FSIZE, 0); 396 if ((i = read(fi, buf, cnt)) != cnt) { 397 if (sflg) { 398 printf("No update\n"); 399 sflg = 0; 400 } 401 for(i=0; i<BSIZE; i++) 402 buf[i] = 0; 403 } 404 } 405 406 bwrite(bno, buf, cnt) 407 daddr_t bno; 408 char *buf; 409 { 410 lseek(fi, bno*FSIZE, 0); 411 if (write(fi, buf, cnt) != cnt) 412 printf("write error %d\n", tell(fi)/BSIZE); 413 } 414 415 makecg() 416 { 417 int c; 418 daddr_t dbase, d, dmin, dmax; 419 long i, j, s; 420 register struct csum *cs; 421 422 sblock.fs_nbfree = 0; 423 sblock.fs_nffree = 0; 424 for (c = 0; c < sblock.fs_ncg; c++) { 425 bread(cgimin(c,&sblock), (char *)itab, 426 sblock.fs_ipg * sizeof (struct dinode)); 427 dbase = cgbase(c, &sblock); 428 dmax = dbase + sblock.fs_fpg; 429 if (dmax > sblock.fs_size) 430 dmax = sblock.fs_size; 431 cs = &sblock.fs_cs[c]; 432 cgrp.cg_time = time((long)0); 433 cgrp.cg_magic = CG_MAGIC; 434 cgrp.cg_cgx = c; 435 cgrp.cg_ncyl = sblock.fs_cpg; 436 cgrp.cg_niblk = sblock.fs_ipg; 437 cgrp.cg_ndblk = dmax - dbase; 438 cgrp.cg_ndir = 0; 439 cgrp.cg_nffree = 0; 440 cgrp.cg_nbfree = 0; 441 cgrp.cg_nifree = 0; 442 for (i = 0; i < sblock.fs_ipg; i++) 443 switch (itab[i].di_mode&IFMT) { 444 445 case 0: 446 cgrp.cg_nifree++; 447 clrbit(cgrp.cg_iused, i); 448 continue; 449 450 case IFDIR: 451 cgrp.cg_ndir++; 452 /* fall into ... */ 453 454 default: 455 setbit(cgrp.cg_iused, i); 456 continue; 457 } 458 while (i < MAXIPG) { 459 clrbit(cgrp.cg_iused, i); 460 i++; 461 } 462 for (s = 0; s < MAXCPG; s++) 463 for (i = 0; i < NRPOS; i++) 464 cgrp.cg_b[s][i] = 0; 465 dmin = cgdmin(c, &sblock) - dbase; 466 if (c == 0) 467 dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 468 for (d = 0; d < dmin; d++) 469 clrbit(cgrp.cg_free, d); 470 #define getbmap(i) isset(bmap, i) 471 for (; (d + FRAG) <= dmax - dbase; d += FRAG) { 472 j = 0; 473 for (i = 0; i < FRAG; i++) { 474 if (!getbmap(dbase+d+i)) { 475 setbit(cgrp.cg_free, d+i); 476 j++; 477 } else 478 clrbit(cgrp.cg_free, d+i); 479 } 480 if (j == FRAG) { 481 cgrp.cg_nbfree++; 482 s = d * NSPF; 483 cgrp.cg_b[s/sblock.fs_spc] 484 [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 485 } else 486 cgrp.cg_nffree += j; 487 } 488 for (; d < dmax - dbase; d++) { 489 if (!getbmap(dbase+d)) { 490 setbit(cgrp.cg_free, d); 491 cgrp.cg_nffree++; 492 } else 493 clrbit(cgrp.cg_free, d); 494 } 495 for (; d < MAXBPG; d++) 496 clrbit(cgrp.cg_free, d); 497 sblock.fs_nffree += cgrp.cg_nffree; 498 sblock.fs_nbfree += cgrp.cg_nbfree; 499 cs->cs_ndir = cgrp.cg_ndir; 500 cs->cs_nifree = cgrp.cg_nifree; 501 cs->cs_nbfree = cgrp.cg_nbfree; 502 bwrite(cgtod(c, &sblock), (char *)&cgrp, sblock.fs_cgsize); 503 } 504 sblock.fs_ronly = 0; 505 sblock.fs_fmod = 0; 506 bwrite(SBLOCK, (char *)&sblock, sizeof (sblock)); 507 lseek(fi, csaddr(&sblock) * FSIZE, 0); 508 if (write(fi,(char *)sblock.fs_cs,cssize(&sblock)) != cssize(&sblock)) 509 printf("write error %d\n", tell(fi)/BSIZE); 510 } 511