1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)icheck.c 5.5 (Berkeley) 07/30/89"; 9 #endif not lint 10 11 /* 12 * icheck 13 */ 14 #define NB 500 15 #define MAXFN 500 16 #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 17 18 #include <sys/param.h> 19 #include <sys/time.h> 20 #include <sys/vnode.h> 21 #include <ufs/inode.h> 22 #include <ufs/fs.h> 23 #ifndef STANDALONE 24 #include <stdio.h> 25 #endif 26 27 union { 28 struct fs sb; 29 char pad[SBSIZE]; 30 } sbun; 31 #define sblock sbun.sb 32 33 union { 34 struct cg cg; 35 char pad[MAXBSIZE]; 36 } cgun; 37 #define cgrp cgun.cg 38 39 struct dinode itab[MAXBSIZE / sizeof(struct dinode)]; 40 41 daddr_t blist[NB]; 42 daddr_t fsblist[NB]; 43 char *bmap; 44 45 int mflg; 46 int dflg; 47 int fi; 48 ino_t ino; 49 int cginit; 50 51 ino_t nrfile; 52 ino_t ndfile; 53 ino_t nbfile; 54 ino_t ncfile; 55 ino_t nlfile; 56 ino_t nsfile; 57 58 daddr_t nblock; 59 daddr_t nfrag; 60 daddr_t nindir; 61 daddr_t niindir; 62 63 daddr_t nffree; 64 daddr_t nbfree; 65 66 daddr_t ndup; 67 68 int nerror; 69 long dev_bsize = 1; 70 71 long atol(); 72 #ifndef STANDALONE 73 char *malloc(); 74 char *calloc(); 75 #endif 76 77 main(argc, argv) 78 int argc; 79 char *argv[]; 80 { 81 register i; 82 long n; 83 84 blist[0] = -1; 85 #ifndef STANDALONE 86 while (--argc) { 87 argv++; 88 if (**argv=='-') 89 switch ((*argv)[1]) { 90 case 'd': 91 dflg++; 92 continue; 93 94 case 'm': 95 mflg++; 96 continue; 97 98 case 'b': 99 for(i=0; i<NB; i++) { 100 n = atol(argv[1]); 101 if(n == 0) 102 break; 103 blist[i] = n; 104 argv++; 105 argc--; 106 } 107 blist[i] = -1; 108 continue; 109 110 default: 111 printf("Bad flag\n"); 112 } 113 check(*argv); 114 } 115 #else 116 { 117 static char fname[128]; 118 119 printf("File: "); 120 gets(fname); 121 check(fname); 122 } 123 #endif 124 return(nerror); 125 } 126 127 check(file) 128 char *file; 129 { 130 register i, j, c; 131 daddr_t d, cgd, cbase, b; 132 long n; 133 char buf[BUFSIZ]; 134 135 fi = open(file, 0); 136 if (fi < 0) { 137 perror(file); 138 nerror |= 04; 139 return; 140 } 141 printf("%s:\n", file); 142 nrfile = 0; 143 ndfile = 0; 144 ncfile = 0; 145 nbfile = 0; 146 nlfile = 0; 147 nsfile = 0; 148 149 nblock = 0; 150 nfrag = 0; 151 nindir = 0; 152 niindir = 0; 153 154 ndup = 0; 155 #ifndef STANDALONE 156 sync(); 157 #endif 158 getsb(&sblock, file); 159 if (nerror) 160 return; 161 for (n=0; blist[n] != -1; n++) 162 fsblist[n] = dbtofsb(&sblock, blist[n]); 163 ino = 0; 164 n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short)); 165 #ifdef STANDALONE 166 bmap = NULL; 167 #else 168 bmap = malloc((unsigned)n); 169 #endif 170 if (bmap==NULL) { 171 printf("Not enough core; duplicates unchecked\n"); 172 dflg++; 173 } 174 ino = 0; 175 cginit = 1; 176 if (!dflg) { 177 for (i = 0; i < (unsigned)n; i++) 178 bmap[i] = 0; 179 for (c = 0; c < sblock.fs_ncg; c++) { 180 cgd = cgtod(&sblock, c); 181 if (c == 0) 182 d = cgbase(&sblock, c); 183 else 184 d = cgsblock(&sblock, c); 185 (void)sprintf(buf, "spare super block %d", c); 186 for (; d < cgd; d += sblock.fs_frag) 187 chk(d, buf, sblock.fs_bsize); 188 d = cgimin(&sblock, c); 189 (void)sprintf(buf, "cylinder group %d", c); 190 while (cgd < d) { 191 chk(cgd, buf, sblock.fs_bsize); 192 cgd += sblock.fs_frag; 193 } 194 d = cgdmin(&sblock, c); 195 i = INOPB(&sblock); 196 for (; cgd < d; cgd += sblock.fs_frag) { 197 (void)sprintf(buf, "inodes %d-%d", ino, ino + i); 198 chk(cgd, buf, sblock.fs_bsize); 199 ino += i; 200 } 201 if (c == 0) { 202 d += howmany(sblock.fs_cssize, sblock.fs_fsize); 203 for (; cgd < d; cgd++) 204 chk(cgd, "csum", sblock.fs_fsize); 205 } 206 } 207 } 208 ino = 0; 209 cginit = 0; 210 for (c = 0; c < sblock.fs_ncg; c++) { 211 for (i = 0; 212 i < sblock.fs_ipg / INOPF(&sblock); 213 i += sblock.fs_frag) { 214 bread(fsbtodb(&sblock, cgimin(&sblock, c) + i), 215 (char *)itab, sblock.fs_bsize); 216 for (j = 0; j < INOPB(&sblock); j++) { 217 pass1(&itab[j]); 218 ino++; 219 } 220 } 221 } 222 ino = 0; 223 #ifndef STANDALONE 224 sync(); 225 #endif 226 nffree = 0; 227 nbfree = 0; 228 for (c = 0; c < sblock.fs_ncg; c++) { 229 cbase = cgbase(&sblock, c); 230 bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp, 231 sblock.fs_cgsize); 232 if (!cg_chkmagic(&cgrp)) 233 printf("cg %d: bad magic number\n", c); 234 for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 235 if (isblock(&sblock, cg_blksfree(&cgrp), 236 b / sblock.fs_frag)) { 237 nbfree++; 238 chk(cbase+b, "free block", sblock.fs_bsize); 239 } else { 240 for (d = 0; d < sblock.fs_frag; d++) 241 if (isset(cg_blksfree(&cgrp), b+d)) { 242 chk(cbase+b+d, "free frag", sblock.fs_fsize); 243 nffree++; 244 } 245 } 246 } 247 } 248 close(fi); 249 #ifndef STANDALONE 250 if (bmap) 251 free(bmap); 252 #endif 253 254 i = nrfile + ndfile + ncfile + nbfile + nlfile + nsfile; 255 #ifndef STANDALONE 256 printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 257 i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 258 #else 259 printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 260 i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 261 #endif 262 n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag; 263 #ifdef STANDALONE 264 printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 265 n, nindir, niindir, nblock, nfrag); 266 printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 267 nbfree, nffree); 268 #else 269 printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 270 n, nindir, niindir, nblock, nfrag); 271 printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 272 nbfree, nffree); 273 #endif 274 if(!dflg) { 275 n = 0; 276 for (d = 0; d < sblock.fs_size; d++) 277 if(!duped(d, sblock.fs_fsize)) { 278 if(mflg) 279 printf("%ld missing\n", d); 280 n++; 281 } 282 printf("missing%5ld\n", n); 283 } 284 } 285 286 pass1(ip) 287 register struct dinode *ip; 288 { 289 daddr_t ind1[MAXNINDIR]; 290 daddr_t ind2[MAXNINDIR]; 291 daddr_t db, ib; 292 register int i, j, k, siz; 293 int lbn; 294 char buf[BUFSIZ]; 295 296 i = ip->di_mode & IFMT; 297 if(i == 0) 298 return; 299 switch (i) { 300 case IFCHR: 301 ncfile++; 302 return; 303 case IFBLK: 304 nbfile++; 305 return; 306 case IFDIR: 307 ndfile++; 308 break; 309 case IFREG: 310 nrfile++; 311 break; 312 case IFSOCK: 313 nsfile++; 314 break; 315 case IFLNK: 316 nlfile++; 317 break; 318 default: 319 printf("bad mode %u\n", ino); 320 return; 321 } 322 for (i = 0; i < NDADDR; i++) { 323 db = ip->di_db[i]; 324 if (db == 0) 325 continue; 326 siz = dblksize(&sblock, ip, i); 327 (void)sprintf(buf, "logical data block %d", i); 328 chk(db, buf, siz); 329 if (siz == sblock.fs_bsize) 330 nblock++; 331 else 332 nfrag += howmany(siz, sblock.fs_fsize); 333 } 334 for(i = 0; i < NIADDR; i++) { 335 ib = ip->di_ib[i]; 336 if (ib == 0) 337 continue; 338 if (chk(ib, "1st indirect", sblock.fs_bsize)) 339 continue; 340 bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); 341 nindir++; 342 for (j = 0; j < NINDIR(&sblock); j++) { 343 ib = ind1[j]; 344 if (ib == 0) 345 continue; 346 if (i == 0) { 347 lbn = NDADDR + j; 348 siz = dblksize(&sblock, ip, lbn); 349 (void)sprintf(buf, "logical data block %d", lbn); 350 chk(ib, buf, siz); 351 if (siz == sblock.fs_bsize) 352 nblock++; 353 else 354 nfrag += howmany(siz, sblock.fs_fsize); 355 continue; 356 } 357 if (chk(ib, "2nd indirect", sblock.fs_bsize)) 358 continue; 359 bread(fsbtodb(&sblock, ib), (char *)ind2, 360 sblock.fs_bsize); 361 niindir++; 362 for (k = 0; k < NINDIR(&sblock); k++) { 363 ib = ind2[k]; 364 if (ib == 0) 365 continue; 366 lbn = NDADDR + NINDIR(&sblock) * (i + j) + k; 367 siz = dblksize(&sblock, ip, lbn); 368 (void)sprintf(buf, "logical data block %d", lbn); 369 chk(ib, buf, siz); 370 if (siz == sblock.fs_bsize) 371 nblock++; 372 else 373 nfrag += howmany(siz, sblock.fs_fsize); 374 } 375 } 376 } 377 } 378 379 chk(bno, s, size) 380 daddr_t bno; 381 char *s; 382 int size; 383 { 384 register n, cg; 385 int frags; 386 387 cg = dtog(&sblock, bno); 388 if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) { 389 printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 390 return(1); 391 } 392 frags = numfrags(&sblock, size); 393 if (frags == sblock.fs_frag) { 394 if (duped(bno, size)) { 395 printf("%ld dup block; inode=%u, class=%s\n", 396 bno, ino, s); 397 ndup += sblock.fs_frag; 398 } 399 } else { 400 for (n = 0; n < frags; n++) { 401 if (duped(bno + n, sblock.fs_fsize)) { 402 printf("%ld dup frag; inode=%u, class=%s\n", 403 bno, ino, s); 404 ndup++; 405 } 406 } 407 } 408 for (n=0; blist[n] != -1; n++) 409 if (fsblist[n] >= bno && fsblist[n] < bno + frags) 410 printf("%ld arg; frag %d of %d, inode=%u, class=%s\n", 411 blist[n], fsblist[n] - bno, frags, ino, s); 412 return(0); 413 } 414 415 duped(bno, size) 416 daddr_t bno; 417 int size; 418 { 419 if(dflg) 420 return(0); 421 if (size != sblock.fs_fsize && size != sblock.fs_bsize) 422 printf("bad size %d to duped\n", size); 423 if (size == sblock.fs_fsize) { 424 if (isset(bmap, bno)) 425 return(1); 426 setbit(bmap, bno); 427 return (0); 428 } 429 if (bno % sblock.fs_frag != 0) 430 printf("bad bno %d to duped\n", bno); 431 if (isblock(&sblock, bmap, bno/sblock.fs_frag)) 432 return (1); 433 setblock(&sblock, bmap, bno/sblock.fs_frag); 434 return(0); 435 } 436 437 getsb(fs, file) 438 register struct fs *fs; 439 char *file; 440 { 441 int i, j, size; 442 443 if (bread(SBOFF, fs, SBSIZE)) { 444 printf("bad super block"); 445 perror(file); 446 nerror |= 04; 447 return; 448 } 449 if (fs->fs_magic != FS_MAGIC) { 450 printf("%s: bad magic number\n", file); 451 nerror |= 04; 452 return; 453 } 454 dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 455 for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 456 size = sblock.fs_cssize - i < sblock.fs_bsize ? 457 sblock.fs_cssize - i : sblock.fs_bsize; 458 sblock.fs_csp[j] = (struct csum *)calloc(1, size); 459 bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)), 460 (char *)fs->fs_csp[j], size); 461 } 462 } 463 464 bread(bno, buf, cnt) 465 daddr_t bno; 466 char *buf; 467 { 468 register i; 469 470 lseek(fi, bno * dev_bsize, 0); 471 if ((i = read(fi, buf, cnt)) != cnt) { 472 for(i=0; i<sblock.fs_bsize; i++) 473 buf[i] = 0; 474 return (1); 475 } 476 return (0); 477 } 478 479 /* 480 * check if a block is available 481 */ 482 isblock(fs, cp, h) 483 struct fs *fs; 484 unsigned char *cp; 485 int h; 486 { 487 unsigned char mask; 488 489 switch (fs->fs_frag) { 490 case 8: 491 return (cp[h] == 0xff); 492 case 4: 493 mask = 0x0f << ((h & 0x1) << 2); 494 return ((cp[h >> 1] & mask) == mask); 495 case 2: 496 mask = 0x03 << ((h & 0x3) << 1); 497 return ((cp[h >> 2] & mask) == mask); 498 case 1: 499 mask = 0x01 << (h & 0x7); 500 return ((cp[h >> 3] & mask) == mask); 501 default: 502 #ifdef STANDALONE 503 printf("isblock bad fs_frag %d\n", fs->fs_frag); 504 #else 505 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 506 #endif 507 return; 508 } 509 } 510 511 /* 512 * put a block into the map 513 */ 514 setblock(fs, cp, h) 515 struct fs *fs; 516 unsigned char *cp; 517 int h; 518 { 519 switch (fs->fs_frag) { 520 case 8: 521 cp[h] = 0xff; 522 return; 523 case 4: 524 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 525 return; 526 case 2: 527 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 528 return; 529 case 1: 530 cp[h >> 3] |= (0x01 << (h & 0x7)); 531 return; 532 default: 533 #ifdef STANDALONE 534 printf("setblock bad fs_frag %d\n", fs->fs_frag); 535 #else 536 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 537 #endif 538 return; 539 } 540 } 541