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