# #define DNBSZ 512 /* Amount of data in disk list */ #define NDISKS 32 /* Maximum number of disk names */ char dnames[DNBSZ]; char *dargv[NDISKS] { 0 }; #define NINOBLK 16 /* Number of inodes per disk block */ #define NIBLK 8 /* Inode buffer size (in blocks) */ #define NINODE NIBLK*NINOBLK #define NI 20 /* Max no of inodes specified to search for */ #ifdef USR #include "/usr/sys/ino.h" #include "/usr/sys/filsys.h" #endif #ifndef USR #include "/sys/ino.h" #include "/sys/filsys.h" #endif struct inode inode[NINODE]; struct filsys sblock; int dflg; int sflg; int headpr; int ilist[NI] { -1}; int fi; char *ecount; char *lasts; int ino; int nerror; int nfiles; struct dir { int ino; char name[14]; }; main(argc, argv) char **argv; { register char **p; register int n, *lp; ecount = sbrk(0); if (argc == 1) { rddsknames(); for (p = dargv; *p;) check(*p++); return(nerror); } while (--argc) { argv++; if (**argv=='-') switch ((*argv)[1]) { case 'd': dflg++; continue; case 's': sflg++; continue; case 'i': lp = ilist; while (lp < &ilist[NI-1] && (n = number(argv[1]))) { *lp++ = n; argv++; argc--; } *lp++ = -1; continue; default: printf("Bad flag\n"); } check(*argv); } return(nerror); } rddsknames() { register char *cp; register char **dp; char *dend; int dtab, dtsz, len; cp = &dnames[0]; dp = &dargv[0]; dtab = open("/etc/disks", 0); if (dtab < 0) bail("Can't open disk table file"); dtsz = read(dtab, cp, DNBSZ); if (dtsz < 0) bail("Can't read disk table file"); close(dtab); len = 0; for (dend = &dnames[dtsz]; (cp < dend); cp++) { if (len++ == 0) *dp++ = cp; if (*cp != '\n') continue; *cp = '\0'; len = 0; } *dp++ = 0; } /* There is still a potential minor bug here: on a disk with N inode * numbers, they run from 1-N, so a table indexed by inode numbers * has to be of size N+1. The sbrk() call sets the size of the 'heap' * to N - i.e. it depends on the number of inodes not being a multiple * of a click, so there's a few extra bytes there, enough for that extra * cell. */ check(file) char *file; { register i, j; fi = open(file, 0); if(fi < 0) { printf("cannot open %s\n", file); return; } headpr = 0; printf("%s:\n", file); sync(); bread(1, &sblock, 512); nfiles = sblock.s_isize*16; if (lasts < nfiles) { if ((sbrk(nfiles - lasts)) == -1) { printf("Not enough core\n"); exit(04); } lasts = nfiles; } for (i=0; i<=nfiles; i++) ecount[i] = 0; if (dflg) { printf("p1: %l\n", nfiles); for (i=0; ilist[i] != -1; i++) printf(" %d %d\n", ilist[i], ecount[ilist[i]]); } ino = 0; for(i=0; inoi_mode&IALLOC) == 0) return; if((ip->i_mode&IFMT) != IFDIR) return; doff = 0; while (dp = dread(ip, doff)) { doff =+ 16; if (dp->ino==0) continue; for (i=0; ilist[i] != -1; i++) if (ilist[i]==dp->ino) printf("%5l as %l-%.14s\n", dp->ino, ino, dp->name); ecount[dp->ino]++; } } pass2(aip) { register struct inode *ip; register i; ip = aip; i = ino; if ((ip->i_mode&IALLOC)==0 && ecount[i]==0) return; if (ip->i_nlink==ecount[i] && ip->i_nlink!=0) return; if (headpr==0) { printf("entries link cnt\n"); headpr++; } printf("%l %d %d\n", ino, ecount[i]&0377, ip->i_nlink&0377); } dread(aip, aoff) { register b, off; register struct inode *ip; static ibuf[256]; static char buf[512]; off = aoff; ip = aip; if ((off&0777)==0) { if (off==0177000) { printf("Monstrous directory %l\n", ino); return(0); } if ((ip->i_mode&ILARG)==0) { if (off>=010000 || (b = ip->i_addr[off>>9])==0) return(0); bread(b, buf, 512); } else { if (off==0) { if (ip->i_addr[0]==0) return(0); bread(ip->i_addr[0], ibuf, 512); } if ((b = ibuf[(off>>9)&0177])==0) return(0); bread(b, buf, 512); } } return(&buf[off&0777]); } bread(bno, buf, cnt) { int rd; seek(fi, bno, 3); if((rd = read(fi, buf, cnt)) != cnt) { printf("read error blk %d ask %d got %d\n", bno, cnt, rd); exit(1); } } number(as) char *as; { register n, c; register char *s; s = as; n = 0; while ((c = *s++) >= '0' && c <= '9') { n = n*10+c-'0'; } return(n); } bail(err) char *err; { printf("%s\n", err); exit(1); }