arbitrarily cut off searching around orphaned directory loops
[unix-history] / usr / src / sbin / dump / traverse.c
index e057d8e..27b4db6 100644 (file)
@@ -1,93 +1,33 @@
-static char *sccsid = "@(#)traverse.c  1.1 (Berkeley) %G%";
-#include "dump.h"
+static char *sccsid = "@(#)traverse.c  1.14 (Berkeley) %G%";
 
 
-struct filsys  sblock;
-struct dinode  itab[INOPB * NI];
+#include "dump.h"
 
 pass(fn, map)
 
 pass(fn, map)
-int (*fn)();
-short *map;
+       int (*fn)();
+       char *map;
 {
 {
-       register i, j;
+       struct dinode *dp;
        int bits;
        int bits;
-       ino_t mino;
-       daddr_t d;
-
-       sync();
-       bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
-       mino = (sblock.s_isize-2) * INOPB;
-       ino = 0;
-       for(i=2;; i+=NI) {
-               if(ino >= mino)
-                       break;
-               d = (unsigned)i;
-               for(j=0; j<INOPB*NI; j++) {
-                       if(ino >= mino)
-                               break;
-                       if((ino % MLEN) == 0) {
-                               bits = ~0;
-                               if(map != NULL)
-                                       bits = *map++;
-                       }
-                       ino++;
-                       if(bits & 1) {
-                               if(d != 0) {
-                                       bread(d, (char *)itab, sizeof(itab));
-                                       d = 0;
-                               }
-                               (*fn)(&itab[j]);
-                       }
-                       bits >>= 1;
-               }
-       }
-}
+       ino_t maxino;
 
 
-icat(ip, fn1, fn2)
-struct dinode  *ip;
-int (*fn1)(), (*fn2)();
-{
-       register i;
-       daddr_t d[NADDR];
-
-       l3tol(&d[0], &ip->di_addr[0], NADDR);
-       (*fn2)(d, NADDR-3);
-       for(i=0; i<NADDR; i++) {
-               if(d[i] != 0) {
-                       if(i < NADDR-3)
-                               (*fn1)(d[i]); else
-                               indir(d[i], fn1, fn2, i-(NADDR-3));
-               }
-       }
-}
-
-indir(d, fn1, fn2, n)
-daddr_t d;
-int (*fn1)(), (*fn2)();
-{
-       register i;
-       daddr_t idblk[NINDIR];
-
-       bread(d, (char *)idblk, sizeof(idblk));
-       if(n <= 0) {
-               spcl.c_type = TS_ADDR;
-               (*fn2)(idblk, NINDIR);
-               for(i=0; i<NINDIR; i++) {
-                       d = idblk[i];
-                       if(d != 0)
-                               (*fn1)(d);
+       maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
+       for (ino = 0; ino < maxino; ) {
+               if((ino % NBBY) == 0) {
+                       bits = ~0;
+                       if(map != NULL)
+                               bits = *map++;
                }
                }
-       } else {
-               n--;
-               for(i=0; i<NINDIR; i++) {
-                       d = idblk[i];
-                       if(d != 0)
-                               indir(d, fn1, fn2, n);
+               ino++;
+               if(bits & 1) {
+                       dp = getino(ino);
+                       (*fn)(dp);
                }
                }
+               bits >>= 1;
        }
 }
 
 mark(ip)
        }
 }
 
 mark(ip)
-struct dinode *ip;
+       struct dinode *ip;
 {
        register f;
 
 {
        register f;
 
@@ -97,10 +37,10 @@ struct dinode *ip;
        BIS(ino, clrmap);
        if(f == IFDIR)
                BIS(ino, dirmap);
        BIS(ino, clrmap);
        if(f == IFDIR)
                BIS(ino, dirmap);
-       if(ip->di_mtime >= spcl.c_ddate ||
-          ip->di_ctime >= spcl.c_ddate) {
+       if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
+           !BIT(ino, nodmap)) {
                BIS(ino, nodmap);
                BIS(ino, nodmap);
-               if (f != IFREG){
+               if (f != IFREG && f != IFDIR && f != IFLNK) {
                        esize += 1;
                        return;
                }
                        esize += 1;
                        return;
                }
@@ -109,28 +49,67 @@ struct dinode *ip;
 }
 
 add(ip)
 }
 
 add(ip)
-struct dinode *ip;
+       register struct dinode  *ip;
 {
 {
+       register int i;
+       long filesize;
 
        if(BIT(ino, nodmap))
                return;
        nsubdir = 0;
        dadded = 0;
 
        if(BIT(ino, nodmap))
                return;
        nsubdir = 0;
        dadded = 0;
-       icat(ip, dsrch, nullf);
+       filesize = ip->di_size;
+       for (i = 0; i < NDADDR; i++) {
+               if (ip->di_db[i] != 0)
+                       dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize);
+               filesize -= sblock->fs_bsize;
+       }
+       for (i = 0; i < NIADDR; i++) {
+               if (ip->di_ib[i] != 0)
+                       indir(ip->di_ib[i], i, &filesize);
+       }
        if(dadded) {
        if(dadded) {
-               BIS(ino, nodmap);
-               est(ip);
                nadded++;
                nadded++;
+               if (!BIT(ino, nodmap)) {
+                       BIS(ino, nodmap);
+                       est(ip);
+               }
        }
        if(nsubdir == 0)
                if(!BIT(ino, nodmap))
                        BIC(ino, dirmap);
 }
 
        }
        if(nsubdir == 0)
                if(!BIT(ino, nodmap))
                        BIC(ino, dirmap);
 }
 
