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*51619Sbostic static char sccsid[] = "@(#)icheck.c 5.8 (Berkeley) 11/11/91"; 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> 26*51619Sbostic #include <ufs/ufs/dinode.h> 27*51619Sbostic #include <ufs/ffs/fs.h> 284240Smckusick #ifndef STANDALONE 294240Smckusick #include <stdio.h> 304240Smckusick #endif 314240Smckusick 324240Smckusick union { 334240Smckusick struct fs sb; 3434148Smckusick char pad[SBSIZE]; 354240Smckusick } sbun; 364240Smckusick #define sblock sbun.sb 374240Smckusick 384240Smckusick union { 394240Smckusick struct cg cg; 405326Smckusic char pad[MAXBSIZE]; 414240Smckusick } cgun; 424240Smckusick #define cgrp cgun.cg 434240Smckusick 4434148Smckusick struct dinode itab[MAXBSIZE / sizeof(struct dinode)]; 4534148Smckusick 464240Smckusick daddr_t blist[NB]; 479298Smckusick daddr_t fsblist[NB]; 484240Smckusick char *bmap; 494240Smckusick 504240Smckusick int mflg; 514240Smckusick int dflg; 524240Smckusick int fi; 534240Smckusick ino_t ino; 544240Smckusick int cginit; 554240Smckusick 564240Smckusick ino_t nrfile; 574240Smckusick ino_t ndfile; 584240Smckusick ino_t nbfile; 594240Smckusick ino_t ncfile; 606286Smckusick ino_t nlfile; 6134148Smckusick ino_t nsfile; 624240Smckusick 634240Smckusick daddr_t nblock; 644240Smckusick daddr_t nfrag; 654240Smckusick daddr_t nindir; 664240Smckusick daddr_t niindir; 674240Smckusick 684240Smckusick daddr_t nffree; 694240Smckusick daddr_t nbfree; 704240Smckusick 714240Smckusick daddr_t ndup; 724240Smckusick 734240Smckusick int nerror; 7430558Smckusick long dev_bsize = 1; 754240Smckusick 764240Smckusick long atol(); 774240Smckusick #ifndef STANDALONE 784240Smckusick char *malloc(); 795098Smckusic char *calloc(); 804240Smckusick #endif 814240Smckusick 824240Smckusick main(argc, argv) 835098Smckusic int argc; 845098Smckusic char *argv[]; 854240Smckusick { 864240Smckusick register i; 874240Smckusick long n; 884240Smckusick 894240Smckusick blist[0] = -1; 904240Smckusick #ifndef STANDALONE 914240Smckusick while (--argc) { 924240Smckusick argv++; 934240Smckusick if (**argv=='-') 944240Smckusick switch ((*argv)[1]) { 954240Smckusick case 'd': 964240Smckusick dflg++; 974240Smckusick continue; 984240Smckusick 994240Smckusick case 'm': 1004240Smckusick mflg++; 1014240Smckusick continue; 1024240Smckusick 1034240Smckusick case 'b': 1044240Smckusick for(i=0; i<NB; i++) { 1054240Smckusick n = atol(argv[1]); 1064240Smckusick if(n == 0) 1074240Smckusick break; 1084240Smckusick blist[i] = n; 1094240Smckusick argv++; 1104240Smckusick argc--; 1114240Smckusick } 1124240Smckusick blist[i] = -1; 1134240Smckusick continue; 1144240Smckusick 1154240Smckusick default: 1164240Smckusick printf("Bad flag\n"); 1174240Smckusick } 1184240Smckusick check(*argv); 1194240Smckusick } 1204240Smckusick #else 1214240Smckusick { 1224240Smckusick static char fname[128]; 1234240Smckusick 1244240Smckusick printf("File: "); 1254240Smckusick gets(fname); 1264240Smckusick check(fname); 1274240Smckusick } 1284240Smckusick #endif 1294240Smckusick return(nerror); 1304240Smckusick } 1314240Smckusick 1324240Smckusick check(file) 1335098Smckusic char *file; 1344240Smckusick { 1354240Smckusick register i, j, c; 1364240Smckusick daddr_t d, cgd, cbase, b; 1374240Smckusick long n; 1389298Smckusick char buf[BUFSIZ]; 1394240Smckusick 14034148Smckusick fi = open(file, 0); 1414240Smckusick if (fi < 0) { 1425098Smckusic perror(file); 1434240Smckusick nerror |= 04; 1444240Smckusick return; 1454240Smckusick } 1464240Smckusick printf("%s:\n", file); 1474240Smckusick nrfile = 0; 1484240Smckusick ndfile = 0; 1494240Smckusick ncfile = 0; 1504240Smckusick nbfile = 0; 1516286Smckusick nlfile = 0; 15234148Smckusick nsfile = 0; 1534240Smckusick 1544240Smckusick nblock = 0; 1554240Smckusick nfrag = 0; 1564240Smckusick nindir = 0; 1574240Smckusick niindir = 0; 1584240Smckusick 1594240Smckusick ndup = 0; 1604240Smckusick #ifndef STANDALONE 1614240Smckusick sync(); 1624240Smckusick #endif 1635326Smckusic getsb(&sblock, file); 1645326Smckusic if (nerror) 1654240Smckusick return; 1669298Smckusick for (n=0; blist[n] != -1; n++) 1679298Smckusick fsblist[n] = dbtofsb(&sblock, blist[n]); 1684240Smckusick ino = 0; 1695098Smckusic n = roundup(howmany(sblock.fs_size, NBBY), sizeof(short)); 1704240Smckusick #ifdef STANDALONE 1714240Smckusick bmap = NULL; 1724240Smckusick #else 1734240Smckusick bmap = malloc((unsigned)n); 1744240Smckusick #endif 1754240Smckusick if (bmap==NULL) { 1764240Smckusick printf("Not enough core; duplicates unchecked\n"); 1774240Smckusick dflg++; 1784240Smckusick } 1794240Smckusick ino = 0; 1804240Smckusick cginit = 1; 1816534Smckusick if (!dflg) { 1826534Smckusick for (i = 0; i < (unsigned)n; i++) 1834240Smckusick bmap[i] = 0; 1846534Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1855382Smckusic cgd = cgtod(&sblock, c); 1866534Smckusick if (c == 0) 1876534Smckusick d = cgbase(&sblock, c); 1886534Smckusick else 1896534Smckusick d = cgsblock(&sblock, c); 19032441Sbostic (void)sprintf(buf, "spare super block %d", c); 1916534Smckusick for (; d < cgd; d += sblock.fs_frag) 1929298Smckusick chk(d, buf, sblock.fs_bsize); 1935382Smckusic d = cgimin(&sblock, c); 19432441Sbostic (void)sprintf(buf, "cylinder group %d", c); 1954240Smckusick while (cgd < d) { 1969298Smckusick chk(cgd, buf, sblock.fs_bsize); 1975326Smckusic cgd += sblock.fs_frag; 1984240Smckusick } 1995382Smckusic d = cgdmin(&sblock, c); 2009298Smckusick i = INOPB(&sblock); 2019298Smckusick for (; cgd < d; cgd += sblock.fs_frag) { 20232441Sbostic (void)sprintf(buf, "inodes %d-%d", ino, ino + i); 2039298Smckusick chk(cgd, buf, sblock.fs_bsize); 2049298Smckusick ino += i; 2059298Smckusick } 2064240Smckusick if (c == 0) { 2076534Smckusick d += howmany(sblock.fs_cssize, sblock.fs_fsize); 2086534Smckusick for (; cgd < d; cgd++) 2096534Smckusick chk(cgd, "csum", sblock.fs_fsize); 2104240Smckusick } 2114240Smckusick } 2124240Smckusick } 2139298Smckusick ino = 0; 2144240Smckusick cginit = 0; 2154240Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 21634148Smckusick for (i = 0; 21734148Smckusick i < sblock.fs_ipg / INOPF(&sblock); 21834148Smckusick i += sblock.fs_frag) { 21934148Smckusick bread(fsbtodb(&sblock, cgimin(&sblock, c) + i), 22034148Smckusick (char *)itab, sblock.fs_bsize); 22134148Smckusick for (j = 0; j < INOPB(&sblock); j++) { 22234148Smckusick pass1(&itab[j]); 22334148Smckusick ino++; 22434148Smckusick } 2254240Smckusick } 2264240Smckusick } 2274240Smckusick ino = 0; 2284240Smckusick #ifndef STANDALONE 2294240Smckusick sync(); 2304240Smckusick #endif 2314240Smckusick nffree = 0; 2324240Smckusick nbfree = 0; 2334240Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 2345382Smckusic cbase = cgbase(&sblock, c); 2355382Smckusic bread(fsbtodb(&sblock, cgtod(&sblock, c)), (char *)&cgrp, 2365326Smckusic sblock.fs_cgsize); 23734148Smckusick if (!cg_chkmagic(&cgrp)) 2386534Smckusick printf("cg %d: bad magic number\n", c); 2395326Smckusic for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 24034148Smckusick if (isblock(&sblock, cg_blksfree(&cgrp), 2415326Smckusic b / sblock.fs_frag)) { 2424240Smckusick nbfree++; 2439298Smckusick chk(cbase+b, "free block", sblock.fs_bsize); 2444240Smckusick } else { 2455326Smckusic for (d = 0; d < sblock.fs_frag; d++) 24634148Smckusick if (isset(cg_blksfree(&cgrp), b+d)) { 2479298Smckusick chk(cbase+b+d, "free frag", sblock.fs_fsize); 2484240Smckusick nffree++; 2494240Smckusick } 2504240Smckusick } 2514240Smckusick } 2524240Smckusick } 2534240Smckusick close(fi); 2544240Smckusick #ifndef STANDALONE 2554240Smckusick if (bmap) 2564240Smckusick free(bmap); 2574240Smckusick #endif 2584240Smckusick 25934148Smckusick i = nrfile + ndfile + ncfile + nbfile + nlfile + nsfile; 2604240Smckusick #ifndef STANDALONE 26134148Smckusick printf("files %6u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 26234148Smckusick i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 2634240Smckusick #else 26434148Smckusick printf("files %u (r=%u,d=%u,b=%u,c=%u,sl=%u,sock=%u)\n", 26534148Smckusick i, nrfile, ndfile, nbfile, ncfile, nlfile, nsfile); 2664240Smckusick #endif 2675326Smckusic n = (nblock + nindir + niindir) * sblock.fs_frag + nfrag; 2684240Smckusick #ifdef STANDALONE 2694240Smckusick printf("used %ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 2704240Smckusick n, nindir, niindir, nblock, nfrag); 2715326Smckusic printf("free %ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 2724240Smckusick nbfree, nffree); 2734240Smckusick #else 2744240Smckusick printf("used %7ld (i=%ld,ii=%ld,b=%ld,f=%ld)\n", 2754240Smckusick n, nindir, niindir, nblock, nfrag); 2765326Smckusic printf("free %7ld (b=%ld,f=%ld)\n", nffree + sblock.fs_frag * nbfree, 2774240Smckusick nbfree, nffree); 2784240Smckusick #endif 2794240Smckusick if(!dflg) { 2804240Smckusick n = 0; 2814410Smckusic for (d = 0; d < sblock.fs_size; d++) 2825326Smckusic if(!duped(d, sblock.fs_fsize)) { 2834240Smckusick if(mflg) 2844240Smckusick printf("%ld missing\n", d); 2854240Smckusick n++; 2864240Smckusick } 2874240Smckusick printf("missing%5ld\n", n); 2884240Smckusick } 2894240Smckusick } 2904240Smckusick 2914240Smckusick pass1(ip) 2924410Smckusic register struct dinode *ip; 2934240Smckusick { 2945326Smckusic daddr_t ind1[MAXNINDIR]; 2955326Smckusic daddr_t ind2[MAXNINDIR]; 2964429Smckusic daddr_t db, ib; 2974429Smckusic register int i, j, k, siz; 2989298Smckusick int lbn; 2999298Smckusick char buf[BUFSIZ]; 3004240Smckusick 3014240Smckusick i = ip->di_mode & IFMT; 3024790Smckusic if(i == 0) 3034240Smckusick return; 3044240Smckusick switch (i) { 3054240Smckusick case IFCHR: 3064240Smckusick ncfile++; 3074240Smckusick return; 3084240Smckusick case IFBLK: 3094240Smckusick nbfile++; 3104240Smckusick return; 3114240Smckusick case IFDIR: 3124240Smckusick ndfile++; 3134240Smckusick break; 3144240Smckusick case IFREG: 3154240Smckusick nrfile++; 3164240Smckusick break; 31734148Smckusick case IFSOCK: 31834148Smckusick nsfile++; 31934148Smckusick break; 3206286Smckusick case IFLNK: 3216286Smckusick nlfile++; 3226286Smckusick break; 3234240Smckusick default: 3244240Smckusick printf("bad mode %u\n", ino); 3254240Smckusick return; 3264240Smckusick } 3274410Smckusic for (i = 0; i < NDADDR; i++) { 3284410Smckusic db = ip->di_db[i]; 3294410Smckusic if (db == 0) 3304240Smckusick continue; 3315326Smckusic siz = dblksize(&sblock, ip, i); 33232441Sbostic (void)sprintf(buf, "logical data block %d", i); 3339298Smckusick chk(db, buf, siz); 3345326Smckusic if (siz == sblock.fs_bsize) 3354429Smckusic nblock++; 3364429Smckusic else 3375326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3384240Smckusick } 3394410Smckusic for(i = 0; i < NIADDR; i++) { 3404410Smckusic ib = ip->di_ib[i]; 3419298Smckusick if (ib == 0) 3424240Smckusick continue; 3435326Smckusic if (chk(ib, "1st indirect", sblock.fs_bsize)) 3444410Smckusic continue; 3455326Smckusic bread(fsbtodb(&sblock, ib), (char *)ind1, sblock.fs_bsize); 3464240Smckusick nindir++; 3475326Smckusic for (j = 0; j < NINDIR(&sblock); j++) { 3484410Smckusic ib = ind1[j]; 3494410Smckusic if (ib == 0) 3504240Smckusick continue; 3514410Smckusic if (i == 0) { 3529298Smckusick lbn = NDADDR + j; 3539298Smckusick siz = dblksize(&sblock, ip, lbn); 35432441Sbostic (void)sprintf(buf, "logical data block %d", lbn); 3559298Smckusick chk(ib, buf, siz); 3565326Smckusic if (siz == sblock.fs_bsize) 3574429Smckusic nblock++; 3584429Smckusic else 3595326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3604240Smckusick continue; 3614240Smckusick } 3625326Smckusic if (chk(ib, "2nd indirect", sblock.fs_bsize)) 3634410Smckusic continue; 3645326Smckusic bread(fsbtodb(&sblock, ib), (char *)ind2, 3655326Smckusic sblock.fs_bsize); 3664240Smckusick niindir++; 3675326Smckusic for (k = 0; k < NINDIR(&sblock); k++) { 3684410Smckusic ib = ind2[k]; 3694410Smckusic if (ib == 0) 3704240Smckusick continue; 3719298Smckusick lbn = NDADDR + NINDIR(&sblock) * (i + j) + k; 3729298Smckusick siz = dblksize(&sblock, ip, lbn); 37332441Sbostic (void)sprintf(buf, "logical data block %d", lbn); 3749298Smckusick chk(ib, buf, siz); 3755326Smckusic if (siz == sblock.fs_bsize) 3764429Smckusic nblock++; 3774429Smckusic else 3785326Smckusic nfrag += howmany(siz, sblock.fs_fsize); 3794240Smckusick } 3804240Smckusick } 3814240Smckusick } 3824240Smckusick } 3834240Smckusick 3844429Smckusic chk(bno, s, size) 3854410Smckusic daddr_t bno; 3864410Smckusic char *s; 3874429Smckusic int size; 3884240Smckusick { 3894240Smckusick register n, cg; 3905957Smckusic int frags; 3914240Smckusick 3925382Smckusic cg = dtog(&sblock, bno); 3936534Smckusick if (cginit == 0 && bno >= sblock.fs_frag * sblock.fs_size) { 3944240Smckusick printf("%ld bad; inode=%u, class=%s\n", bno, ino, s); 3954240Smckusick return(1); 3964240Smckusick } 3979298Smckusick frags = numfrags(&sblock, size); 3989298Smckusick if (frags == sblock.fs_frag) { 3994429Smckusic if (duped(bno, size)) { 4004429Smckusic printf("%ld dup block; inode=%u, class=%s\n", 4014429Smckusic bno, ino, s); 4025326Smckusic ndup += sblock.fs_frag; 4034429Smckusic } 4044429Smckusic } else { 4055957Smckusic for (n = 0; n < frags; n++) { 4065326Smckusic if (duped(bno + n, sblock.fs_fsize)) { 4074429Smckusic printf("%ld dup frag; inode=%u, class=%s\n", 4084429Smckusic bno, ino, s); 4094429Smckusic ndup++; 4104429Smckusic } 4114429Smckusic } 4124240Smckusick } 4134240Smckusick for (n=0; blist[n] != -1; n++) 4149298Smckusick if (fsblist[n] >= bno && fsblist[n] < bno + frags) 4159298Smckusick printf("%ld arg; frag %d of %d, inode=%u, class=%s\n", 4169298Smckusick blist[n], fsblist[n] - bno, frags, ino, s); 4174240Smckusick return(0); 4184240Smckusick } 4194240Smckusick 4204429Smckusic duped(bno, size) 4214410Smckusic daddr_t bno; 4224429Smckusic int size; 4234240Smckusick { 4244240Smckusick if(dflg) 4254240Smckusick return(0); 4265326Smckusic if (size != sblock.fs_fsize && size != sblock.fs_bsize) 4274429Smckusic printf("bad size %d to duped\n", size); 4285326Smckusic if (size == sblock.fs_fsize) { 4294410Smckusic if (isset(bmap, bno)) 4304410Smckusic return(1); 4314410Smckusic setbit(bmap, bno); 4324410Smckusic return (0); 4334410Smckusic } 4345326Smckusic if (bno % sblock.fs_frag != 0) 4354410Smckusic printf("bad bno %d to duped\n", bno); 4365326Smckusic if (isblock(&sblock, bmap, bno/sblock.fs_frag)) 4374410Smckusic return (1); 4385326Smckusic setblock(&sblock, bmap, bno/sblock.fs_frag); 4394240Smckusick return(0); 4404240Smckusick } 4414240Smckusick 4425326Smckusic getsb(fs, file) 4435326Smckusic register struct fs *fs; 4445326Smckusic char *file; 4455326Smckusic { 4466534Smckusick int i, j, size; 4475326Smckusic 44830558Smckusick if (bread(SBOFF, fs, SBSIZE)) { 4495326Smckusic printf("bad super block"); 4505326Smckusic perror(file); 4515326Smckusic nerror |= 04; 4525326Smckusic return; 4535326Smckusic } 4545326Smckusic if (fs->fs_magic != FS_MAGIC) { 4555326Smckusic printf("%s: bad magic number\n", file); 4565326Smckusic nerror |= 04; 4575326Smckusic return; 4585326Smckusic } 45930558Smckusick dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 4606534Smckusick for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 4616534Smckusick size = sblock.fs_cssize - i < sblock.fs_bsize ? 4626534Smckusick sblock.fs_cssize - i : sblock.fs_bsize; 4636534Smckusick sblock.fs_csp[j] = (struct csum *)calloc(1, size); 4646534Smckusick bread(fsbtodb(fs, fs->fs_csaddr + (j * fs->fs_frag)), 4656534Smckusick (char *)fs->fs_csp[j], size); 4665326Smckusic } 4675326Smckusic } 4685326Smckusic 4694240Smckusick bread(bno, buf, cnt) 4704410Smckusic daddr_t bno; 4714410Smckusic char *buf; 4724240Smckusick { 4734240Smckusick register i; 4744240Smckusick 47530558Smckusick lseek(fi, bno * dev_bsize, 0); 4764240Smckusick if ((i = read(fi, buf, cnt)) != cnt) { 4775326Smckusic for(i=0; i<sblock.fs_bsize; i++) 4784240Smckusick buf[i] = 0; 4795326Smckusic return (1); 4804240Smckusick } 4815326Smckusic return (0); 4824240Smckusick } 4835326Smckusic 4845326Smckusic /* 4858143Smckusick * check if a block is available 4865326Smckusic */ 4875326Smckusic isblock(fs, cp, h) 4885326Smckusic struct fs *fs; 4895326Smckusic unsigned char *cp; 4905326Smckusic int h; 4915326Smckusic { 4925326Smckusic unsigned char mask; 4935326Smckusic 4945326Smckusic switch (fs->fs_frag) { 4955326Smckusic case 8: 4965326Smckusic return (cp[h] == 0xff); 4975326Smckusic case 4: 4985326Smckusic mask = 0x0f << ((h & 0x1) << 2); 4995326Smckusic return ((cp[h >> 1] & mask) == mask); 5005326Smckusic case 2: 5015326Smckusic mask = 0x03 << ((h & 0x3) << 1); 5025326Smckusic return ((cp[h >> 2] & mask) == mask); 5035326Smckusic case 1: 5045326Smckusic mask = 0x01 << (h & 0x7); 5055326Smckusic return ((cp[h >> 3] & mask) == mask); 5065326Smckusic default: 5078143Smckusick #ifdef STANDALONE 5088143Smckusick printf("isblock bad fs_frag %d\n", fs->fs_frag); 5098143Smckusick #else 5105326Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 5118143Smckusick #endif 5125326Smckusic return; 5135326Smckusic } 5145326Smckusic } 5155326Smckusic 5168143Smckusick /* 5178143Smckusick * put a block into the map 5188143Smckusick */ 5195326Smckusic setblock(fs, cp, h) 5205326Smckusic struct fs *fs; 5215326Smckusic unsigned char *cp; 5225326Smckusic int h; 5235326Smckusic { 5245326Smckusic switch (fs->fs_frag) { 5255326Smckusic case 8: 5265326Smckusic cp[h] = 0xff; 5275326Smckusic return; 5285326Smckusic case 4: 5295326Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 5305326Smckusic return; 5315326Smckusic case 2: 5325326Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 5335326Smckusic return; 5345326Smckusic case 1: 5355326Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 5365326Smckusic return; 5375326Smckusic default: 5388143Smckusick #ifdef STANDALONE 5398143Smckusick printf("setblock bad fs_frag %d\n", fs->fs_frag); 5408143Smckusick #else 5415326Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 5428143Smckusick #endif 5435326Smckusic return; 5445326Smckusic } 5455326Smckusic } 546