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