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*34148Smckusick static char sccsid[] = "@(#)icheck.c 5.4 (Berkeley) 05/02/88"; 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 184240Smckusick #ifndef STANDALONE 194240Smckusick #include <stdio.h> 204240Smckusick #endif 216490Smckusick #include <sys/param.h> 226490Smckusick #include <sys/inode.h> 236490Smckusick #include <sys/fs.h> 244240Smckusick 254240Smckusick union { 264240Smckusick struct fs sb; 27*34148Smckusick char pad[SBSIZE]; 284240Smckusick } sbun; 294240Smckusick #define sblock sbun.sb 304240Smckusick 314240Smckusick union { 324240Smckusick struct cg cg; 335326Smckusic char pad[MAXBSIZE]; 344240Smckusick } cgun; 354240Smckusick #define cgrp cgun.cg 364240Smckusick 37*34148Smckusick struct dinode itab[MAXBSIZE / sizeof(struct dinode)]; 38*34148Smckusick 394240Smckusick daddr_t blist[NB]; 409298Smckusick daddr_t fsblist[NB]; 414240Smckusick char *bmap; 424240Smckusick 434240Smckusick int mflg; 444240Smckusick int dflg; 454240Smckusick int fi; 464240Smckusick ino_t ino; 474240Smckusick int cginit; 484240Smckusick 494240Smckusick ino_t nrfile; 504240Smckusick ino_t ndfile; 514240Smckusick ino_t nbfile; 524240Smckusick ino_t ncfile; 536286Smckusick ino_t nlfile; 54*34148Smckusick ino_t nsfile; 554240Smckusick 564240Smckusick daddr_t nblock; 574240Smckusick daddr_t nfrag; 584240Smckusick daddr_t nindir; 594240Smckusick daddr_t niindir; 604240Smckusick 614240Smckusick daddr_t nffree; 624240Smckusick daddr_t nbfree; 634240Smckusick 644240Smckusick daddr_t ndup; 654240Smckusick 664240Smckusick int nerror; 6730558Smckusick long dev_bsize = 1; 684240Smckusick 694240Smckusick long atol(); 704240Smckusick #ifndef STANDALONE 714240Smckusick char *malloc(); 725098Smckusic char *calloc(); 734240Smckusick #endif 744240Smckusick 754240Smckusick main(argc, argv) 765098Smckusic int argc; 775098Smckusic char *argv[]; 784240Smckusick { 794240Smckusick register i; 804240Smckusick long n; 814240Smckusick 824240Smckusick blist[0] = -1; 834240Smckusick #ifndef STANDALONE 844240Smckusick while (--argc) { 854240Smckusick argv++; 864240Smckusick if (**argv=='-') 874240Smckusick switch ((*argv)[1]) { 884240Smckusick case 'd': 894240Smckusick dflg++; 904240Smckusick continue; 914240Smckusick 924240Smckusick case 'm': 934240Smckusick mflg++; 944240Smckusick continue; 954240Smckusick 964240Smckusick case 'b': 974240Smckusick for(i=0; i<NB; i++) { 984240Smckusick n = atol(argv[1]); 994240Smckusick if(n == 0) 1004240Smckusick break; 1014240Smckusick blist[i] = n; 1024240Smckusick argv++; 1034240Smckusick argc--; 1044240Smckusick } 1054240Smckusick blist[i] = -1; 1064240Smckusick continue; 1074240Smckusick 1084240Smckusick default: 1094240Smckusick printf("Bad flag\n"); 1104240Smckusick } 1114240Smckusick check(*argv); 1124240Smckusick } 1134240Smckusick #else 1144240Smckusick { 1154240Smckusick static char fname[128]; 1164240Smckusick 1174240Smckusick printf("File: "); 1184240Smckusick gets(fname); 1194240Smckusick check(fname); 1204240Smckusick } 1214240Smckusick #endif 1224240Smckusick return(nerror); 1234240Smckusick } 1244240Smckusick 1254240Smckusick check(file) 1265098Smckusic char *file; 1274240Smckusick { 1284240Smckusick register i, j, c; 1294240Smckusick daddr_t d, cgd, cbase, b; 1304240Smckusick long n; 1319298Smckusick char buf[BUFSIZ]; 1324240Smckusick 133*34148Smckusick fi = open(file, 0); 1344240Smckusick if (fi < 0) { 1355098Smckusic perror(file); 1364240Smckusick nerror |= 04; 1374240Smckusick return; 1384240Smckusick } 1394240Smckusick printf("%s:\n", file); 1404240Smckusick nrfile = 0; 1414240Smckusick ndfile = 0; 1424240Smckusick ncfile = 0; 1434240Smckusick nbfile = 0; 1446286Smckusick nlfile = 0; 145*34148Smckusick nsfile = 0; 1464240Smckusick 1474240Smckusick nblock = 0; 1484240Smckusick nfrag = 0; 1494240Smckusick nindir = 0; 1504240Smckusick niindir = 0; 1514240Smckusick 1524240Smckusick ndup = 0; 1534240Smckusick #ifndef STANDALONE 1544240Smckusick sync(); 1554240Smckusick #endif 1565326Smckusic getsb(&sblock, file); 1575326Smckusic if (nerror) 1584240Smckusick return; 1599298Smckusick for (n=0; blist[n] != -1; n++) 1609298Smckusick fsblist[n] = dbtofsb(&sblock, blist[n]); 1614240Smckusick ino = 0; 1625098Smckusic n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short)); 1634240Smckusick #ifdef STANDALONE 1644240Smckusick bmap = NULL; 1654240Smckusick #else 1664240Smckusick bmap = malloc((unsigned)n); 1674240Smckusick #endif 1684240Smckusick if (bmap==NULL) { 1694240Smckusick printf("Not enough core; duplicates unchecked\n"); 1704240Smckusick dflg++; 1714240Smckusick } 1724240Smckusick ino = 0; 1734240Smckusick cginit = 1; 1746534Smckusick if (!dflg) { 1756534Smckusick for (i = 0; i < (unsigned)n; i++) 1764240Smckusick bmap[i] = 0; 1776534Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1785382Smckusic cgd = cgtod(&sblock, c); 1796534Smckusick if (c == 0) 1806534Smckusick d = cgbase(&sblock, c); 1816534Smckusick else 1826534Smckusick d = cgsblock(&sblock, c); 18332441Sbostic (void)sprintf(buf, "spare super block %d", c); 1846534Smckusick for (; d < cgd; d += sblock.fs_frag) 1859298Smckusick chk(d, buf, sblock.fs_bsize); 1865382Smckusic d = cgimin(&sblock, c); 18732441Sbostic (void)sprintf(buf, "cylinder group %d", c); 1884240Smckusick while (cgd < d) { 1899298Smckusick chk(cgd, buf, sblock.fs_bsize); 1905326Smckusic cgd += sblock.fs_frag; 1914240Smckusick } 1925382Smckusic d = cgdmin(&sblock, c); 1939298Smckusick i = INOPB(&sblock); 1949298Smckusick for (; cgd < d; cgd += sblock.fs_frag) { 19532441Sbostic (void)sprintf(buf, "inodes %d-%d", ino, ino + i); 1969298Smckusick chk(cgd, buf, sblock.fs_bsize); 1979298Smckusick ino += i; 1989298Smckusick } 1994240Smckusick if (c == 0) { 2006534Smckusick d += howmany(sblock.fs_cssize, sblock.fs_fsize); 2016534Smckusick for (; cgd < d; cgd++) 2026534Smckusick chk(cgd, "csum", sblock.fs_fsize); 2034240Smckusick } 2044240Smckusick } 2054240Smckusick } 2069298Smckusick ino = 0; 2074240Smckusick cginit = 0; 2084240Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 209*34148Smckusick for (i = 0; 210*34148Smckusick i < sblock.fs_ipg / INOPF(&sblock); 211*34148Smckusick i += sblock.fs_frag) { 212*34148Smckusick bread(fsbtodb(&sblock, cgimin(&sblock, c) + i), 213*34148Smckusick (char *)itab, sblock.fs_bsize); 214*34148Smckusick for (j = 0; j < INOPB(&sblock); j++) { 215*34148Smckusick pass1(&itab[j]); 216*34148Smckusick ino++; 217*34148Smckusick } 2184240Smckusick } 2194240Smckusick } 2204240Smckusick ino = 0; 2214240Smckusick #ifndef STANDALONE 2224240Smckusick sync(); 2234240Smckusick #endif 2244240Smckusick nffree = 0; 2254240Smckusick nbfree = 0; 2264240Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 2275382Smckusic cbase = cgbase(&sblock, c); 2285382Smckusic bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp, 2295326Smckusic sblock.fs_cgsize); 230*34148Smckusick if (!cg_chkmagic(&cgrp)) 2316534Smckusick printf("cg %d: bad magic number\n", c); 2325326Smckusic for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 233*34148Smckusick if (isblock(&sblock, cg_blksfree(&cgrp), 2345326Smckusic b / sblock.fs_frag)) { 2354240Smckusick nbfree++; 2369298Smckusick chk(cbase+b, "free block", sblock.fs_bsize); 2374240Smckusick } else { 2385326Smckusic for (d = 0; d < sblock.fs_frag; d++) 239*34148Smckusick if (isset(cg_blksfree(&cgrp), b+d)) { 2409298Smckusick chk(cbase+b+d, "free frag", sblock.fs_fsize); 2414240Smckusick nffree++; 2424240Smckusick } 2434240Smckusick } 2444240Smckusick } 2454240Smckusick } 2464240Smckusick close(fi); 2474240Smckusick #ifndef STANDALONE 2484240Smckusick if (bmap) 2494240Smckusick free(bmap); 2504240Smckusick #endif 2514240Smckusick 252*34148Smckusick i = nrfile + ndfile + ncfile + nbfile + nlfile + nsfile; 2534240Smckusick #ifndef STANDALONE 254*34148Smckusick printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 255*34148Smckusick i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 2564240Smckusick #else 257*34148Smckusick printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 258*34148Smckusick i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 2594240Smckusick #endif 2605326Smckusic n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag; 2614240Smckusick #ifdef STANDALONE 2624240Smckusick printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 2634240Smckusick n, nindir, niindir, nblock, nfrag); 2645326Smckusic printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 2654240Smckusick nbfree, nffree); 2664240Smckusick #else 2674240Smckusick printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 2684240Smckusick n, nindir, niindir, nblock, nfrag); 2695326Smckusic printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 2704240Smckusick nbfree, nffree); 2714240Smckusick #endif 2724240Smckusick if(!dflg) { 2734240Smckusick n = 0; 2744410Smckusic for (d = 0; d < sblock.fs_size; d++) 2755326Smckusic if(!duped(d, sblock.fs_fsize)) { 2764240Smckusick if(mflg) 2774240Smckusick printf("%ld missing\n", d); 2784240Smckusick n++; 2794240Smckusick } 2804240Smckusick printf("missing%5ld\n", n); 2814240Smckusick } 2824240Smckusick } 2834240Smckusick 2844240Smckusick pass1(ip) 2854410Smckusic register struct dinode *ip; 2864240Smckusick { 2875326Smckusic daddr_t ind1[MAXNINDIR]; 2885326Smckusic daddr_t ind2[MAXNINDIR]; 2894429Smckusic daddr_t db, ib; 2904429Smckusic register int i, j, k, siz; 2919298Smckusick int lbn; 2929298Smckusick char buf[BUFSIZ]; 2934240Smckusick 2944240Smckusick i = ip->di_mode & IFMT; 2954790Smckusic if(i == 0) 2964240Smckusick return; 2974240Smckusick switch (i) { 2984240Smckusick case IFCHR: 2994240Smckusick ncfile++; 3004240Smckusick return; 3014240Smckusick case IFBLK: 3024240Smckusick nbfile++; 3034240Smckusick return; 3044240Smckusick case IFDIR: 3054240Smckusick ndfile++; 3064240Smckusick break; 3074240Smckusick case IFREG: 3084240Smckusick nrfile++; 3094240Smckusick break; 310*34148Smckusick case IFSOCK: 311*34148Smckusick nsfile++; 312*34148Smckusick break; 3136286Smckusick case IFLNK: 3146286Smckusick nlfile++; 3156286Smckusick break; 3164240Smckusick default: 3174240Smckusick printf("bad mode %u\n", ino); 3184240Smckusick return; 3194240Smckusick } 3204410Smckusic for (i = 0; i < NDADDR; i++) { 3214410Smckusic db = ip->di_db[i]; 3224410Smckusic if (db == 0) 3234240Smckusick continue; 3245326Smckusic siz = dblksize(&sblock, ip, i); 32532441Sbostic (void)sprintf(buf, "logical data block %d", i); 3269298Smckusick chk(db, buf, siz); 3275326Smckusic if (siz == sblock.fs_bsize) 3284429Smckusic nblock++; 3294429Smckusic else 3305326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3314240Smckusick } 3324410Smckusic for(i = 0; i < NIADDR; i++) { 3334410Smckusic ib = ip->di_ib[i]; 3349298Smckusick if (ib == 0) 3354240Smckusick continue; 3365326Smckusic if (chk(ib, "1st indirect", sblock.fs_bsize)) 3374410Smckusic continue; 3385326Smckusic bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); 3394240Smckusick nindir++; 3405326Smckusic for (j = 0; j < NINDIR(&sblock); j++) { 3414410Smckusic ib = ind1[j]; 3424410Smckusic if (ib == 0) 3434240Smckusick continue; 3444410Smckusic if (i == 0) { 3459298Smckusick lbn = NDADDR + j; 3469298Smckusick siz = dblksize(&sblock, ip, lbn); 34732441Sbostic (void)sprintf(buf, "logical data block %d", lbn); 3489298Smckusick chk(ib, buf, siz); 3495326Smckusic if (siz == sblock.fs_bsize) 3504429Smckusic nblock++; 3514429Smckusic else 3525326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3534240Smckusick continue; 3544240Smckusick } 3555326Smckusic if (chk(ib, "2nd indirect", sblock.fs_bsize)) 3564410Smckusic continue; 3575326Smckusic bread(fsbtodb(&sblock, ib), (char *)ind2, 3585326Smckusic sblock.fs_bsize); 3594240Smckusick niindir++; 3605326Smckusic for (k = 0; k < NINDIR(&sblock); k++) { 3614410Smckusic ib = ind2[k]; 3624410Smckusic if (ib == 0) 3634240Smckusick continue; 3649298Smckusick lbn = NDADDR + NINDIR(&sblock) * (i + j) + k; 3659298Smckusick siz = dblksize(&sblock, ip, lbn); 36632441Sbostic (void)sprintf(buf, "logical data block %d", lbn); 3679298Smckusick chk(ib, buf, siz); 3685326Smckusic if (siz == sblock.fs_bsize) 3694429Smckusic nblock++; 3704429Smckusic else 3715326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3724240Smckusick } 3734240Smckusick } 3744240Smckusick } 3754240Smckusick } 3764240Smckusick 3774429Smckusic chk(bno, s, size) 3784410Smckusic daddr_t bno; 3794410Smckusic char *s; 3804429Smckusic int size; 3814240Smckusick { 3824240Smckusick register n, cg; 3835957Smckusic int frags; 3844240Smckusick 3855382Smckusic cg = dtog(&sblock, bno); 3866534Smckusick if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) { 3874240Smckusick printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 3884240Smckusick return(1); 3894240Smckusick } 3909298Smckusick frags = numfrags(&sblock, size); 3919298Smckusick if (frags == sblock.fs_frag) { 3924429Smckusic if (duped(bno, size)) { 3934429Smckusic printf("%ld dup block; inode=%u, class=%s\n", 3944429Smckusic bno, ino, s); 3955326Smckusic ndup += sblock.fs_frag; 3964429Smckusic } 3974429Smckusic } else { 3985957Smckusic for (n = 0; n < frags; n++) { 3995326Smckusic if (duped(bno + n, sblock.fs_fsize)) { 4004429Smckusic printf("%ld dup frag; inode=%u, class=%s\n", 4014429Smckusic bno, ino, s); 4024429Smckusic ndup++; 4034429Smckusic } 4044429Smckusic } 4054240Smckusick } 4064240Smckusick for (n=0; blist[n] != -1; n++) 4079298Smckusick if (fsblist[n] >= bno && fsblist[n] < bno + frags) 4089298Smckusick printf("%ld arg; frag %d of %d, inode=%u, class=%s\n", 4099298Smckusick blist[n], fsblist[n] - bno, frags, ino, s); 4104240Smckusick return(0); 4114240Smckusick } 4124240Smckusick 4134429Smckusic duped(bno, size) 4144410Smckusic daddr_t bno; 4154429Smckusic int size; 4164240Smckusick { 4174240Smckusick if(dflg) 4184240Smckusick return(0); 4195326Smckusic if (size != sblock.fs_fsize && size != sblock.fs_bsize) 4204429Smckusic printf("bad size %d to duped\n", size); 4215326Smckusic if (size == sblock.fs_fsize) { 4224410Smckusic if (isset(bmap, bno)) 4234410Smckusic return(1); 4244410Smckusic setbit(bmap, bno); 4254410Smckusic return (0); 4264410Smckusic } 4275326Smckusic if (bno % sblock.fs_frag != 0) 4284410Smckusic printf("bad bno %d to duped\n", bno); 4295326Smckusic if (isblock(&sblock, bmap, bno/sblock.fs_frag)) 4304410Smckusic return (1); 4315326Smckusic setblock(&sblock, bmap, bno/sblock.fs_frag); 4324240Smckusick return(0); 4334240Smckusick } 4344240Smckusick 4355326Smckusic getsb(fs, file) 4365326Smckusic register struct fs *fs; 4375326Smckusic char *file; 4385326Smckusic { 4396534Smckusick int i, j, size; 4405326Smckusic 44130558Smckusick if (bread(SBOFF, fs, SBSIZE)) { 4425326Smckusic printf("bad super block"); 4435326Smckusic perror(file); 4445326Smckusic nerror |= 04; 4455326Smckusic return; 4465326Smckusic } 4475326Smckusic if (fs->fs_magic != FS_MAGIC) { 4485326Smckusic printf("%s: bad magic number\n", file); 4495326Smckusic nerror |= 04; 4505326Smckusic return; 4515326Smckusic } 45230558Smckusick dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 4536534Smckusick for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 4546534Smckusick size = sblock.fs_cssize - i < sblock.fs_bsize ? 4556534Smckusick sblock.fs_cssize - i : sblock.fs_bsize; 4566534Smckusick sblock.fs_csp[j] = (struct csum *)calloc(1, size); 4576534Smckusick bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)), 4586534Smckusick (char *)fs->fs_csp[j], size); 4595326Smckusic } 4605326Smckusic } 4615326Smckusic 4624240Smckusick bread(bno, buf, cnt) 4634410Smckusic daddr_t bno; 4644410Smckusic char *buf; 4654240Smckusick { 4664240Smckusick register i; 4674240Smckusick 46830558Smckusick lseek(fi, bno * dev_bsize, 0); 4694240Smckusick if ((i = read(fi, buf, cnt)) != cnt) { 4705326Smckusic for(i=0; i<sblock.fs_bsize; i++) 4714240Smckusick buf[i] = 0; 4725326Smckusic return (1); 4734240Smckusick } 4745326Smckusic return (0); 4754240Smckusick } 4765326Smckusic 4775326Smckusic /* 4788143Smckusick * check if a block is available 4795326Smckusic */ 4805326Smckusic isblock(fs, cp, h) 4815326Smckusic struct fs *fs; 4825326Smckusic unsigned char *cp; 4835326Smckusic int h; 4845326Smckusic { 4855326Smckusic unsigned char mask; 4865326Smckusic 4875326Smckusic switch (fs->fs_frag) { 4885326Smckusic case 8: 4895326Smckusic return (cp[h] == 0xff); 4905326Smckusic case 4: 4915326Smckusic mask = 0x0f << ((h & 0x1) << 2); 4925326Smckusic return ((cp[h >> 1] & mask) == mask); 4935326Smckusic case 2: 4945326Smckusic mask = 0x03 << ((h & 0x3) << 1); 4955326Smckusic return ((cp[h >> 2] & mask) == mask); 4965326Smckusic case 1: 4975326Smckusic mask = 0x01 << (h & 0x7); 4985326Smckusic return ((cp[h >> 3] & mask) == mask); 4995326Smckusic default: 5008143Smckusick #ifdef STANDALONE 5018143Smckusick printf("isblock bad fs_frag %d\n", fs->fs_frag); 5028143Smckusick #else 5035326Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 5048143Smckusick #endif 5055326Smckusic return; 5065326Smckusic } 5075326Smckusic } 5085326Smckusic 5098143Smckusick /* 5108143Smckusick * put a block into the map 5118143Smckusick */ 5125326Smckusic setblock(fs, cp, h) 5135326Smckusic struct fs *fs; 5145326Smckusic unsigned char *cp; 5155326Smckusic int h; 5165326Smckusic { 5175326Smckusic switch (fs->fs_frag) { 5185326Smckusic case 8: 5195326Smckusic cp[h] = 0xff; 5205326Smckusic return; 5215326Smckusic case 4: 5225326Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 5235326Smckusic return; 5245326Smckusic case 2: 5255326Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 5265326Smckusic return; 5275326Smckusic case 1: 5285326Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 5295326Smckusic return; 5305326Smckusic default: 5318143Smckusick #ifdef STANDALONE 5328143Smckusick printf("setblock bad fs_frag %d\n", fs->fs_frag); 5338143Smckusick #else 5345326Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 5358143Smckusick #endif 5365326Smckusic return; 5375326Smckusic } 5385326Smckusic } 539