1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)dcheck.c 5.1 (Berkeley) 6/6/85"; 15: #endif not lint 16: 17: /* 18: * dcheck - check directory consistency 19: */ 20: #define NB 10 21: #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 22: 23: #include <sys/param.h> 24: #include <sys/inode.h> 25: #include <sys/fs.h> 26: #include <sys/dir.h> 27: #include <stdio.h> 28: 29: union { 30: struct fs fs; 31: char pad[MAXBSIZE]; 32: } fsun; 33: #define sblock fsun.fs 34: 35: struct dirstuff { 36: int loc; 37: struct dinode *ip; 38: char dbuf[MAXBSIZE]; 39: }; 40: 41: struct dinode itab[MAXIPG]; 42: struct dinode *gip; 43: ino_t ilist[NB]; 44: 45: int fi; 46: ino_t ino; 47: ino_t *ecount; 48: int headpr; 49: int nfiles; 50: 51: int nerror; 52: daddr_t bmap(); 53: long atol(); 54: char *malloc(); 55: 56: main(argc, argv) 57: char *argv[]; 58: { 59: register i; 60: long n; 61: 62: while (--argc) { 63: argv++; 64: if (**argv=='-') 65: switch ((*argv)[1]) { 66: 67: case 'i': 68: for(i=0; i<NB; i++) { 69: n = atol(argv[1]); 70: if(n == 0) 71: break; 72: ilist[i] = n; 73: argv++; 74: argc--; 75: } 76: ilist[i] = 0; 77: continue; 78: 79: default: 80: printf("Bad flag %c\n", (*argv)[1]); 81: nerror++; 82: } 83: check(*argv); 84: } 85: return(nerror); 86: } 87: 88: check(file) 89: char *file; 90: { 91: register i, j, c; 92: 93: fi = open(file, 0); 94: if(fi < 0) { 95: printf("cannot open %s\n", file); 96: nerror++; 97: return; 98: } 99: headpr = 0; 100: printf("%s:\n", file); 101: sync(); 102: bread(SBLOCK, (char *)&sblock, SBSIZE); 103: if (sblock.fs_magic != FS_MAGIC) { 104: printf("%s: not a file system\n", file); 105: nerror++; 106: return; 107: } 108: nfiles = sblock.fs_ipg * sblock.fs_ncg; 109: ecount = (ino_t *)malloc((nfiles+1) * sizeof (*ecount)); 110: if (ecount == 0) { 111: printf("%s: not enough core for %d files\n", file, nfiles); 112: exit(04); 113: } 114: for (i = 0; i<=nfiles; i++) 115: ecount[i] = 0; 116: ino = 0; 117: for (c = 0; c < sblock.fs_ncg; c++) { 118: bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 119: sblock.fs_ipg * sizeof (struct dinode)); 120: for (j = 0; j < sblock.fs_ipg; j++) { 121: pass1(&itab[j]); 122: ino++; 123: } 124: } 125: ino = 0; 126: for (c = 0; c < sblock.fs_ncg; c++) { 127: bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, 128: sblock.fs_ipg * sizeof (struct dinode)); 129: for (j = 0; j < sblock.fs_ipg; j++) { 130: pass2(&itab[j]); 131: ino++; 132: } 133: } 134: free(ecount); 135: } 136: 137: pass1(ip) 138: register struct dinode *ip; 139: { 140: register struct direct *dp; 141: struct dirstuff dirp; 142: int k; 143: 144: if((ip->di_mode&IFMT) != IFDIR) 145: return; 146: dirp.loc = 0; 147: dirp.ip = ip; 148: gip = ip; 149: for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 150: if(dp->d_ino == 0) 151: continue; 152: if(dp->d_ino > nfiles || dp->d_ino < ROOTINO) { 153: printf("%d bad; %d/%s\n", 154: dp->d_ino, ino, dp->d_name); 155: nerror++; 156: continue; 157: } 158: for (k = 0; ilist[k] != 0; k++) 159: if (ilist[k] == dp->d_ino) { 160: printf("%d arg; %d/%s\n", 161: dp->d_ino, ino, dp->d_name); 162: nerror++; 163: } 164: ecount[dp->d_ino]++; 165: } 166: } 167: 168: pass2(ip) 169: register struct dinode *ip; 170: { 171: register i; 172: 173: i = ino; 174: if ((ip->di_mode&IFMT)==0 && ecount[i]==0) 175: return; 176: if (ip->di_nlink==ecount[i] && ip->di_nlink!=0) 177: return; 178: if (headpr==0) { 179: printf(" entries link cnt\n"); 180: headpr++; 181: } 182: printf("%u\t%d\t%d\n", ino, 183: ecount[i], ip->di_nlink); 184: } 185: 186: /* 187: * get next entry in a directory. 188: */ 189: struct direct * 190: readdir(dirp) 191: register struct dirstuff *dirp; 192: { 193: register struct direct *dp; 194: daddr_t lbn, d; 195: 196: for(;;) { 197: if (dirp->loc >= dirp->ip->di_size) 198: return NULL; 199: if ((lbn = lblkno(&sblock, dirp->loc)) == 0) { 200: d = bmap(lbn); 201: if(d == 0) 202: return NULL; 203: bread(fsbtodb(&sblock, d), dirp->dbuf, 204: dblksize(&sblock, dirp->ip, lbn)); 205: } 206: dp = (struct direct *) 207: (dirp->dbuf + blkoff(&sblock, dirp->loc)); 208: dirp->loc += dp->d_reclen; 209: if (dp->d_ino == 0) 210: continue; 211: return (dp); 212: } 213: } 214: 215: bread(bno, buf, cnt) 216: daddr_t bno; 217: char *buf; 218: { 219: register i; 220: 221: lseek(fi, bno * DEV_BSIZE, 0); 222: if (read(fi, buf, cnt) != cnt) { 223: printf("read error %d\n", bno); 224: for(i=0; i < cnt; i++) 225: buf[i] = 0; 226: } 227: } 228: 229: daddr_t 230: bmap(i) 231: { 232: daddr_t ibuf[MAXNINDIR]; 233: 234: if(i < NDADDR) 235: return(gip->di_db[i]); 236: i -= NDADDR; 237: if(i > NINDIR(&sblock)) { 238: printf("%u - huge directory\n", ino); 239: return((daddr_t)0); 240: } 241: bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf)); 242: return(ibuf[i]); 243: }