121133Sdist /* 221133Sdist * Copyright (c) 1980 Regents of the University of California. 321133Sdist * All rights reserved. The Berkeley software License Agreement 421133Sdist * specifies the terms and conditions for redistribution. 521133Sdist */ 64410Smckusic 721133Sdist #ifndef lint 8*38509Sbostic static char sccsid[] = "@(#)icheck.c 5.5 (Berkeley) 07/30/89"; 921133Sdist #endif not lint 1021133Sdist 114240Smckusick /* 124240Smckusick * icheck 134240Smckusick */ 144240Smckusick #define NB 500 154240Smckusick #define MAXFN 500 165349Smckusic #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 174240Smckusick 18*38509Sbostic #include <sys/param.h> 19*38509Sbostic #include <sys/time.h> 20*38509Sbostic #include <sys/vnode.h> 21*38509Sbostic #include <ufs/inode.h> 22*38509Sbostic #include <ufs/fs.h> 234240Smckusick #ifndef STANDALONE 244240Smckusick #include <stdio.h> 254240Smckusick #endif 264240Smckusick 274240Smckusick union { 284240Smckusick struct fs sb; 2934148Smckusick char pad[SBSIZE]; 304240Smckusick } sbun; 314240Smckusick #define sblock sbun.sb 324240Smckusick 334240Smckusick union { 344240Smckusick struct cg cg; 355326Smckusic char pad[MAXBSIZE]; 364240Smckusick } cgun; 374240Smckusick #define cgrp cgun.cg 384240Smckusick 3934148Smckusick struct dinode itab[MAXBSIZE / sizeof(struct dinode)]; 4034148Smckusick 414240Smckusick daddr_t blist[NB]; 429298Smckusick daddr_t fsblist[NB]; 434240Smckusick char *bmap; 444240Smckusick 454240Smckusick int mflg; 464240Smckusick int dflg; 474240Smckusick int fi; 484240Smckusick ino_t ino; 494240Smckusick int cginit; 504240Smckusick 514240Smckusick ino_t nrfile; 524240Smckusick ino_t ndfile; 534240Smckusick ino_t nbfile; 544240Smckusick ino_t ncfile; 556286Smckusick ino_t nlfile; 5634148Smckusick ino_t nsfile; 574240Smckusick 584240Smckusick daddr_t nblock; 594240Smckusick daddr_t nfrag; 604240Smckusick daddr_t nindir; 614240Smckusick daddr_t niindir; 624240Smckusick 634240Smckusick daddr_t nffree; 644240Smckusick daddr_t nbfree; 654240Smckusick 664240Smckusick daddr_t ndup; 674240Smckusick 684240Smckusick int nerror; 6930558Smckusick long dev_bsize = 1; 704240Smckusick 714240Smckusick long atol(); 724240Smckusick #ifndef STANDALONE 734240Smckusick char *malloc(); 745098Smckusic char *calloc(); 754240Smckusick #endif 764240Smckusick 774240Smckusick main(argc, argv) 785098Smckusic int argc; 795098Smckusic char *argv[]; 804240Smckusick { 814240Smckusick register i; 824240Smckusick long n; 834240Smckusick 844240Smckusick blist[0] = -1; 854240Smckusick #ifndef STANDALONE 864240Smckusick while (--argc) { 874240Smckusick argv++; 884240Smckusick if (**argv=='-') 894240Smckusick switch ((*argv)[1]) { 904240Smckusick case 'd': 914240Smckusick dflg++; 924240Smckusick continue; 934240Smckusick 944240Smckusick case 'm': 954240Smckusick mflg++; 964240Smckusick continue; 974240Smckusick 984240Smckusick case 'b': 994240Smckusick for(i=0; i<NB; i++) { 1004240Smckusick n = atol(argv[1]); 1014240Smckusick if(n == 0) 1024240Smckusick break; 1034240Smckusick blist[i] = n; 1044240Smckusick argv++; 1054240Smckusick argc--; 1064240Smckusick } 1074240Smckusick blist[i] = -1; 1084240Smckusick continue; 1094240Smckusick 1104240Smckusick default: 1114240Smckusick printf("Bad flag\n"); 1124240Smckusick } 1134240Smckusick check(*argv); 1144240Smckusick } 1154240Smckusick #else 1164240Smckusick { 1174240Smckusick static char fname[128]; 1184240Smckusick 1194240Smckusick printf("File: "); 1204240Smckusick gets(fname); 1214240Smckusick check(fname); 1224240Smckusick } 1234240Smckusick #endif 1244240Smckusick return(nerror); 1254240Smckusick } 1264240Smckusick 1274240Smckusick check(file) 1285098Smckusic char *file; 1294240Smckusick { 1304240Smckusick register i, j, c; 1314240Smckusick daddr_t d, cgd, cbase, b; 1324240Smckusick long n; 1339298Smckusick char buf[BUFSIZ]; 1344240Smckusick 13534148Smckusick fi = open(file, 0); 1364240Smckusick if (fi < 0) { 1375098Smckusic perror(file); 1384240Smckusick nerror |= 04; 1394240Smckusick return; 1404240Smckusick } 1414240Smckusick printf("%s:\n", file); 1424240Smckusick nrfile = 0; 1434240Smckusick ndfile = 0; 1444240Smckusick ncfile = 0; 1454240Smckusick nbfile = 0; 1466286Smckusick nlfile = 0; 14734148Smckusick nsfile = 0; 1484240Smckusick 1494240Smckusick nblock = 0; 1504240Smckusick nfrag = 0; 1514240Smckusick nindir = 0; 1524240Smckusick niindir = 0; 1534240Smckusick 1544240Smckusick ndup = 0; 1554240Smckusick #ifndef STANDALONE 1564240Smckusick sync(); 1574240Smckusick #endif 1585326Smckusic getsb(&sblock, file); 1595326Smckusic if (nerror) 1604240Smckusick return; 1619298Smckusick for (n=0; blist[n] != -1; n++) 1629298Smckusick fsblist[n] = dbtofsb(&sblock, blist[n]); 1634240Smckusick ino = 0; 1645098Smckusic n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short)); 1654240Smckusick #ifdef STANDALONE 1664240Smckusick bmap = NULL; 1674240Smckusick #else 1684240Smckusick bmap = malloc((unsigned)n); 1694240Smckusick #endif 1704240Smckusick if (bmap==NULL) { 1714240Smckusick printf("Not enough core; duplicates unchecked\n"); 1724240Smckusick dflg++; 1734240Smckusick } 1744240Smckusick ino = 0; 1754240Smckusick cginit = 1; 1766534Smckusick if (!dflg) { 1776534Smckusick for (i = 0; i < (unsigned)n; i++) 1784240Smckusick bmap[i] = 0; 1796534Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1805382Smckusic cgd = cgtod(&sblock, c); 1816534Smckusick if (c == 0) 1826534Smckusick d = cgbase(&sblock, c); 1836534Smckusick else 1846534Smckusick d = cgsblock(&sblock, c); 18532441Sbostic (void)sprintf(buf, "spare super block %d", c); 1866534Smckusick for (; d < cgd; d += sblock.fs_frag) 1879298Smckusick chk(d, buf, sblock.fs_bsize); 1885382Smckusic d = cgimin(&sblock, c); 18932441Sbostic (void)sprintf(buf, "cylinder group %d", c); 1904240Smckusick while (cgd < d) { 1919298Smckusick chk(cgd, buf, sblock.fs_bsize); 1925326Smckusic cgd += sblock.fs_frag; 1934240Smckusick } 1945382Smckusic d = cgdmin(&sblock, c); 1959298Smckusick i = INOPB(&sblock); 1969298Smckusick for (; cgd < d; cgd += sblock.fs_frag) { 19732441Sbostic (void)sprintf(buf, "inodes %d-%d", ino, ino + i); 1989298Smckusick chk(cgd, buf, sblock.fs_bsize); 1999298Smckusick ino += i; 2009298Smckusick } 2014240Smckusick if (c == 0) { 2026534Smckusick d += howmany(sblock.fs_cssize, sblock.fs_fsize); 2036534Smckusick for (; cgd < d; cgd++) 2046534Smckusick chk(cgd, "csum", sblock.fs_fsize); 2054240Smckusick } 2064240Smckusick } 2074240Smckusick } 2089298Smckusick ino = 0; 2094240Smckusick cginit = 0; 2104240Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 21134148Smckusick for (i = 0; 21234148Smckusick i < sblock.fs_ipg / INOPF(&sblock); 21334148Smckusick i += sblock.fs_frag) { 21434148Smckusick bread(fsbtodb(&sblock, cgimin(&sblock, c) + i), 21534148Smckusick (char *)itab, sblock.fs_bsize); 21634148Smckusick for (j = 0; j < INOPB(&sblock); j++) { 21734148Smckusick pass1(&itab[j]); 21834148Smckusick ino++; 21934148Smckusick } 2204240Smckusick } 2214240Smckusick } 2224240Smckusick ino = 0; 2234240Smckusick #ifndef STANDALONE 2244240Smckusick sync(); 2254240Smckusick #endif 2264240Smckusick nffree = 0; 2274240Smckusick nbfree = 0; 2284240Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 2295382Smckusic cbase = cgbase(&sblock, c); 2305382Smckusic bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp, 2315326Smckusic sblock.fs_cgsize); 23234148Smckusick if (!cg_chkmagic(&cgrp)) 2336534Smckusick printf("cg %d: bad magic number\n", c); 2345326Smckusic for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 23534148Smckusick if (isblock(&sblock, cg_blksfree(&cgrp), 2365326Smckusic b / sblock.fs_frag)) { 2374240Smckusick nbfree++; 2389298Smckusick chk(cbase+b, "free block", sblock.fs_bsize); 2394240Smckusick } else { 2405326Smckusic for (d = 0; d < sblock.fs_frag; d++) 24134148Smckusick if (isset(cg_blksfree(&cgrp), b+d)) { 2429298Smckusick chk(cbase+b+d, "free frag", sblock.fs_fsize); 2434240Smckusick nffree++; 2444240Smckusick } 2454240Smckusick } 2464240Smckusick } 2474240Smckusick } 2484240Smckusick close(fi); 2494240Smckusick #ifndef STANDALONE 2504240Smckusick if (bmap) 2514240Smckusick free(bmap); 2524240Smckusick #endif 2534240Smckusick 25434148Smckusick i = nrfile + ndfile + ncfile + nbfile + nlfile + nsfile; 2554240Smckusick #ifndef STANDALONE 25634148Smckusick printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 25734148Smckusick i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 2584240Smckusick #else 25934148Smckusick printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 26034148Smckusick i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 2614240Smckusick #endif 2625326Smckusic n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag; 2634240Smckusick #ifdef STANDALONE 2644240Smckusick printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 2654240Smckusick n, nindir, niindir, nblock, nfrag); 2665326Smckusic printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 2674240Smckusick nbfree, nffree); 2684240Smckusick #else 2694240Smckusick printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 2704240Smckusick n, nindir, niindir, nblock, nfrag); 2715326Smckusic printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 2724240Smckusick nbfree, nffree); 2734240Smckusick #endif 2744240Smckusick if(!dflg) { 2754240Smckusick n = 0; 2764410Smckusic for (d = 0; d < sblock.fs_size; d++) 2775326Smckusic if(!duped(d, sblock.fs_fsize)) { 2784240Smckusick if(mflg) 2794240Smckusick printf("%ld missing\n", d); 2804240Smckusick n++; 2814240Smckusick } 2824240Smckusick printf("missing%5ld\n", n); 2834240Smckusick } 2844240Smckusick } 2854240Smckusick 2864240Smckusick pass1(ip) 2874410Smckusic register struct dinode *ip; 2884240Smckusick { 2895326Smckusic daddr_t ind1[MAXNINDIR]; 2905326Smckusic daddr_t ind2[MAXNINDIR]; 2914429Smckusic daddr_t db, ib; 2924429Smckusic register int i, j, k, siz; 2939298Smckusick int lbn; 2949298Smckusick char buf[BUFSIZ]; 2954240Smckusick 2964240Smckusick i = ip->di_mode & IFMT; 2974790Smckusic if(i == 0) 2984240Smckusick return; 2994240Smckusick switch (i) { 3004240Smckusick case IFCHR: 3014240Smckusick ncfile++; 3024240Smckusick return; 3034240Smckusick case IFBLK: 3044240Smckusick nbfile++; 3054240Smckusick return; 3064240Smckusick case IFDIR: 3074240Smckusick ndfile++; 3084240Smckusick break; 3094240Smckusick case IFREG: 3104240Smckusick nrfile++; 3114240Smckusick break; 31234148Smckusick case IFSOCK: 31334148Smckusick nsfile++; 31434148Smckusick break; 3156286Smckusick case IFLNK: 3166286Smckusick nlfile++; 3176286Smckusick break; 3184240Smckusick default: 3194240Smckusick printf("bad mode %u\n", ino); 3204240Smckusick return; 3214240Smckusick } 3224410Smckusic for (i = 0; i < NDADDR; i++) { 3234410Smckusic db = ip->di_db[i]; 3244410Smckusic if (db == 0) 3254240Smckusick continue; 3265326Smckusic siz = dblksize(&sblock, ip, i); 32732441Sbostic (void)sprintf(buf, "logical data block %d", i); 3289298Smckusick chk(db, buf, siz); 3295326Smckusic if (siz == sblock.fs_bsize) 3304429Smckusic nblock++; 3314429Smckusic else 3325326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3334240Smckusick } 3344410Smckusic for(i = 0; i < NIADDR; i++) { 3354410Smckusic ib = ip->di_ib[i]; 3369298Smckusick if (ib == 0) 3374240Smckusick continue; 3385326Smckusic if (chk(ib, "1st indirect", sblock.fs_bsize)) 3394410Smckusic continue; 3405326Smckusic bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); 3414240Smckusick nindir++; 3425326Smckusic for (j = 0; j < NINDIR(&sblock); j++) { 3434410Smckusic ib = ind1[j]; 3444410Smckusic if (ib == 0) 3454240Smckusick continue; 3464410Smckusic if (i == 0) { 3479298Smckusick lbn = NDADDR + j; 3489298Smckusick siz = dblksize(&sblock, ip, lbn); 34932441Sbostic (void)sprintf(buf, "logical data block %d", lbn); 3509298Smckusick chk(ib, buf, siz); 3515326Smckusic if (siz == sblock.fs_bsize) 3524429Smckusic nblock++; 3534429Smckusic else 3545326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3554240Smckusick continue; 3564240Smckusick } 3575326Smckusic if (chk(ib, "2nd indirect", sblock.fs_bsize)) 3584410Smckusic continue; 3595326Smckusic bread(fsbtodb(&sblock, ib), (char *)ind2, 3605326Smckusic sblock.fs_bsize); 3614240Smckusick niindir++; 3625326Smckusic for (k = 0; k < NINDIR(&sblock); k++) { 3634410Smckusic ib = ind2[k]; 3644410Smckusic if (ib == 0) 3654240Smckusick continue; 3669298Smckusick lbn = NDADDR + NINDIR(&sblock) * (i + j) + k; 3679298Smckusick siz = dblksize(&sblock, ip, lbn); 36832441Sbostic (void)sprintf(buf, "logical data block %d", lbn); 3699298Smckusick chk(ib, buf, siz); 3705326Smckusic if (siz == sblock.fs_bsize) 3714429Smckusic nblock++; 3724429Smckusic else 3735326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3744240Smckusick } 3754240Smckusick } 3764240Smckusick } 3774240Smckusick } 3784240Smckusick 3794429Smckusic chk(bno, s, size) 3804410Smckusic daddr_t bno; 3814410Smckusic char *s; 3824429Smckusic int size; 3834240Smckusick { 3844240Smckusick register n, cg; 3855957Smckusic int frags; 3864240Smckusick 3875382Smckusic cg = dtog(&sblock, bno); 3886534Smckusick if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) { 3894240Smckusick printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 3904240Smckusick return(1); 3914240Smckusick } 3929298Smckusick frags = numfrags(&sblock, size); 3939298Smckusick if (frags == sblock.fs_frag) { 3944429Smckusic if (duped(bno, size)) { 3954429Smckusic printf("%ld dup block; inode=%u, class=%s\n", 3964429Smckusic bno, ino, s); 3975326Smckusic ndup += sblock.fs_frag; 3984429Smckusic } 3994429Smckusic } else { 4005957Smckusic for (n = 0; n < frags; n++) { 4015326Smckusic if (duped(bno + n, sblock.fs_fsize)) { 4024429Smckusic printf("%ld dup frag; inode=%u, class=%s\n", 4034429Smckusic bno, ino, s); 4044429Smckusic ndup++; 4054429Smckusic } 4064429Smckusic } 4074240Smckusick } 4084240Smckusick for (n=0; blist[n] != -1; n++) 4099298Smckusick if (fsblist[n] >= bno && fsblist[n] < bno + frags) 4109298Smckusick printf("%ld arg; frag %d of %d, inode=%u, class=%s\n", 4119298Smckusick blist[n], fsblist[n] - bno, frags, ino, s); 4124240Smckusick return(0); 4134240Smckusick } 4144240Smckusick 4154429Smckusic duped(bno, size) 4164410Smckusic daddr_t bno; 4174429Smckusic int size; 4184240Smckusick { 4194240Smckusick if(dflg) 4204240Smckusick return(0); 4215326Smckusic if (size != sblock.fs_fsize && size != sblock.fs_bsize) 4224429Smckusic printf("bad size %d to duped\n", size); 4235326Smckusic if (size == sblock.fs_fsize) { 4244410Smckusic if (isset(bmap, bno)) 4254410Smckusic return(1); 4264410Smckusic setbit(bmap, bno); 4274410Smckusic return (0); 4284410Smckusic } 4295326Smckusic if (bno % sblock.fs_frag != 0) 4304410Smckusic printf("bad bno %d to duped\n", bno); 4315326Smckusic if (isblock(&sblock, bmap, bno/sblock.fs_frag)) 4324410Smckusic return (1); 4335326Smckusic setblock(&sblock, bmap, bno/sblock.fs_frag); 4344240Smckusick return(0); 4354240Smckusick } 4364240Smckusick 4375326Smckusic getsb(fs, file) 4385326Smckusic register struct fs *fs; 4395326Smckusic char *file; 4405326Smckusic { 4416534Smckusick int i, j, size; 4425326Smckusic 44330558Smckusick if (bread(SBOFF, fs, SBSIZE)) { 4445326Smckusic printf("bad super block"); 4455326Smckusic perror(file); 4465326Smckusic nerror |= 04; 4475326Smckusic return; 4485326Smckusic } 4495326Smckusic if (fs->fs_magic != FS_MAGIC) { 4505326Smckusic printf("%s: bad magic number\n", file); 4515326Smckusic nerror |= 04; 4525326Smckusic return; 4535326Smckusic } 45430558Smckusick dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 4556534Smckusick for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 4566534Smckusick size = sblock.fs_cssize - i < sblock.fs_bsize ? 4576534Smckusick sblock.fs_cssize - i : sblock.fs_bsize; 4586534Smckusick sblock.fs_csp[j] = (struct csum *)calloc(1, size); 4596534Smckusick bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)), 4606534Smckusick (char *)fs->fs_csp[j], size); 4615326Smckusic } 4625326Smckusic } 4635326Smckusic 4644240Smckusick bread(bno, buf, cnt) 4654410Smckusic daddr_t bno; 4664410Smckusic char *buf; 4674240Smckusick { 4684240Smckusick register i; 4694240Smckusick 47030558Smckusick lseek(fi, bno * dev_bsize, 0); 4714240Smckusick if ((i = read(fi, buf, cnt)) != cnt) { 4725326Smckusic for(i=0; i<sblock.fs_bsize; i++) 4734240Smckusick buf[i] = 0; 4745326Smckusic return (1); 4754240Smckusick } 4765326Smckusic return (0); 4774240Smckusick } 4785326Smckusic 4795326Smckusic /* 4808143Smckusick * check if a block is available 4815326Smckusic */ 4825326Smckusic isblock(fs, cp, h) 4835326Smckusic struct fs *fs; 4845326Smckusic unsigned char *cp; 4855326Smckusic int h; 4865326Smckusic { 4875326Smckusic unsigned char mask; 4885326Smckusic 4895326Smckusic switch (fs->fs_frag) { 4905326Smckusic case 8: 4915326Smckusic return (cp[h] == 0xff); 4925326Smckusic case 4: 4935326Smckusic mask = 0x0f << ((h & 0x1) << 2); 4945326Smckusic return ((cp[h >> 1] & mask) == mask); 4955326Smckusic case 2: 4965326Smckusic mask = 0x03 << ((h & 0x3) << 1); 4975326Smckusic return ((cp[h >> 2] & mask) == mask); 4985326Smckusic case 1: 4995326Smckusic mask = 0x01 << (h & 0x7); 5005326Smckusic return ((cp[h >> 3] & mask) == mask); 5015326Smckusic default: 5028143Smckusick #ifdef STANDALONE 5038143Smckusick printf("isblock bad fs_frag %d\n", fs->fs_frag); 5048143Smckusick #else 5055326Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 5068143Smckusick #endif 5075326Smckusic return; 5085326Smckusic } 5095326Smckusic } 5105326Smckusic 5118143Smckusick /* 5128143Smckusick * put a block into the map 5138143Smckusick */ 5145326Smckusic setblock(fs, cp, h) 5155326Smckusic struct fs *fs; 5165326Smckusic unsigned char *cp; 5175326Smckusic int h; 5185326Smckusic { 5195326Smckusic switch (fs->fs_frag) { 5205326Smckusic case 8: 5215326Smckusic cp[h] = 0xff; 5225326Smckusic return; 5235326Smckusic case 4: 5245326Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 5255326Smckusic return; 5265326Smckusic case 2: 5275326Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 5285326Smckusic return; 5295326Smckusic case 1: 5305326Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 5315326Smckusic return; 5325326Smckusic default: 5338143Smckusick #ifdef STANDALONE 5348143Smckusick printf("setblock bad fs_frag %d\n", fs->fs_frag); 5358143Smckusick #else 5365326Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 5378143Smckusick #endif 5385326Smckusic return; 5395326Smckusic } 5405326Smckusic } 541