122489Sdist /* 222489Sdist * Copyright (c) 1980 Regents of the University of California. 322489Sdist * All rights reserved. The Berkeley software License Agreement 422489Sdist * specifies the terms and conditions for redistribution. 522489Sdist */ 622489Sdist 713550Ssam #ifndef lint 822489Sdist char copyright[] = 922489Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1022489Sdist All rights reserved.\n"; 1122489Sdist #endif not lint 1222489Sdist 1322489Sdist #ifndef lint 14*30558Smckusick static char sccsid[] = "@(#)dcheck.c 5.2 (Berkeley) 02/23/87"; 1522489Sdist #endif not lint 1622489Sdist 174238Smckusick /* 184238Smckusick * dcheck - check directory consistency 194238Smckusick */ 204238Smckusick #define NB 10 215348Smckusic #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 224238Smckusick 236493Smckusick #include <sys/param.h> 246493Smckusick #include <sys/inode.h> 256493Smckusick #include <sys/fs.h> 2613550Ssam #include <sys/dir.h> 275946Smckusic #include <stdio.h> 284238Smckusick 294238Smckusick union { 304238Smckusick struct fs fs; 315326Smckusic char pad[MAXBSIZE]; 324238Smckusick } fsun; 334238Smckusick #define sblock fsun.fs 344238Smckusick 355946Smckusic struct dirstuff { 365946Smckusic int loc; 375946Smckusic struct dinode *ip; 385946Smckusic char dbuf[MAXBSIZE]; 395946Smckusic }; 405946Smckusic 414238Smckusick struct dinode itab[MAXIPG]; 424253Smckusic struct dinode *gip; 434238Smckusick ino_t ilist[NB]; 444238Smckusick 454238Smckusick int fi; 464238Smckusick ino_t ino; 474238Smckusick ino_t *ecount; 484238Smckusick int headpr; 494238Smckusick int nfiles; 50*30558Smckusick long dev_bsize = 1; 514238Smckusick 524238Smckusick int nerror; 534238Smckusick daddr_t bmap(); 544238Smckusick long atol(); 554238Smckusick char *malloc(); 564238Smckusick 574238Smckusick main(argc, argv) 584238Smckusick char *argv[]; 594238Smckusick { 604238Smckusick register i; 614238Smckusick long n; 624238Smckusick 634238Smckusick while (--argc) { 644238Smckusick argv++; 654238Smckusick if (**argv=='-') 664238Smckusick switch ((*argv)[1]) { 674238Smckusick 684238Smckusick case 'i': 694238Smckusick for(i=0; i<NB; i++) { 704238Smckusick n = atol(argv[1]); 714238Smckusick if(n == 0) 724238Smckusick break; 734238Smckusick ilist[i] = n; 744238Smckusick argv++; 754238Smckusick argc--; 764238Smckusick } 774238Smckusick ilist[i] = 0; 784238Smckusick continue; 794238Smckusick 804238Smckusick default: 814238Smckusick printf("Bad flag %c\n", (*argv)[1]); 824238Smckusick nerror++; 834238Smckusick } 844238Smckusick check(*argv); 854238Smckusick } 864238Smckusick return(nerror); 874238Smckusick } 884238Smckusick 894238Smckusick check(file) 904238Smckusick char *file; 914238Smckusick { 924238Smckusick register i, j, c; 934238Smckusick 944238Smckusick fi = open(file, 0); 954238Smckusick if(fi < 0) { 964238Smckusick printf("cannot open %s\n", file); 974238Smckusick nerror++; 984238Smckusick return; 994238Smckusick } 1004238Smckusick headpr = 0; 1014238Smckusick printf("%s:\n", file); 1024238Smckusick sync(); 103*30558Smckusick bread(SBOFF, (char *)&sblock, SBSIZE); 1044238Smckusick if (sblock.fs_magic != FS_MAGIC) { 1054238Smckusick printf("%s: not a file system\n", file); 1064238Smckusick nerror++; 1074238Smckusick return; 1084238Smckusick } 109*30558Smckusick dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); 1104238Smckusick nfiles = sblock.fs_ipg * sblock.fs_ncg; 1114238Smckusick ecount = (ino_t *)malloc((nfiles+1) * sizeof (*ecount)); 1124238Smckusick if (ecount == 0) { 1134238Smckusick printf("%s: not enough core for %d files\n", file, nfiles); 1144238Smckusick exit(04); 1154238Smckusick } 1164238Smckusick for (i = 0; i<=nfiles; i++) 1174238Smckusick ecount[i] = 0; 1184238Smckusick ino = 0; 1194238Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1205379Smckusic bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 1214238Smckusick sblock.fs_ipg * sizeof (struct dinode)); 1224238Smckusick for (j = 0; j < sblock.fs_ipg; j++) { 1234238Smckusick pass1(&itab[j]); 1244238Smckusick ino++; 1254238Smckusick } 1264238Smckusick } 1274238Smckusick ino = 0; 1284238Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1295379Smckusic bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 1304238Smckusick sblock.fs_ipg * sizeof (struct dinode)); 1314238Smckusick for (j = 0; j < sblock.fs_ipg; j++) { 1324238Smckusick pass2(&itab[j]); 1334238Smckusick ino++; 1344238Smckusick } 1354238Smckusick } 1364238Smckusick free(ecount); 1374238Smckusick } 1384238Smckusick 1394238Smckusick pass1(ip) 1405946Smckusic register struct dinode *ip; 1414238Smckusick { 1425946Smckusic register struct direct *dp; 1435946Smckusic struct dirstuff dirp; 1444238Smckusick int k; 1454238Smckusick 1464238Smckusick if((ip->di_mode&IFMT) != IFDIR) 1474238Smckusick return; 1485946Smckusic dirp.loc = 0; 1495946Smckusic dirp.ip = ip; 1504253Smckusic gip = ip; 1515946Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 1525946Smckusic if(dp->d_ino == 0) 1535946Smckusic continue; 1545946Smckusic if(dp->d_ino > nfiles || dp->d_ino < ROOTINO) { 1555946Smckusic printf("%d bad; %d/%s\n", 1565946Smckusic dp->d_ino, ino, dp->d_name); 1575946Smckusic nerror++; 1585946Smckusic continue; 1595946Smckusic } 1605946Smckusic for (k = 0; ilist[k] != 0; k++) 1615946Smckusic if (ilist[k] == dp->d_ino) { 1625946Smckusic printf("%d arg; %d/%s\n", 1635946Smckusic dp->d_ino, ino, dp->d_name); 1644238Smckusick nerror++; 1654238Smckusick } 1665946Smckusic ecount[dp->d_ino]++; 1674238Smckusick } 1684238Smckusick } 1694238Smckusick 1704238Smckusick pass2(ip) 1714238Smckusick register struct dinode *ip; 1724238Smckusick { 1734238Smckusick register i; 1744238Smckusick 1754238Smckusick i = ino; 1764238Smckusick if ((ip->di_mode&IFMT)==0 && ecount[i]==0) 1774238Smckusick return; 1784238Smckusick if (ip->di_nlink==ecount[i] && ip->di_nlink!=0) 1794238Smckusick return; 1804238Smckusick if (headpr==0) { 1814238Smckusick printf(" entries link cnt\n"); 1824238Smckusick headpr++; 1834238Smckusick } 1844238Smckusick printf("%u\t%d\t%d\n", ino, 1854238Smckusick ecount[i], ip->di_nlink); 1864238Smckusick } 1874238Smckusick 1885946Smckusic /* 1895946Smckusic * get next entry in a directory. 1905946Smckusic */ 1915946Smckusic struct direct * 1925946Smckusic readdir(dirp) 1935946Smckusic register struct dirstuff *dirp; 1945946Smckusic { 1955946Smckusic register struct direct *dp; 1965946Smckusic daddr_t lbn, d; 1975946Smckusic 1985946Smckusic for(;;) { 1995946Smckusic if (dirp->loc >= dirp->ip->di_size) 2005946Smckusic return NULL; 2015957Smckusic if ((lbn = lblkno(&sblock, dirp->loc)) == 0) { 2025946Smckusic d = bmap(lbn); 2035946Smckusic if(d == 0) 2045946Smckusic return NULL; 2055946Smckusic bread(fsbtodb(&sblock, d), dirp->dbuf, 2065946Smckusic dblksize(&sblock, dirp->ip, lbn)); 2075946Smckusic } 2085946Smckusic dp = (struct direct *) 2095957Smckusic (dirp->dbuf + blkoff(&sblock, dirp->loc)); 2105946Smckusic dirp->loc += dp->d_reclen; 2115946Smckusic if (dp->d_ino == 0) 2125946Smckusic continue; 2135946Smckusic return (dp); 2145946Smckusic } 2155946Smckusic } 2165946Smckusic 2174238Smckusick bread(bno, buf, cnt) 2184238Smckusick daddr_t bno; 2194238Smckusick char *buf; 2204238Smckusick { 2214238Smckusick register i; 2224238Smckusick 223*30558Smckusick lseek(fi, bno * dev_bsize, 0); 2244238Smckusick if (read(fi, buf, cnt) != cnt) { 2254238Smckusick printf("read error %d\n", bno); 2265326Smckusic for(i=0; i < cnt; i++) 2274238Smckusick buf[i] = 0; 2284238Smckusick } 2294238Smckusick } 2304238Smckusick 2314238Smckusick daddr_t 2324238Smckusick bmap(i) 2334238Smckusick { 2345326Smckusic daddr_t ibuf[MAXNINDIR]; 2354238Smckusick 2364238Smckusick if(i < NDADDR) 2374253Smckusic return(gip->di_db[i]); 2384238Smckusick i -= NDADDR; 2395326Smckusic if(i > NINDIR(&sblock)) { 2404238Smckusick printf("%u - huge directory\n", ino); 2414238Smckusick return((daddr_t)0); 2424238Smckusick } 2435326Smckusic bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf)); 2444238Smckusick return(ibuf[i]); 2454238Smckusick } 246