/*- * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * %sccs.include.proprietary.c% */ #ifndef lint static char copyright[] = "@(#) Copyright (c) 1988, 1990, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)ncheck.c 8.1 (Berkeley) 06/05/93"; #endif /* not lint */ /* * ncheck -- obtain file names from reading filesystem */ #define NB 500 #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) #include #include #include #include #include #include #include struct fs *sblockp; struct dinode itab[MAXBSIZE/sizeof(struct dinode)]; struct dinode *gip; struct ilist { ino_t ino; u_short mode; short uid; short gid; } ilist[NB]; struct htab { ino_t h_ino; ino_t h_pino; char *h_name; } *htab; char *strngtab; long hsize; int strngloc; struct dirstuff { int loc; struct dinode *ip; char dbuf[MAXBSIZE]; }; int aflg; int sflg; int iflg; /* number of inodes being searched for */ int mflg; int fi; ino_t ino; int nhent; int nxfile; int dev_bsize = 1; int nerror; daddr_t bmap(); long atol(); char *malloc(), *strcpy(); struct htab *lookup(); struct direct *nreaddir(); main(argc, argv) int argc; char *argv[]; { long n; while (--argc) { argv++; if (**argv=='-') switch ((*argv)[1]) { case 'a': aflg++; continue; case 'i': for(iflg=0; iflg= 2; iflg++) { n = atol(argv[1]); if(n == 0) break; ilist[iflg].ino = n; nxfile = iflg; argv++; argc--; } continue; case 'm': mflg++; continue; case 's': sflg++; continue; default: (void) fprintf(stderr, "ncheck: bad flag %c\n", (*argv)[1]); nerror++; } check(*argv); } return(nerror); } check(file) char *file; { register int i, j, c; fi = open(file, 0); if(fi < 0) { (void) fprintf(stderr, "ncheck: cannot open %s\n", file); nerror++; return; } nhent = 0; (void) printf("%s:\n", file); sync(); dev_bsize = 1; sblockp = (struct fs *)malloc((unsigned)SBSIZE); if (sblockp == 0) { (void) printf("icheck: couldn't malloc superblock memory\n"); nerror++; return; } bread((daddr_t)SBOFF, (char *)sblockp, (long)SBSIZE); if (sblockp->fs_magic != FS_MAGIC) { (void) printf("%s: not a file system\n", file); nerror++; return; } dev_bsize = sblockp->fs_fsize / fsbtodb(sblockp, 1); hsize = sblockp->fs_ipg * sblockp->fs_ncg - sblockp->fs_cstotal.cs_nifree + 1; htab = (struct htab *)malloc((unsigned)hsize * sizeof(struct htab)); strngtab = malloc((unsigned)(30 * hsize)); if (htab == 0 || strngtab == 0) { (void) printf("not enough memory to allocate tables\n"); nerror++; return; } ino = 0; for (c = 0; c < sblockp->fs_ncg; c++) { for (i = 0; i < sblockp->fs_ipg / INOPF(sblockp); i += sblockp->fs_frag) { bread(fsbtodb(sblockp, cgimin(sblockp, c) + i), (char *)itab, sblockp->fs_bsize); for (j = 0; j < INOPB(sblockp); j++) { if (itab[j].di_mode != 0) pass1(&itab[j]); ino++; } } } ilist[nxfile+1].ino = 0; ino = 0; for (c = 0; c < sblockp->fs_ncg; c++) { for (i = 0; i < sblockp->fs_ipg / INOPF(sblockp); i += sblockp->fs_frag) { bread(fsbtodb(sblockp, cgimin(sblockp, c) + i), (char *)itab, sblockp->fs_bsize); for (j = 0; j < INOPB(sblockp); j++) { if (itab[j].di_mode != 0) pass2(&itab[j]); ino++; } } } ino = 0; for (c = 0; c < sblockp->fs_ncg; c++) { for (i = 0; i < sblockp->fs_ipg / INOPF(sblockp); i += sblockp->fs_frag) { bread(fsbtodb(sblockp, cgimin(sblockp, c) + i), (char *)itab, sblockp->fs_bsize); for (j = 0; j < INOPB(sblockp); j++) { if (itab[j].di_mode != 0) pass3(&itab[j]); ino++; } } } (void) close(fi); for (i = 0; i < hsize; i++) htab[i].h_ino = 0; for (i = iflg; i < NB; i++) ilist[i].ino = 0; nxfile = iflg; } pass1(ip) register struct dinode *ip; { int i; if (mflg) for (i = 0; i < iflg; i++) if (ino == ilist[i].ino) { ilist[i].mode = ip->di_mode; ilist[i].uid = ip->di_uid; ilist[i].gid = ip->di_gid; } if ((ip->di_mode & IFMT) != IFDIR) { if (sflg==0 || nxfile>=NB) return; if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR || ip->di_mode&(ISUID|ISGID)) { ilist[nxfile].ino = ino; ilist[nxfile].mode = ip->di_mode; ilist[nxfile].uid = ip->di_uid; ilist[nxfile++].gid = ip->di_gid; return; } } (void) lookup(ino, 1); } pass2(ip) register struct dinode *ip; { register struct direct *dp; struct dirstuff dirp; struct htab *hp; if((ip->di_mode&IFMT) != IFDIR) return; dirp.loc = 0; dirp.ip = ip; gip = ip; for (dp = nreaddir(&dirp); dp != NULL; dp = nreaddir(&dirp)) { if(dp->d_ino == 0) continue; hp = lookup(dp->d_ino, 0); if(hp == 0) continue; if(dotname(dp)) continue; hp->h_pino = ino; hp->h_name = &strngtab[strngloc]; strngloc += strlen(dp->d_name) + 1; (void) strcpy(hp->h_name, dp->d_name); } } pass3(ip) register struct dinode *ip; { register struct direct *dp; struct dirstuff dirp; int k; if((ip->di_mode&IFMT) != IFDIR) return; dirp.loc = 0; dirp.ip = ip; gip = ip; for(dp = nreaddir(&dirp); dp != NULL; dp = nreaddir(&dirp)) { if(aflg==0 && dotname(dp)) continue; if(sflg == 0 && iflg == 0) goto pr; for(k = 0; ilist[k].ino != 0; k++) if(ilist[k].ino == dp->d_ino) break; if (ilist[k].ino == 0) continue; if (mflg) (void) printf("mode %-6o uid %-5d gid %-5d ino ", ilist[k].mode, ilist[k].uid, ilist[k].gid); pr: (void) printf("%-5lu\t", dp->d_ino); pname(ino, 0); (void) printf("/%s", dp->d_name); if (lookup(dp->d_ino, 0)) (void) printf("/."); (void) printf("\n"); } } /* * get next entry in a directory. */ struct direct * nreaddir(dirp) register struct dirstuff *dirp; { register struct direct *dp; daddr_t lbn, d; for(;;) { if (dirp->loc >= dirp->ip->di_size) return NULL; if (blkoff(sblockp, dirp->loc) == 0) { lbn = lblkno(sblockp, dirp->loc); d = bmap(lbn); if(d == 0) return NULL; bread(fsbtodb(sblockp, d), dirp->dbuf, (long)dblksize(sblockp, dirp->ip, lbn)); } dp = (struct direct *) (dirp->dbuf + blkoff(sblockp, dirp->loc)); dirp->loc += dp->d_reclen; if (dp->d_ino == 0) continue; return (dp); } } dotname(dp) register struct direct *dp; { if (dp->d_name[0]=='.') if (dp->d_name[1]==0 || (dp->d_name[1]=='.' && dp->d_name[2]==0)) return(1); return(0); } pname(i, lev) ino_t i; int lev; { register struct htab *hp; if (i==ROOTINO) return; if ((hp = lookup(i, 0)) == 0) { (void) printf("???"); return; } if (lev > 10) { (void) printf("..."); return; } pname(hp->h_pino, ++lev); (void) printf("/%s", hp->h_name); } struct htab * lookup(i, ef) ino_t i; int ef; { register struct htab *hp; for (hp = &htab[i%hsize]; hp->h_ino;) { if (hp->h_ino==i) return(hp); if (++hp >= &htab[hsize]) hp = htab; } if (ef==0) return(0); if (++nhent >= hsize) { (void) fprintf(stderr, "ncheck: hsize of %ld is too small\n", hsize); exit(1); } hp->h_ino = i; return(hp); } bread(bno, buf, lcount) daddr_t bno; register char *buf; long lcount; { register int i, cnt = lcount; register off_t off = bno * dev_bsize; (void) lseek(fi, off, SEEK_SET); if (read(fi, buf, cnt) != cnt) { (void) fprintf(stderr, "ncheck: read error %ld\n", bno); if (cnt % dev_bsize) { /* THIS INDICATES A SERIOUS BUG */ /* bzero is probably not correct, but will do */ (void) fprintf(stderr, "ncheck: bread: cnt %d not multiple of %d\n", cnt, dev_bsize); bzero(buf, cnt); return; } for (i = 0; i < cnt; i += dev_bsize) { (void) lseek(fi, off, SEEK_SET); if (read(fi, buf, dev_bsize) != dev_bsize) { (void) fprintf(stderr, "ncheck: re-read error %ld\n", bno); bzero(buf, dev_bsize); } off += dev_bsize; buf += dev_bsize; bno++; } } } /* * Swiped from standalone sys.c. */ #define NBUFS 4 char b[NBUFS][MAXBSIZE]; daddr_t blknos[NBUFS]; daddr_t bmap(bn) register daddr_t bn; { register int j; int i, sh; daddr_t nb, *bap; if (bn < 0) { (void) fprintf(stderr, "ncheck: bn %ld negative\n", bn); return ((daddr_t)0); } /* * blocks 0..NDADDR are direct blocks */ if(bn < NDADDR) return(gip->di_db[bn]); /* * addresses NIADDR have single and double indirect blocks. * the first step is to determine how many levels of indirection. */ sh = 1; bn -= NDADDR; for (j = NIADDR; j > 0; j--) { sh *= NINDIR(sblockp); if (bn < sh) break; bn -= sh; } if (j == 0) { (void) printf("ncheck: bn %ld ovf, ino %lu\n", bn, ino); return ((daddr_t)0); } /* * fetch the first indirect block address from the inode */ nb = gip->di_ib[NIADDR - j]; if (nb == 0) { (void) printf("ncheck: bn %ld void1, ino %lu\n", bn, ino); return ((daddr_t)0); } /* * fetch through the indirect blocks */ for (; j <= NIADDR; j++) { if (blknos[j] != nb) { bread(fsbtodb(sblockp, nb), b[j], sblockp->fs_bsize); blknos[j] = nb; } bap = (daddr_t *)b[j]; sh /= NINDIR(sblockp); i = (bn / sh) % NINDIR(sblockp); nb = bap[i]; if(nb == 0) { (void) printf("ncheck: bn %ld void2, ino %lu\n", bn, ino); return ((daddr_t)0); } } return (nb); }