-dump(ip)
-struct dinode *ip;
+indir(d, n, filesize)
+       daddr_t d;
+       int n, *filesize;
 {
        register i;
 {
        register i;
+       daddr_t idblk[MAXNINDIR];
+
+       bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize);
+       if(n <= 0) {
+               for(i=0; i < NINDIR(sblock); i++) {
+                       d = idblk[i];
+                       if(d != 0)
+                               dsrch(d, sblock->fs_bsize, *filesize);
+                       *filesize -= sblock->fs_bsize;
+               }
+       } else {
+               n--;
+               for(i=0; i < NINDIR(sblock); i++) {
+                       d = idblk[i];
+                       if(d != 0)
+                               indir(d, n, filesize);
+               }
+       }
+}
+
+dump(ip)
+       struct dinode *ip;
+{
+       register int i;
+       long size;
 
        if(newtape) {
                newtape = 0;
 
        if(newtape) {
                newtape = 0;
@@ -141,98 +120,172 @@ struct dinode *ip;
        spcl.c_type = TS_INODE;
        spcl.c_count = 0;
        i = ip->di_mode & IFMT;
        spcl.c_type = TS_INODE;
        spcl.c_count = 0;
        i = ip->di_mode & IFMT;
-       if(i != IFDIR && i != IFREG) {
+       if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
                spclrec();
                return;
        }
                spclrec();
                return;
        }
-       icat(ip, tapsrec, dmpspc);
+       if (ip->di_size > NDADDR * sblock->fs_bsize)
+               i = NDADDR * sblock->fs_frag;
+       else
+               i = howmany(ip->di_size, sblock->fs_fsize);
+       blksout(&ip->di_db[0], i);
+       size = ip->di_size - NDADDR * sblock->fs_bsize;
+       if (size <= 0)
+               return;
+       for (i = 0; i < NIADDR; i++) {
+               dmpindir(ip->di_ib[i], i, &size);
+               if (size <= 0)
+                       return;
+       }
 }
 
 }
 
-dmpspc(dp, n)
-daddr_t *dp;
+dmpindir(blk, lvl, size)
+       daddr_t blk;
+       int lvl;
+       long *size;
 {
 {
-       register i, t;
+       int i, cnt;
+       daddr_t idblk[MAXNINDIR];
 
 
-       spcl.c_count = n;
-       for(i=0; i<n; i++) {
-               t = 0;
-               if(dp[i] != 0)
-                       t++;
-               spcl.c_addr[i] = t;
+       if (blk != 0)
+               bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
+       else
+               bzero(idblk, sblock->fs_bsize);
+       if (lvl <= 0) {
+               if (*size < NINDIR(sblock) * sblock->fs_bsize)
+                       cnt = howmany(*size, sblock->fs_fsize);
+               else
+                       cnt = NINDIR(sblock) * sblock->fs_frag;
+               *size -= NINDIR(sblock) * sblock->fs_bsize;
+               blksout(&idblk[0], cnt);
+               return;
+       }
+       lvl--;
+       for (i = 0; i < NINDIR(sblock); i++) {
+               dmpindir(idblk[i], lvl, size);
+               if (*size <= 0)
+                       return;
+       }
+}
+
+blksout(blkp, frags)
+       daddr_t *blkp;
+       int frags;
+{
+       int i, j, count, blks, tbperdb;
+
+       blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
+       tbperdb = sblock->fs_bsize / TP_BSIZE;
+       for (i = 0; i < blks; i += TP_NINDIR) {
+               if (i + TP_NINDIR > blks)
+                       count = blks;
+               else
+                       count = i + TP_NINDIR;
+               for (j = i; j < count; j++)
+                       if (blkp[j / tbperdb] != 0)
+                               spcl.c_addr[j - i] = 1;
+                       else
+                               spcl.c_addr[j - i] = 0;
+               spcl.c_count = count - i;
+               spclrec();
+               for (j = i; j < count; j += tbperdb)
+                       if (blkp[j / tbperdb] != 0)
+                               if (j + tbperdb <= count)
+                                       dmpblk(blkp[j / tbperdb],
+                                           sblock->fs_bsize);
+                               else
+                                       dmpblk(blkp[j / tbperdb],
+                                           (count - j) * TP_BSIZE);
+               spcl.c_type = TS_ADDR;
        }
        }
-       spclrec();
 }
 
 bitmap(map, typ)
 }
 
 bitmap(map, typ)
