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