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: #if !defined(lint) && defined(DOSCCS) 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: static char sccsid[] = "@(#)dcheck.c 5.1 (Berkeley) 6/6/85"; 12: #endif 13: 14: /* 15: * dcheck - check directory consistency 16: */ 17: #define NI 8 18: #define NF 2048 19: #define NB 10 20: #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 21: 22: #include <sys/param.h> 23: #include <sys/inode.h> 24: #include <sys/fs.h> 25: #include <sys/dir.h> 26: #include <sys/file.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: off_t loc; 37: struct dinode *ip; 38: char dbuf[MAXBSIZE]; 39: }; 40: 41: struct dinode itab[NI * INOPB]; 42: struct dinode *gip; 43: ino_t ilist[NB]; 44: 45: int fi; 46: int fo; 47: ino_t ino; 48: ino_t ecount[NF]; 49: ino_t starti, endi; 50: int edirty; 51: char *tfn = "/tmp/dchkXXXXXX"; 52: int headpr; 53: ino_t nfiles; 54: 55: int nerror; 56: daddr_t bmap(); 57: extern long atol(), lseek(); 58: extern char *malloc(); 59: extern int errno; 60: 61: main(argc, argv) 62: char *argv[]; 63: { 64: register i; 65: long n; 66: 67: mktemp(tfn); 68: fo = open(tfn, O_CREAT|O_RDWR, 0600); 69: if (fo < 0) { 70: fprintf(stderr, "Can't create tmp file: %s\n", tfn); 71: exit(4); 72: } 73: unlink(tfn); 74: 75: while (--argc) { 76: argv++; 77: if (**argv=='-') 78: switch ((*argv)[1]) { 79: 80: case 'i': 81: for(i=0; i<NB; i++) { 82: n = atol(argv[1]); 83: if(n == 0) 84: break; 85: ilist[i] = (ino_t)n; 86: argv++; 87: argc--; 88: } 89: ilist[i] = 0; 90: continue; 91: 92: default: 93: printf("Bad flag %c\n", (*argv)[1]); 94: nerror++; 95: } 96: check(*argv); 97: } 98: return(nerror); 99: } 100: 101: check(file) 102: char *file; 103: { 104: register i, j; 105: 106: fi = open(file, 0); 107: if(fi < 0) { 108: printf("cannot open %s\n", file); 109: nerror++; 110: return; 111: } 112: 113: bread(SBLOCK, (char *)&sblock, SBSIZE); 114: nfiles = (sblock.fs_isize - 2) * INOPB; 115: bzero(ecount, sizeof (ecount)); 116: 117: lseek(fo, 0L, 0); 118: ftruncate(fo, 0L); 119: lseek(fo, (off_t)nfiles * sizeof (u_short), 0); 120: write(fo, ecount, sizeof (ecount)); 121: 122: headpr = 0; 123: printf("%s:\n", file); 124: sync(); 125: ino = 0; 126: for (i = 2; ; i += NI) { 127: if (ino >= nfiles) 128: break; 129: bread((daddr_t)i, (char *)itab, sizeof (itab)); 130: for (j = 0; j < INOPB * NI; j++) { 131: if (ino >= nfiles) 132: break; 133: ino++; 134: pass1(&itab[j]); 135: } 136: } 137: ino = 0; 138: for (i = 2; ; i += NI) { 139: if (ino >= nfiles) 140: break; 141: bread((daddr_t)i, (char *)itab, sizeof (itab)); 142: for (j = 0; j < INOPB * NI; j++) { 143: if (ino >= nfiles) 144: break; 145: ino++; 146: pass1(&itab[j]); 147: } 148: } 149: } 150: 151: pass1(ip) 152: register struct dinode *ip; 153: { 154: register struct direct *dp; 155: struct dirstuff dirp; 156: register int k; 157: 158: if((ip->di_mode&IFMT) != IFDIR) 159: return; 160: dirp.loc = 0; 161: dirp.ip = ip; 162: gip = ip; 163: for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 164: if(dp->d_ino == 0) 165: continue; 166: if(dp->d_ino > nfiles || dp->d_ino < ROOTINO) { 167: printf("%u bad; %u/%s\n", 168: dp->d_ino, ino, dp->d_name); 169: nerror++; 170: continue; 171: } 172: for (k = 0; ilist[k] != 0; k++) 173: if (ilist[k] == dp->d_ino) { 174: printf("%u arg; %u/%s\n", 175: dp->d_ino, ino, dp->d_name); 176: nerror++; 177: } 178: dolncnt((ino_t)dp->d_ino, 1); 179: } 180: } 181: 182: pass2(ip) 183: register struct dinode *ip; 184: { 185: register ino_t i; 186: register u_short cnt; 187: 188: i = ino; 189: cnt = dolncnt(i, 0); 190: if ((ip->di_mode&IFMT)==0 && cnt==0) 191: return; 192: if (ip->di_nlink==cnt && ip->di_nlink!=0) 193: return; 194: if (headpr==0) { 195: printf(" entries link cnt\n"); 196: headpr++; 197: } 198: printf("%u\t%d\t%d\n", ino, cnt, ip->di_nlink); 199: } 200: 201: /* 202: * get next entry in a directory. 203: */ 204: struct direct * 205: readdir(dirp) 206: register struct dirstuff *dirp; 207: { 208: register struct direct *dp; 209: daddr_t lbn, d; 210: 211: for(;;) { 212: if (dirp->loc >= dirp->ip->di_size) 213: return NULL; 214: if ((lbn = lblkno(dirp->loc)) == 0) { 215: d = bmap(lbn); 216: if(d == 0) 217: return NULL; 218: bread(d, dirp->dbuf, DEV_BSIZE); 219: } 220: dp = (struct direct *)(dirp->dbuf + blkoff(dirp->loc)); 221: dirp->loc += dp->d_reclen; 222: if (dp->d_ino == 0) 223: continue; 224: return (dp); 225: } 226: } 227: 228: bread(bno, buf, cnt) 229: daddr_t bno; 230: char *buf; 231: { 232: 233: lseek(fi, bno * DEV_BSIZE, 0); 234: if (read(fi, buf, cnt) != cnt) { 235: printf("read error %ld\n", bno); 236: bzero(buf, cnt); 237: } 238: } 239: 240: daddr_t 241: bmap(i) 242: daddr_t i; 243: { 244: daddr_t ibuf[MAXNINDIR]; 245: 246: if(i < NDADDR) 247: return(gip->di_addr[i]); 248: i -= NDADDR; 249: if(i > NINDIR) { 250: printf("%u - huge directory\n", ino); 251: return((daddr_t)0); 252: } 253: bread(gip->di_addr[NDADDR], (char *)ibuf, sizeof(ibuf)); 254: return(ibuf[i]); 255: } 256: 257: u_short 258: dolncnt(i, cnt) 259: register ino_t i; 260: register u_short cnt; 261: { 262: again: 263: if (i >= starti && i <= endi) { 264: if (cnt) 265: edirty = 1; 266: ecount[i - starti] += cnt; 267: return(ecount[i - starti]); 268: } 269: fill(i); 270: goto again; 271: } 272: 273: flush() 274: { 275: 276: if (edirty) { 277: edirty = 0; 278: if (lseek(fo, (off_t)(starti / NF) * sizeof (ecount), 0) < 0) { 279: fprintf(stderr, "lseek error %d in tmp file\n", errno); 280: return; 281: } 282: if (write(fo, ecount, sizeof (ecount)) != sizeof (ecount)) { 283: fprintf(stderr, "write error %d in tmp file\n", errno); 284: return; 285: } 286: } 287: } 288: 289: fill(i) 290: register ino_t i; 291: { 292: flush(); 293: starti = (i / NF) * NF; 294: endi = starti + NF - 1; 295: if (lseek(fo, (off_t)(starti/NF) * sizeof (ecount), 0) < 0) { 296: fprintf(stderr, "lseek error %d in tmp file\n", errno); 297: return; 298: } 299: if (read(fo, ecount, sizeof (ecount)) != sizeof (ecount)) { 300: fprintf(stderr, "read error %d in tmp file\n", errno); 301: return; 302: } 303: }