-short *map;
+       char *map;
 {
        register i, n;
        char *cp;
 
        n = -1;
 {
        register i, n;
        char *cp;
 
        n = -1;
-       for(i=0; i<MSIZ; i++)
+       for (i = 0; i < msiz; i++)
                if(map[i])
                        n = i;
                if(map[i])
                        n = i;
-       if(n < 0)
+       if (n < 0)
                return;
                return;
+       n++;
        spcl.c_type = typ;
        spcl.c_type = typ;
-       spcl.c_count = (n*sizeof(map[0]) + BSIZE)/BSIZE;
+       spcl.c_count = howmany(n * sizeof(map[0]), TP_BSIZE);
        spclrec();
        spclrec();
-       cp = (char *)map;
-       for(i=0; i<spcl.c_count; i++) {
+       for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
                taprec(cp);
                taprec(cp);
-               cp += BSIZE;
-       }
 }
 
 spclrec()
 {
 }
 
 spclrec()
 {
-       register i, *ip, s;
+       register int s, i, *ip;
 
        spcl.c_inumber = ino;
 
        spcl.c_inumber = ino;
-       spcl.c_magic = MAGIC;
+       spcl.c_magic = NFS_MAGIC;
        spcl.c_checksum = 0;
        ip = (int *)&spcl;
        s = 0;
        spcl.c_checksum = 0;
        ip = (int *)&spcl;
        s = 0;
-       for(i=0; i<BSIZE/sizeof(*ip); i++)
+       for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++)
                s += *ip++;
        spcl.c_checksum = CHECKSUM - s;
        taprec((char *)&spcl);
 }
 
                s += *ip++;
        spcl.c_checksum = CHECKSUM - s;
        taprec((char *)&spcl);
 }
 
-dsrch(d)
-daddr_t d;
+dsrch(d, size, filesize)
+       daddr_t d;
+       int size, filesize;
 {
 {
-       register char *cp;
-       register i;
-       register ino_t in;
-       struct direct dblk[DIRPB];
+       register struct direct *dp;
+       long loc;
+       char dblk[MAXBSIZE];
 
        if(dadded)
                return;
 
        if(dadded)
                return;
-       bread(d, (char *)dblk, sizeof(dblk));
-       for(i=0; i<DIRPB; i++) {
-               in = dblk[i].d_ino;
-               if(in == 0)
+       bread(fsbtodb(sblock, d), dblk, size);
+       if (filesize > size)
+               filesize = size;
+       for (loc = 0; loc < filesize; ) {
+               dp = (struct direct *)(dblk + loc);
+               if (dp->d_reclen == 0) {
+                       msg("corrupted directory, inumber %d\n", ino);
+                       break;
+               }
+               loc += dp->d_reclen;
+               if(dp->d_ino == 0)
                        continue;
                        continue;
-               cp = dblk[i].d_name;
-               if(cp[0] == '.') {
-                       if(cp[1] == '\0')
+               if(dp->d_name[0] == '.') {
+                       if(dp->d_name[1] == '\0')
                                continue;
                                continue;
-                       if(cp[1] == '.' && cp[2] == '\0')
+                       if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
                                continue;
                }
                                continue;
                }
-               if(BIT(in, nodmap)) {
+               if(BIT(dp->d_ino, nodmap)) {
                        dadded++;
                        return;
                }
                        dadded++;
                        return;
                }
-               if(BIT(in, dirmap))
+               if(BIT(dp->d_ino, dirmap))
                        nsubdir++;
        }
 }
 
                        nsubdir++;
        }
 }
 
-nullf()
+struct dinode *
+getino(ino)
+       daddr_t ino;
 {
 {
+       static daddr_t minino, maxino;
+       static struct dinode itab[MAXINOPB];
+
+       if (ino >= minino && ino < maxino) {
+               return (&itab[ino - minino]);
+       }
+       bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize);
+       minino = ino - (ino % INOPB(sblock));
+       maxino = minino + INOPB(sblock);
+       return (&itab[ino - minino]);
 }
 
 int    breaderrors = 0;                
 }
 
 int    breaderrors = 0;                
@@ -246,12 +299,12 @@ bread(da, ba, c)
        register n;
        register        regc;
 
        register n;
        register        regc;
 
-       if (lseek(fi, (long)(da*BSIZE), 0) < 0){
+       if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
                msg("bread: lseek fails\n");
        }
        regc = c;       /* put c someplace safe; it gets clobbered */
        n = read(fi, ba, c);
                msg("bread: lseek fails\n");
        }
        regc = c;       /* put c someplace safe; it gets clobbered */
        n = read(fi, ba, c);
-       if(n != c || regc != c){
+       if (n != c || regc != c) {
                msg("(This should not happen)bread from %s [block %d]: c=0x%x, regc=0x%x, &c=0x%x, n=0x%x\n",
                        disk, da, c, regc, &c, n);
 #ifdef ERNIE
                msg("(This should not happen)bread from %s [block %d]: c=0x%x, regc=0x%x, &c=0x%x, n=0x%x\n",
                        disk, da, c, regc, &c, n);
 #ifdef ERNIE
@@ -270,15 +323,3 @@ bread(da, ba, c)
                }
        }
 }
                }
        }
 }
-
-CLR(map)
-register short *map;
-{
-       register n;
-
-       n = MSIZ;
-       do
-               *map++ = 0;
-       while(--n);
-}
-