/* * dcheck - check directory consistency */ #define NI 16 #define NB 10 #define NDIR (BSIZE/sizeof(struct direct)) #include <stdio.h> #include <sys/param.h> #include <sys/inode.h> #include <sys/ino.h> #include <sys/dir.h> #include <sys/filsys.h> #include <sys/fblk.h> struct filsys sblock; struct dinode itab[INOPB*NI]; daddr_t iaddr[NADDR]; ino_t ilist[NB]; int fi; ino_t ino; char *ecount; int headpr; unsigned nfiles; int nerror; daddr_t bmap(); long atol(); char *malloc(); main(argc, argv) char *argv[]; { register i; long n; while (--argc) { argv++; if (**argv=='-') switch ((*argv)[1]) { case 'i': for(i=0; i<NB; i++) { n = atol(argv[1]); if(n == 0) break; ilist[i] = n; argv++; argc--; } ilist[i] = 0; continue; default: printf("Bad flag %c\n", (*argv)[1]); nerror++; } check(*argv); } return(nerror); } check(file) char *file; { register i; register j; fi = open(file, 0); if(fi < 0) { printf("cannot open %s\n", file); nerror++; return; } headpr = 0; printf("%s:\n", file); sync(); bread((daddr_t)1, (char *)&sblock, sizeof(sblock)); nfiles = (sblock.s_isize-2)*INOPB; if (nfiles > 40000) { printf("Only doing 40000 files\n"); nfiles = 40000; } ecount = malloc(nfiles+1); if (ecount==NULL) { printf("Not enough core\n"); exit(04); } for (i=0; i<=nfiles; i++) ecount[i] = 0; ino = 0; for(i=2;; i+=NI) { if(ino >= nfiles) break; bread((daddr_t)i, (char *)itab, sizeof(itab)); for(j=0; j<INOPB*NI; j++) { if(ino >= nfiles) break; ino++; pass1(&itab[j]); } } ino = 0; for(i=2;; i+=NI) { if(ino >= nfiles) break; bread((daddr_t)i, (char *)itab, sizeof(itab)); for(j=0; j<INOPB*NI; j++) { if(ino >= nfiles) break; ino++; pass2(&itab[j]); } } free(ecount); } pass1(ip) register struct dinode *ip; { struct direct dbuf[NDIR]; long doff; struct direct *dp; register i, j; int k; daddr_t d; ino_t kno; if((ip->di_mode&IFMT) != IFDIR) return; l3tol(iaddr, ip->di_addr, NADDR); doff = 0; for(i=0;; i++) { if(doff >= ip->di_size) break; d = bmap(i); if(d == 0) break; bread(d, (char *)dbuf, BSIZE); for(j=0; j<NDIR; j++) { if(doff >= ip->di_size) break; doff += sizeof(struct direct); dp = &dbuf[j]; kno = dp->d_ino; if(kno == 0) continue; if(kno > nfiles || kno <= 1) { printf("%5u bad; %u/%.14s\n", kno, ino, dp->d_name); nerror++; continue; } for (k=0; ilist[k] != 0; k++) if (ilist[k]==kno) { printf("%5u arg; %u/%.14s\n", kno, ino, dp->d_name); nerror++; } ecount[kno]++; if (ecount[kno] == 0) ecount[kno] = 0377; } } } pass2(ip) register struct dinode *ip; { register i; i = ino; if ((ip->di_mode&IFMT)==0 && ecount[i]==0) return; if (ip->di_nlink==((ecount[i])&0377) && ip->di_nlink!=0) return; if (ino < ROOTINO && ip->di_nlink==0 && ecount[i]==0) return; if (headpr==0) { printf(" entries link cnt\n"); headpr++; } printf("%u %d %d\n", ino, ecount[i]&0377, ip->di_nlink); } bread(bno, buf, cnt) daddr_t bno; char *buf; { register i; lseek(fi, bno*BSIZE, 0); if (read(fi, buf, cnt) != cnt) { printf("read error %D\n", bno); for(i=0; i<BSIZE; i++) buf[i] = 0; } } daddr_t bmap(i) { daddr_t ibuf[NINDIR]; if(i < NADDR-3) return(iaddr[i]); i -= NADDR-3; if(i > NINDIR) { printf("%u - huge directory\n", ino); return((daddr_t)0); } bread(iaddr[NADDR-3], (char *)ibuf, sizeof(ibuf)); return(ibuf[i]); }