1*22489Sdist /* 2*22489Sdist * Copyright (c) 1980 Regents of the University of California. 3*22489Sdist * All rights reserved. The Berkeley software License Agreement 4*22489Sdist * specifies the terms and conditions for redistribution. 5*22489Sdist */ 6*22489Sdist 713550Ssam #ifndef lint 8*22489Sdist char copyright[] = 9*22489Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10*22489Sdist All rights reserved.\n"; 11*22489Sdist #endif not lint 12*22489Sdist 13*22489Sdist #ifndef lint 14*22489Sdist static char sccsid[] = "@(#)dcheck.c 5.1 (Berkeley) 06/06/85"; 15*22489Sdist #endif not lint 16*22489Sdist 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; 504238Smckusick 514238Smckusick int nerror; 524238Smckusick daddr_t bmap(); 534238Smckusick long atol(); 544238Smckusick char *malloc(); 554238Smckusick 564238Smckusick main(argc, argv) 574238Smckusick char *argv[]; 584238Smckusick { 594238Smckusick register i; 604238Smckusick long n; 614238Smckusick 624238Smckusick while (--argc) { 634238Smckusick argv++; 644238Smckusick if (**argv=='-') 654238Smckusick switch ((*argv)[1]) { 664238Smckusick 674238Smckusick case 'i': 684238Smckusick for(i=0; i<NB; i++) { 694238Smckusick n = atol(argv[1]); 704238Smckusick if(n == 0) 714238Smckusick break; 724238Smckusick ilist[i] = n; 734238Smckusick argv++; 744238Smckusick argc--; 754238Smckusick } 764238Smckusick ilist[i] = 0; 774238Smckusick continue; 784238Smckusick 794238Smckusick default: 804238Smckusick printf("Bad flag %c\n", (*argv)[1]); 814238Smckusick nerror++; 824238Smckusick } 834238Smckusick check(*argv); 844238Smckusick } 854238Smckusick return(nerror); 864238Smckusick } 874238Smckusick 884238Smckusick check(file) 894238Smckusick char *file; 904238Smckusick { 914238Smckusick register i, j, c; 924238Smckusick 934238Smckusick fi = open(file, 0); 944238Smckusick if(fi < 0) { 954238Smckusick printf("cannot open %s\n", file); 964238Smckusick nerror++; 974238Smckusick return; 984238Smckusick } 994238Smckusick headpr = 0; 1004238Smckusick printf("%s:\n", file); 1014238Smckusick sync(); 1025348Smckusic bread(SBLOCK, (char *)&sblock, SBSIZE); 1034238Smckusick if (sblock.fs_magic != FS_MAGIC) { 1044238Smckusick printf("%s: not a file system\n", file); 1054238Smckusick nerror++; 1064238Smckusick return; 1074238Smckusick } 1084238Smckusick nfiles = sblock.fs_ipg * sblock.fs_ncg; 1094238Smckusick ecount = (ino_t *)malloc((nfiles+1) * sizeof (*ecount)); 1104238Smckusick if (ecount == 0) { 1114238Smckusick printf("%s: not enough core for %d files\n", file, nfiles); 1124238Smckusick exit(04); 1134238Smckusick } 1144238Smckusick for (i = 0; i<=nfiles; i++) 1154238Smckusick ecount[i] = 0; 1164238Smckusick ino = 0; 1174238Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1185379Smckusic bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 1194238Smckusick sblock.fs_ipg * sizeof (struct dinode)); 1204238Smckusick for (j = 0; j < sblock.fs_ipg; j++) { 1214238Smckusick pass1(&itab[j]); 1224238Smckusick ino++; 1234238Smckusick } 1244238Smckusick } 1254238Smckusick ino = 0; 1264238Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 1275379Smckusic bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 1284238Smckusick sblock.fs_ipg * sizeof (struct dinode)); 1294238Smckusick for (j = 0; j < sblock.fs_ipg; j++) { 1304238Smckusick pass2(&itab[j]); 1314238Smckusick ino++; 1324238Smckusick } 1334238Smckusick } 1344238Smckusick free(ecount); 1354238Smckusick } 1364238Smckusick 1374238Smckusick pass1(ip) 1385946Smckusic register struct dinode *ip; 1394238Smckusick { 1405946Smckusic register struct direct *dp; 1415946Smckusic struct dirstuff dirp; 1424238Smckusick int k; 1434238Smckusick 1444238Smckusick if((ip->di_mode&IFMT) != IFDIR) 1454238Smckusick return; 1465946Smckusic dirp.loc = 0; 1475946Smckusic dirp.ip = ip; 1484253Smckusic gip = ip; 1495946Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 1505946Smckusic if(dp->d_ino == 0) 1515946Smckusic continue; 1525946Smckusic if(dp->d_ino > nfiles || dp->d_ino < ROOTINO) { 1535946Smckusic printf("%d bad; %d/%s\n", 1545946Smckusic dp->d_ino, ino, dp->d_name); 1555946Smckusic nerror++; 1565946Smckusic continue; 1575946Smckusic } 1585946Smckusic for (k = 0; ilist[k] != 0; k++) 1595946Smckusic if (ilist[k] == dp->d_ino) { 1605946Smckusic printf("%d arg; %d/%s\n", 1615946Smckusic dp->d_ino, ino, dp->d_name); 1624238Smckusick nerror++; 1634238Smckusick } 1645946Smckusic ecount[dp->d_ino]++; 1654238Smckusick } 1664238Smckusick } 1674238Smckusick 1684238Smckusick pass2(ip) 1694238Smckusick register struct dinode *ip; 1704238Smckusick { 1714238Smckusick register i; 1724238Smckusick 1734238Smckusick i = ino; 1744238Smckusick if ((ip->di_mode&IFMT)==0 && ecount[i]==0) 1754238Smckusick return; 1764238Smckusick if (ip->di_nlink==ecount[i] && ip->di_nlink!=0) 1774238Smckusick return; 1784238Smckusick if (headpr==0) { 1794238Smckusick printf(" entries link cnt\n"); 1804238Smckusick headpr++; 1814238Smckusick } 1824238Smckusick printf("%u\t%d\t%d\n", ino, 1834238Smckusick ecount[i], ip->di_nlink); 1844238Smckusick } 1854238Smckusick 1865946Smckusic /* 1875946Smckusic * get next entry in a directory. 1885946Smckusic */ 1895946Smckusic struct direct * 1905946Smckusic readdir(dirp) 1915946Smckusic register struct dirstuff *dirp; 1925946Smckusic { 1935946Smckusic register struct direct *dp; 1945946Smckusic daddr_t lbn, d; 1955946Smckusic 1965946Smckusic for(;;) { 1975946Smckusic if (dirp->loc >= dirp->ip->di_size) 1985946Smckusic return NULL; 1995957Smckusic if ((lbn = lblkno(&sblock, dirp->loc)) == 0) { 2005946Smckusic d = bmap(lbn); 2015946Smckusic if(d == 0) 2025946Smckusic return NULL; 2035946Smckusic bread(fsbtodb(&sblock, d), dirp->dbuf, 2045946Smckusic dblksize(&sblock, dirp->ip, lbn)); 2055946Smckusic } 2065946Smckusic dp = (struct direct *) 2075957Smckusic (dirp->dbuf + blkoff(&sblock, dirp->loc)); 2085946Smckusic dirp->loc += dp->d_reclen; 2095946Smckusic if (dp->d_ino == 0) 2105946Smckusic continue; 2115946Smckusic return (dp); 2125946Smckusic } 2135946Smckusic } 2145946Smckusic 2154238Smckusick bread(bno, buf, cnt) 2164238Smckusick daddr_t bno; 2174238Smckusick char *buf; 2184238Smckusick { 2194238Smckusick register i; 2204238Smckusick 2215326Smckusic lseek(fi, bno * DEV_BSIZE, 0); 2224238Smckusick if (read(fi, buf, cnt) != cnt) { 2234238Smckusick printf("read error %d\n", bno); 2245326Smckusic for(i=0; i < cnt; i++) 2254238Smckusick buf[i] = 0; 2264238Smckusick } 2274238Smckusick } 2284238Smckusick 2294238Smckusick daddr_t 2304238Smckusick bmap(i) 2314238Smckusick { 2325326Smckusic daddr_t ibuf[MAXNINDIR]; 2334238Smckusick 2344238Smckusick if(i < NDADDR) 2354253Smckusic return(gip->di_db[i]); 2364238Smckusick i -= NDADDR; 2375326Smckusic if(i > NINDIR(&sblock)) { 2384238Smckusick printf("%u - huge directory\n", ino); 2394238Smckusick return((daddr_t)0); 2404238Smckusick } 2415326Smckusic bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf)); 2424238Smckusick return(ibuf[i]); 2434238Smckusick } 244