148404Sbostic /*- 248404Sbostic * Copyright (c) 1988 The Regents of the University of California. 348404Sbostic * All rights reserved. 448404Sbostic * 548404Sbostic * %sccs.include.proprietary.c% 621133Sdist */ 74410Smckusic 821133Sdist #ifndef lint 948404Sbostic char copyright[] = 1048404Sbostic "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ 1148404Sbostic All rights reserved.\n"; 1248404Sbostic #endif /* not lint */ 1321133Sdist 1448404Sbostic #ifndef lint 15*57999Sralph static char sccsid[] = "@(#)icheck.c 5.11 (Berkeley) 02/15/93"; 1648404Sbostic #endif /* not lint */ 1748404Sbostic 184240Smckusick /* 194240Smckusick * icheck 204240Smckusick */ 214240Smckusick #define NB 500 224240Smckusick #define MAXFN 500 235349Smckusic #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 244240Smckusick 2538509Sbostic #include <sys/param.h> 2653733Smckusick #include <sys/time.h> 2751619Sbostic #include <ufs/ufs/dinode.h> 2851619Sbostic #include <ufs/ffs/fs.h> 294240Smckusick #ifndef STANDALONE 30*57999Sralph #include <unistd.h> 314240Smckusick #include <stdio.h> 324240Smckusick #endif 334240Smckusick 344240Smckusick union { 354240Smckusick struct fs sb; 3634148Smckusick char pad[SBSIZE]; 374240Smckusick } sbun; 384240Smckusick #define sblock sbun.sb 394240Smckusick 404240Smckusick union { 414240Smckusick struct cg cg; 425326Smckusic char pad[MAXBSIZE]; 434240Smckusick } cgun; 444240Smckusick #define cgrp cgun.cg 454240Smckusick 4634148Smckusick struct dinode itab[MAXBSIZE / sizeof(struct dinode)]; 4734148Smckusick 484240Smckusick daddr_t blist[NB]; 499298Smckusick daddr_t fsblist[NB]; 504240Smckusick char *bmap; 514240Smckusick 524240Smckusick int mflg; 534240Smckusick int dflg; 544240Smckusick int fi; 554240Smckusick ino_t ino; 564240Smckusick int cginit; 574240Smckusick 584240Smckusick ino_t nrfile; 594240Smckusick ino_t ndfile; 604240Smckusick ino_t nbfile; 614240Smckusick ino_t ncfile; 626286Smckusick ino_t nlfile; 6334148Smckusick ino_t nsfile; 644240Smckusick 654240Smckusick daddr_t nblock; 664240Smckusick daddr_t nfrag; 674240Smckusick daddr_t nindir; 684240Smckusick daddr_t niindir; 694240Smckusick 704240Smckusick daddr_t nffree; 714240Smckusick daddr_t nbfree; 724240Smckusick 734240Smckusick daddr_t ndup; 744240Smckusick 754240Smckusick int nerror; 7630558Smckusick long dev_bsize = 1; 774240Smckusick 784240Smckusick long atol(); 794240Smckusick #ifndef STANDALONE 804240Smckusick char *malloc(); 815098Smckusic char *calloc(); 824240Smckusick #endif 834240Smckusick 844240Smckusick main(argc, argv) 855098Smckusic int argc; 865098Smckusic char *argv[]; 874240Smckusick { 884240Smckusick register i; 894240Smckusick long n; 904240Smckusick 914240Smckusick blist[0] = -1; 924240Smckusick #ifndef STANDALONE 934240Smckusick while (--argc) { 944240Smckusick argv++; 954240Smckusick if (**argv=='-') 964240Smckusick switch ((*argv)[1]) { 974240Smckusick case 'd': 984240Smckusick dflg++; 994240Smckusick continue; 1004240Smckusick 1014240Smckusick case 'm': 1024240Smckusick mflg++; 1034240Smckusick continue; 1044240Smckusick 1054240Smckusick case 'b': 10653026Sbostic for(i=0; i<NB && argc >= 2; i++) { 1074240Smckusick n = atol(argv[1]); 1084240Smckusick if(n == 0) 1094240Smckusick break; 1104240Smckusick blist[i] = n; 1114240Smckusick argv++; 1124240Smckusick argc--; 1134240Smckusick } 1144240Smckusick blist[i] = -1; 1154240Smckusick continue; 1164240Smckusick 1174240Smckusick default: 1184240Smckusick printf("Bad flag\n"); 1194240Smckusick } 1204240Smckusick check(*argv); 1214240Smckusick } 1224240Smckusick #else 1234240Smckusick { 1244240Smckusick static char fname[128]; 1254240Smckusick 1264240Smckusick printf("File: "); 1274240Smckusick gets(fname); 1284240Smckusick check(fname); 1294240Smckusick } 1304240Smckusick #endif 1314240Smckusick return(nerror); 1324240Smckusick } 1334240Smckusick 1344240Smckusick check(file) 1355098Smckusic char *file; 1364240Smckusick { 1374240Smckusick register i, j, c; 1384240Smckusick daddr_t d, cgd, cbase, b; 1394240Smckusick long n; 1409298Smckusick char buf[BUFSIZ]; 1414240Smckusick 14234148Smckusick fi = open(file, 0); 1434240Smckusick if (fi < 0) { 1445098Smckusic perror(file); 1454240Smckusick nerror |= 04; 1464240Smckusick return; 1474240Smckusick } 1484240Smckusick printf("%s:\n", file); 1494240Smckusick nrfile = 0; 1504240Smckusick ndfile = 0; 1514240Smckusick ncfile = 0; 1524240Smckusick nbfile = 0; 1536286Smckusick nlfile = 0; 15434148Smckusick nsfile = 0; 1554240Smckusick 1564240Smckusick nblock = 0; 1574240Smckusick nfrag = 0; 1584240Smckusick nindir = 0; 1594240Smckusick niindir = 0; 1604240Smckusick 1614240Smckusick ndup = 0; 1624240Smckusick #ifndef STANDALONE 1634240Smckusick sync(); 1644240Smckusick #endif 1655326Smckusic getsb(&sblock, file); 1665326Smckusic if (nerror) 1674240Smckusick return; 1689298Smckusick for (n=0; blist[n] != -1; n++) 1699298Smckusick fsblist[n] = dbtofsb(&sblock, blist[n]); 1704240Smckusick ino = 0; 1715098Smckusic n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short)); 1724240Smckusick #ifdef STANDALONE 1734240Smckusick bmap = NULL; 1744240Smckusick #else 1754240Smckusick bmap = malloc((unsigned)n); 1764240Smckusick #endif 1774240Smckusick if (bmap==NULL) { 1784240Smckusick printf("Not enough core; duplicates unchecked\n"); 1794240Smckusick dflg++; 1804240Smckusick } 1814240Smckusick ino = 0; 1824240Smckusick cginit = 1; 1836534Smckusick if (!dflg) { 1846534Smckusick for (i = 0; i < (unsigned)n; i++) 1854240Smckusick bmap[i] = 0; 1866534Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1875382Smckusic cgd = cgtod(&sblock, c); 1886534Smckusick if (c == 0) 1896534Smckusick d = cgbase(&sblock, c); 1906534Smckusick else 1916534Smckusick d = cgsblock(&sblock, c); 19232441Sbostic (void)sprintf(buf, "spare super block %d", c); 1936534Smckusick for (; d < cgd; d += sblock.fs_frag) 1949298Smckusick chk(d, buf, sblock.fs_bsize); 1955382Smckusic d = cgimin(&sblock, c); 19632441Sbostic (void)sprintf(buf, "cylinder group %d", c); 1974240Smckusick while (cgd < d) { 1989298Smckusick chk(cgd, buf, sblock.fs_bsize); 1995326Smckusic cgd += sblock.fs_frag; 2004240Smckusick } 2015382Smckusic d = cgdmin(&sblock, c); 2029298Smckusick i = INOPB(&sblock); 2039298Smckusick for (; cgd < d; cgd += sblock.fs_frag) { 20432441Sbostic (void)sprintf(buf, "inodes %d-%d", ino, ino + i); 2059298Smckusick chk(cgd, buf, sblock.fs_bsize); 2069298Smckusick ino += i; 2079298Smckusick } 2084240Smckusick if (c == 0) { 2096534Smckusick d += howmany(sblock.fs_cssize, sblock.fs_fsize); 2106534Smckusick for (; cgd < d; cgd++) 2116534Smckusick chk(cgd, "csum", sblock.fs_fsize); 2124240Smckusick } 2134240Smckusick } 2144240Smckusick } 2159298Smckusick ino = 0; 2164240Smckusick cginit = 0; 2174240Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 21834148Smckusick for (i = 0; 21934148Smckusick i < sblock.fs_ipg / INOPF(&sblock); 22034148Smckusick i += sblock.fs_frag) { 22134148Smckusick bread(fsbtodb(&sblock, cgimin(&sblock, c) + i), 22234148Smckusick (char *)itab, sblock.fs_bsize); 22334148Smckusick for (j = 0; j < INOPB(&sblock); j++) { 22434148Smckusick pass1(&itab[j]); 22534148Smckusick ino++; 22634148Smckusick } 2274240Smckusick } 2284240Smckusick } 2294240Smckusick ino = 0; 2304240Smckusick #ifndef STANDALONE 2314240Smckusick sync(); 2324240Smckusick #endif 2334240Smckusick nffree = 0; 2344240Smckusick nbfree = 0; 2354240Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 2365382Smckusic cbase = cgbase(&sblock, c); 2375382Smckusic bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp, 2385326Smckusic sblock.fs_cgsize); 23934148Smckusick if (!cg_chkmagic(&cgrp)) 2406534Smckusick printf("cg %d: bad magic number\n", c); 2415326Smckusic for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 24234148Smckusick if (isblock(&sblock, cg_blksfree(&cgrp), 2435326Smckusic b / sblock.fs_frag)) { 2444240Smckusick nbfree++; 2459298Smckusick chk(cbase+b, "free block", sblock.fs_bsize); 2464240Smckusick } else { 2475326Smckusic for (d = 0; d < sblock.fs_frag; d++) 24834148Smckusick if (isset(cg_blksfree(&cgrp), b+d)) { 2499298Smckusick chk(cbase+b+d, "free frag", sblock.fs_fsize); 2504240Smckusick nffree++; 2514240Smckusick } 2524240Smckusick } 2534240Smckusick } 2544240Smckusick } 2554240Smckusick close(fi); 2564240Smckusick #ifndef STANDALONE 2574240Smckusick if (bmap) 2584240Smckusick free(bmap); 2594240Smckusick #endif 2604240Smckusick 26134148Smckusick i = nrfile + ndfile + ncfile + nbfile + nlfile + nsfile; 2624240Smckusick #ifndef STANDALONE 26334148Smckusick printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 26434148Smckusick i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 2654240Smckusick #else 26634148Smckusick printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 26734148Smckusick i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 2684240Smckusick #endif 2695326Smckusic n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag; 2704240Smckusick #ifdef STANDALONE 2714240Smckusick printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 2724240Smckusick n, nindir, niindir, nblock, nfrag); 2735326Smckusic printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 2744240Smckusick nbfree, nffree); 2754240Smckusick #else 2764240Smckusick printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 2774240Smckusick n, nindir, niindir, nblock, nfrag); 2785326Smckusic printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 2794240Smckusick nbfree, nffree); 2804240Smckusick #endif 2814240Smckusick if(!dflg) { 2824240Smckusick n = 0; 2834410Smckusic for (d = 0; d < sblock.fs_size; d++) 2845326Smckusic if(!duped(d, sblock.fs_fsize)) { 2854240Smckusick if(mflg) 2864240Smckusick printf("%ld missing\n", d); 2874240Smckusick n++; 2884240Smckusick } 2894240Smckusick printf("missing%5ld\n", n); 2904240Smckusick } 2914240Smckusick } 2924240Smckusick 2934240Smckusick pass1(ip) 2944410Smckusic register struct dinode *ip; 2954240Smckusick { 2965326Smckusic daddr_t ind1[MAXNINDIR]; 2975326Smckusic daddr_t ind2[MAXNINDIR]; 2984429Smckusic daddr_t db, ib; 2994429Smckusic register int i, j, k, siz; 3009298Smckusick int lbn; 3019298Smckusick char buf[BUFSIZ]; 3024240Smckusick 3034240Smckusick i = ip->di_mode & IFMT; 3044790Smckusic if(i == 0) 3054240Smckusick return; 3064240Smckusick switch (i) { 3074240Smckusick case IFCHR: 3084240Smckusick ncfile++; 3094240Smckusick return; 3104240Smckusick case IFBLK: 3114240Smckusick nbfile++; 3124240Smckusick return; 3134240Smckusick case IFDIR: 3144240Smckusick ndfile++; 3154240Smckusick break; 3164240Smckusick case IFREG: 3174240Smckusick nrfile++; 3184240Smckusick break; 31934148Smckusick case IFSOCK: 32034148Smckusick nsfile++; 32134148Smckusick break; 3226286Smckusick case IFLNK: 3236286Smckusick nlfile++; 3246286Smckusick break; 3254240Smckusick default: 3264240Smckusick printf("bad mode %u\n", ino); 3274240Smckusick return; 3284240Smckusick } 3294410Smckusic for (i = 0; i < NDADDR; i++) { 3304410Smckusic db = ip->di_db[i]; 3314410Smckusic if (db == 0) 3324240Smckusick continue; 3335326Smckusic siz = dblksize(&sblock, ip, i); 33432441Sbostic (void)sprintf(buf, "logical data block %d", i); 3359298Smckusick chk(db, buf, siz); 3365326Smckusic if (siz == sblock.fs_bsize) 3374429Smckusic nblock++; 3384429Smckusic else 3395326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3404240Smckusick } 3414410Smckusic for(i = 0; i < NIADDR; i++) { 3424410Smckusic ib = ip->di_ib[i]; 3439298Smckusick if (ib == 0) 3444240Smckusick continue; 3455326Smckusic if (chk(ib, "1st indirect", sblock.fs_bsize)) 3464410Smckusic continue; 3475326Smckusic bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); 3484240Smckusick nindir++; 3495326Smckusic for (j = 0; j < NINDIR(&sblock); j++) { 3504410Smckusic ib = ind1[j]; 3514410Smckusic if (ib == 0) 3524240Smckusick continue; 3534410Smckusic if (i == 0) { 3549298Smckusick lbn = NDADDR + j; 3559298Smckusick siz = dblksize(&sblock, ip, lbn); 35632441Sbostic (void)sprintf(buf, "logical data block %d", lbn); 3579298Smckusick chk(ib, buf, siz); 3585326Smckusic if (siz == sblock.fs_bsize) 3594429Smckusic nblock++; 3604429Smckusic else 3615326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3624240Smckusick continue; 3634240Smckusick } 3645326Smckusic if (chk(ib, "2nd indirect", sblock.fs_bsize)) 3654410Smckusic continue; 3665326Smckusic bread(fsbtodb(&sblock, ib), (char *)ind2, 3675326Smckusic sblock.fs_bsize); 3684240Smckusick niindir++; 3695326Smckusic for (k = 0; k < NINDIR(&sblock); k++) { 3704410Smckusic ib = ind2[k]; 3714410Smckusic if (ib == 0) 3724240Smckusick continue; 3739298Smckusick lbn = NDADDR + NINDIR(&sblock) * (i + j) + k; 3749298Smckusick siz = dblksize(&sblock, ip, lbn); 37532441Sbostic (void)sprintf(buf, "logical data block %d", lbn); 3769298Smckusick chk(ib, buf, siz); 3775326Smckusic if (siz == sblock.fs_bsize) 3784429Smckusic nblock++; 3794429Smckusic else 3805326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3814240Smckusick } 3824240Smckusick } 3834240Smckusick } 3844240Smckusick } 3854240Smckusick 3864429Smckusic chk(bno, s, size) 3874410Smckusic daddr_t bno; 3884410Smckusic char *s; 3894429Smckusic int size; 3904240Smckusick { 3914240Smckusick register n, cg; 3925957Smckusic int frags; 3934240Smckusick 3945382Smckusic cg = dtog(&sblock, bno); 3956534Smckusick if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) { 3964240Smckusick printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 3974240Smckusick return(1); 3984240Smckusick } 3999298Smckusick frags = numfrags(&sblock, size); 4009298Smckusick if (frags == sblock.fs_frag) { 4014429Smckusic if (duped(bno, size)) { 4024429Smckusic printf("%ld dup block; inode=%u, class=%s\n", 4034429Smckusic bno, ino, s); 4045326Smckusic ndup += sblock.fs_frag; 4054429Smckusic } 4064429Smckusic } else { 4075957Smckusic for (n = 0; n < frags; n++) { 4085326Smckusic if (duped(bno + n, sblock.fs_fsize)) { 4094429Smckusic printf("%ld dup frag; inode=%u, class=%s\n", 4104429Smckusic bno, ino, s); 4114429Smckusic ndup++; 4124429Smckusic } 4134429Smckusic } 4144240Smckusick } 4154240Smckusick for (n=0; blist[n] != -1; n++) 4169298Smckusick if (fsblist[n] >= bno && fsblist[n] < bno + frags) 4179298Smckusick printf("%ld arg; frag %d of %d, inode=%u, class=%s\n", 4189298Smckusick blist[n], fsblist[n] - bno, frags, ino, s); 4194240Smckusick return(0); 4204240Smckusick } 4214240Smckusick 4224429Smckusic duped(bno, size) 4234410Smckusic daddr_t bno; 4244429Smckusic int size; 4254240Smckusick { 4264240Smckusick if(dflg) 4274240Smckusick return(0); 4285326Smckusic if (size != sblock.fs_fsize && size != sblock.fs_bsize) 4294429Smckusic printf("bad size %d to duped\n", size); 4305326Smckusic if (size == sblock.fs_fsize) { 4314410Smckusic if (isset(bmap, bno)) 4324410Smckusic return(1); 4334410Smckusic setbit(bmap, bno); 4344410Smckusic return (0); 4354410Smckusic } 4365326Smckusic if (bno % sblock.fs_frag != 0) 4374410Smckusic printf("bad bno %d to duped\n", bno); 4385326Smckusic if (isblock(&sblock, bmap, bno/sblock.fs_frag)) 4394410Smckusic return (1); 4405326Smckusic setblock(&sblock, bmap, bno/sblock.fs_frag); 4414240Smckusick return(0); 4424240Smckusick } 4434240Smckusick 4445326Smckusic getsb(fs, file) 4455326Smckusic register struct fs *fs; 4465326Smckusic char *file; 4475326Smckusic { 4486534Smckusick int i, j, size; 4495326Smckusic 45030558Smckusick if (bread(SBOFF, fs, SBSIZE)) { 4515326Smckusic printf("bad super block"); 4525326Smckusic perror(file); 4535326Smckusic nerror |= 04; 4545326Smckusic return; 4555326Smckusic } 4565326Smckusic if (fs->fs_magic != FS_MAGIC) { 4575326Smckusic printf("%s: bad magic number\n", file); 4585326Smckusic nerror |= 04; 4595326Smckusic return; 4605326Smckusic } 46130558Smckusick dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 4626534Smckusick for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 4636534Smckusick size = sblock.fs_cssize - i < sblock.fs_bsize ? 4646534Smckusick sblock.fs_cssize - i : sblock.fs_bsize; 4656534Smckusick sblock.fs_csp[j] = (struct csum *)calloc(1, size); 4666534Smckusick bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)), 4676534Smckusick (char *)fs->fs_csp[j], size); 4685326Smckusic } 4695326Smckusic } 4705326Smckusic 4714240Smckusick bread(bno, buf, cnt) 4724410Smckusic daddr_t bno; 4734410Smckusic char *buf; 4744240Smckusick { 4754240Smckusick register i; 4764240Smckusick 477*57999Sralph lseek(fi, (off_t)bno * dev_bsize, SEEK_SET); 4784240Smckusick if ((i = read(fi, buf, cnt)) != cnt) { 479*57999Sralph for (i = 0; i < sblock.fs_bsize; i++) 4804240Smckusick buf[i] = 0; 4815326Smckusic return (1); 4824240Smckusick } 4835326Smckusic return (0); 4844240Smckusick } 4855326Smckusic 4865326Smckusic /* 4878143Smckusick * check if a block is available 4885326Smckusic */ 4895326Smckusic isblock(fs, cp, h) 4905326Smckusic struct fs *fs; 4915326Smckusic unsigned char *cp; 4925326Smckusic int h; 4935326Smckusic { 4945326Smckusic unsigned char mask; 4955326Smckusic 4965326Smckusic switch (fs->fs_frag) { 4975326Smckusic case 8: 4985326Smckusic return (cp[h] == 0xff); 4995326Smckusic case 4: 5005326Smckusic mask = 0x0f << ((h & 0x1) << 2); 5015326Smckusic return ((cp[h >> 1] & mask) == mask); 5025326Smckusic case 2: 5035326Smckusic mask = 0x03 << ((h & 0x3) << 1); 5045326Smckusic return ((cp[h >> 2] & mask) == mask); 5055326Smckusic case 1: 5065326Smckusic mask = 0x01 << (h & 0x7); 5075326Smckusic return ((cp[h >> 3] & mask) == mask); 5085326Smckusic default: 5098143Smckusick #ifdef STANDALONE 5108143Smckusick printf("isblock bad fs_frag %d\n", fs->fs_frag); 5118143Smckusick #else 5125326Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 5138143Smckusick #endif 5145326Smckusic return; 5155326Smckusic } 5165326Smckusic } 5175326Smckusic 5188143Smckusick /* 5198143Smckusick * put a block into the map 5208143Smckusick */ 5215326Smckusic setblock(fs, cp, h) 5225326Smckusic struct fs *fs; 5235326Smckusic unsigned char *cp; 5245326Smckusic int h; 5255326Smckusic { 5265326Smckusic switch (fs->fs_frag) { 5275326Smckusic case 8: 5285326Smckusic cp[h] = 0xff; 5295326Smckusic return; 5305326Smckusic case 4: 5315326Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 5325326Smckusic return; 5335326Smckusic case 2: 5345326Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 5355326Smckusic return; 5365326Smckusic case 1: 5375326Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 5385326Smckusic return; 5395326Smckusic default: 5408143Smckusick #ifdef STANDALONE 5418143Smckusick printf("setblock bad fs_frag %d\n", fs->fs_frag); 5428143Smckusick #else 5435326Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 5448143Smckusick #endif 5455326Smckusic return; 5465326Smckusic } 5475326Smckusic } 548