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