1*13550Ssam #ifndef lint 2*13550Ssam static char *sccsid = "@(#)dcheck.c 2.4 (Berkeley) 07/01/83"; 3*13550Ssam #endif 44238Smckusick /* 54238Smckusick * dcheck - check directory consistency 64238Smckusick */ 74238Smckusick #define NB 10 85348Smckusic #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 94238Smckusick 106493Smckusick #include <sys/param.h> 116493Smckusick #include <sys/inode.h> 126493Smckusick #include <sys/fs.h> 13*13550Ssam #include <sys/dir.h> 145946Smckusic #include <stdio.h> 154238Smckusick 164238Smckusick union { 174238Smckusick struct fs fs; 185326Smckusic char pad[MAXBSIZE]; 194238Smckusick } fsun; 204238Smckusick #define sblock fsun.fs 214238Smckusick 225946Smckusic struct dirstuff { 235946Smckusic int loc; 245946Smckusic struct dinode *ip; 255946Smckusic char dbuf[MAXBSIZE]; 265946Smckusic }; 275946Smckusic 284238Smckusick struct dinode itab[MAXIPG]; 294253Smckusic struct dinode *gip; 304238Smckusick ino_t ilist[NB]; 314238Smckusick 324238Smckusick int fi; 334238Smckusick ino_t ino; 344238Smckusick ino_t *ecount; 354238Smckusick int headpr; 364238Smckusick int nfiles; 374238Smckusick 384238Smckusick int nerror; 394238Smckusick daddr_t bmap(); 404238Smckusick long atol(); 414238Smckusick char *malloc(); 424238Smckusick 434238Smckusick main(argc, argv) 444238Smckusick char *argv[]; 454238Smckusick { 464238Smckusick register i; 474238Smckusick long n; 484238Smckusick 494238Smckusick while (--argc) { 504238Smckusick argv++; 514238Smckusick if (**argv=='-') 524238Smckusick switch ((*argv)[1]) { 534238Smckusick 544238Smckusick case 'i': 554238Smckusick for(i=0; i<NB; i++) { 564238Smckusick n = atol(argv[1]); 574238Smckusick if(n == 0) 584238Smckusick break; 594238Smckusick ilist[i] = n; 604238Smckusick argv++; 614238Smckusick argc--; 624238Smckusick } 634238Smckusick ilist[i] = 0; 644238Smckusick continue; 654238Smckusick 664238Smckusick default: 674238Smckusick printf("Bad flag %c\n", (*argv)[1]); 684238Smckusick nerror++; 694238Smckusick } 704238Smckusick check(*argv); 714238Smckusick } 724238Smckusick return(nerror); 734238Smckusick } 744238Smckusick 754238Smckusick check(file) 764238Smckusick char *file; 774238Smckusick { 784238Smckusick register i, j, c; 794238Smckusick 804238Smckusick fi = open(file, 0); 814238Smckusick if(fi < 0) { 824238Smckusick printf("cannot open %s\n", file); 834238Smckusick nerror++; 844238Smckusick return; 854238Smckusick } 864238Smckusick headpr = 0; 874238Smckusick printf("%s:\n", file); 884238Smckusick sync(); 895348Smckusic bread(SBLOCK, (char *)&sblock, SBSIZE); 904238Smckusick if (sblock.fs_magic != FS_MAGIC) { 914238Smckusick printf("%s: not a file system\n", file); 924238Smckusick nerror++; 934238Smckusick return; 944238Smckusick } 954238Smckusick nfiles = sblock.fs_ipg * sblock.fs_ncg; 964238Smckusick ecount = (ino_t *)malloc((nfiles+1) * sizeof (*ecount)); 974238Smckusick if (ecount == 0) { 984238Smckusick printf("%s: not enough core for %d files\n", file, nfiles); 994238Smckusick exit(04); 1004238Smckusick } 1014238Smckusick for (i = 0; i<=nfiles; i++) 1024238Smckusick ecount[i] = 0; 1034238Smckusick ino = 0; 1044238Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1055379Smckusic bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 1064238Smckusick sblock.fs_ipg * sizeof (struct dinode)); 1074238Smckusick for (j = 0; j < sblock.fs_ipg; j++) { 1084238Smckusick pass1(&itab[j]); 1094238Smckusick ino++; 1104238Smckusick } 1114238Smckusick } 1124238Smckusick ino = 0; 1134238Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1145379Smckusic bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 1154238Smckusick sblock.fs_ipg * sizeof (struct dinode)); 1164238Smckusick for (j = 0; j < sblock.fs_ipg; j++) { 1174238Smckusick pass2(&itab[j]); 1184238Smckusick ino++; 1194238Smckusick } 1204238Smckusick } 1214238Smckusick free(ecount); 1224238Smckusick } 1234238Smckusick 1244238Smckusick pass1(ip) 1255946Smckusic register struct dinode *ip; 1264238Smckusick { 1275946Smckusic register struct direct *dp; 1285946Smckusic struct dirstuff dirp; 1294238Smckusick int k; 1304238Smckusick 1314238Smckusick if((ip->di_mode&IFMT) != IFDIR) 1324238Smckusick return; 1335946Smckusic dirp.loc = 0; 1345946Smckusic dirp.ip = ip; 1354253Smckusic gip = ip; 1365946Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 1375946Smckusic if(dp->d_ino == 0) 1385946Smckusic continue; 1395946Smckusic if(dp->d_ino > nfiles || dp->d_ino < ROOTINO) { 1405946Smckusic printf("%d bad; %d/%s\n", 1415946Smckusic dp->d_ino, ino, dp->d_name); 1425946Smckusic nerror++; 1435946Smckusic continue; 1445946Smckusic } 1455946Smckusic for (k = 0; ilist[k] != 0; k++) 1465946Smckusic if (ilist[k] == dp->d_ino) { 1475946Smckusic printf("%d arg; %d/%s\n", 1485946Smckusic dp->d_ino, ino, dp->d_name); 1494238Smckusick nerror++; 1504238Smckusick } 1515946Smckusic ecount[dp->d_ino]++; 1524238Smckusick } 1534238Smckusick } 1544238Smckusick 1554238Smckusick pass2(ip) 1564238Smckusick register struct dinode *ip; 1574238Smckusick { 1584238Smckusick register i; 1594238Smckusick 1604238Smckusick i = ino; 1614238Smckusick if ((ip->di_mode&IFMT)==0 && ecount[i]==0) 1624238Smckusick return; 1634238Smckusick if (ip->di_nlink==ecount[i] && ip->di_nlink!=0) 1644238Smckusick return; 1654238Smckusick if (headpr==0) { 1664238Smckusick printf(" entries link cnt\n"); 1674238Smckusick headpr++; 1684238Smckusick } 1694238Smckusick printf("%u\t%d\t%d\n", ino, 1704238Smckusick ecount[i], ip->di_nlink); 1714238Smckusick } 1724238Smckusick 1735946Smckusic /* 1745946Smckusic * get next entry in a directory. 1755946Smckusic */ 1765946Smckusic struct direct * 1775946Smckusic readdir(dirp) 1785946Smckusic register struct dirstuff *dirp; 1795946Smckusic { 1805946Smckusic register struct direct *dp; 1815946Smckusic daddr_t lbn, d; 1825946Smckusic 1835946Smckusic for(;;) { 1845946Smckusic if (dirp->loc >= dirp->ip->di_size) 1855946Smckusic return NULL; 1865957Smckusic if ((lbn = lblkno(&sblock, dirp->loc)) == 0) { 1875946Smckusic d = bmap(lbn); 1885946Smckusic if(d == 0) 1895946Smckusic return NULL; 1905946Smckusic bread(fsbtodb(&sblock, d), dirp->dbuf, 1915946Smckusic dblksize(&sblock, dirp->ip, lbn)); 1925946Smckusic } 1935946Smckusic dp = (struct direct *) 1945957Smckusic (dirp->dbuf + blkoff(&sblock, dirp->loc)); 1955946Smckusic dirp->loc += dp->d_reclen; 1965946Smckusic if (dp->d_ino == 0) 1975946Smckusic continue; 1985946Smckusic return (dp); 1995946Smckusic } 2005946Smckusic } 2015946Smckusic 2024238Smckusick bread(bno, buf, cnt) 2034238Smckusick daddr_t bno; 2044238Smckusick char *buf; 2054238Smckusick { 2064238Smckusick register i; 2074238Smckusick 2085326Smckusic lseek(fi, bno * DEV_BSIZE, 0); 2094238Smckusick if (read(fi, buf, cnt) != cnt) { 2104238Smckusick printf("read error %d\n", bno); 2115326Smckusic for(i=0; i < cnt; i++) 2124238Smckusick buf[i] = 0; 2134238Smckusick } 2144238Smckusick } 2154238Smckusick 2164238Smckusick daddr_t 2174238Smckusick bmap(i) 2184238Smckusick { 2195326Smckusic daddr_t ibuf[MAXNINDIR]; 2204238Smckusick 2214238Smckusick if(i < NDADDR) 2224253Smckusic return(gip->di_db[i]); 2234238Smckusick i -= NDADDR; 2245326Smckusic if(i > NINDIR(&sblock)) { 2254238Smckusick printf("%u - huge directory\n", ino); 2264238Smckusick return((daddr_t)0); 2274238Smckusick } 2285326Smckusic bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf)); 2294238Smckusick return(ibuf[i]); 2304238Smckusick } 231