BSD 4_3_Tahoe release
[unix-history] / usr / src / etc / dump / dumptraverse.c
index 02cd751..e26da77 100644 (file)
@@ -1,27 +1,32 @@
-static char *sccsid = "@(#)dumptraverse.c      1.13 (Berkeley) 2/11/83";
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)dumptraverse.c     5.4 (Berkeley) 2/23/87";
+#endif not lint
 
 #include "dump.h"
 
 pass(fn, map)
 
 #include "dump.h"
 
 pass(fn, map)
-       int (*fn)();
-       char *map;
+       register int (*fn)();
+       register char *map;
 {
 {
-       struct dinode *dp;
-       int bits;
+       register int bits;
        ino_t maxino;
 
        maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
        for (ino = 0; ino < maxino; ) {
        ino_t maxino;
 
        maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
        for (ino = 0; ino < maxino; ) {
-               if((ino % NBBY) == 0) {
+               if ((ino % NBBY) == 0) {
                        bits = ~0;
                        bits = ~0;
-                       if(map != NULL)
+                       if (map != NULL)
                                bits = *map++;
                }
                ino++;
                                bits = *map++;
                }
                ino++;
-               if(bits & 1) {
-                       dp = getino(ino);
-                       (*fn)(dp);
-               }
+               if (bits & 1)
+                       (*fn)(getino(ino));
                bits >>= 1;
        }
 }
                bits >>= 1;
        }
 }
@@ -29,13 +34,14 @@ pass(fn, map)
 mark(ip)
        struct dinode *ip;
 {
 mark(ip)
        struct dinode *ip;
 {
-       register f;
+       register int f;
+       extern int anydskipped;
 
        f = ip->di_mode & IFMT;
 
        f = ip->di_mode & IFMT;
-       if(f == 0)
+       if (f == 0)
                return;
        BIS(ino, clrmap);
                return;
        BIS(ino, clrmap);
-       if(f == IFDIR)
+       if (f == IFDIR)
                BIS(ino, dirmap);
        if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
            !BIT(ino, nodmap)) {
                BIS(ino, dirmap);
        if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
            !BIT(ino, nodmap)) {
@@ -45,25 +51,29 @@ mark(ip)
                        return;
                }
                est(ip);
                        return;
                }
                est(ip);
-       }
+       } else if (f == IFDIR)
+               anydskipped = 1;
 }
 
 add(ip)
        register struct dinode  *ip;
 {
        register int i;
 }
 
 add(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;
+       filesize = ip->di_size;
        for (i = 0; i < NDADDR; i++) {
                if (ip->di_db[i] != 0)
        for (i = 0; i < NDADDR; i++) {
                if (ip->di_db[i] != 0)
-                       dsrch(ip->di_db[i], dblksize(sblock, ip, i));
+                       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)
        }
        for (i = 0; i < NIADDR; i++) {
                if (ip->di_ib[i] != 0)
-                       indir(ip->di_ib[i], i);
+                       indir(ip->di_ib[i], i, &filesize);
        }
        if(dadded) {
                nadded++;
        }
        if(dadded) {
                nadded++;
@@ -77,9 +87,9 @@ add(ip)
                        BIC(ino, dirmap);
 }
 
                        BIC(ino, dirmap);
 }
 
-indir(d, n)
+indir(d, n, filesize)
        daddr_t d;
        daddr_t d;
-       int n;
+       int n, *filesize;
 {
        register i;
        daddr_t idblk[MAXNINDIR];
 {
        register i;
        daddr_t idblk[MAXNINDIR];
@@ -89,18 +99,28 @@ indir(d, n)
                for(i=0; i < NINDIR(sblock); i++) {
                        d = idblk[i];
                        if(d != 0)
                for(i=0; i < NINDIR(sblock); i++) {
                        d = idblk[i];
                        if(d != 0)
-                               dsrch(d, sblock->fs_bsize);
+                               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)
                }
        } else {
                n--;
                for(i=0; i < NINDIR(sblock); i++) {
                        d = idblk[i];
                        if(d != 0)
-                               indir(d, n);
+                               indir(d, n, filesize);
                }
        }
 }
 
                }
        }
 }
 
+dirdump(ip)
+       struct dinode *ip;
+{
+       /* watchout for dir inodes deleted and maybe reallocated */
+       if ((ip->di_mode & IFMT) != IFDIR)
+               return;
+       dump(ip);
+}
+
 dump(ip)
        struct dinode *ip;
 {
 dump(ip)
        struct dinode *ip;
 {
@@ -116,6 +136,8 @@ dump(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 == 0) /* free inode */
+               return;
        if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
                spclrec();
                return;
        if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
                spclrec();
                return;
@@ -199,18 +221,11 @@ blksout(blkp, frags)
 bitmap(map, typ)
        char *map;
 {
 bitmap(map, typ)
        char *map;
 {
-       register i, n;
+       register i;
        char *cp;
 
        char *cp;
 
-       n = -1;
-       for (i = 0; i < msiz; i++)
-               if(map[i])
-                       n = i;
-       if (n < 0)
-               return;
-       n++;
        spcl.c_type = typ;
        spcl.c_type = typ;
-       spcl.c_count = howmany(n * sizeof(map[0]), TP_BSIZE);
+       spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE);
        spclrec();
        for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
                taprec(cp);
        spclrec();
        for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
                taprec(cp);
@@ -225,15 +240,18 @@ spclrec()
        spcl.c_checksum = 0;
        ip = (int *)&spcl;
        s = 0;
        spcl.c_checksum = 0;
        ip = (int *)&spcl;
        s = 0;
-       for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++)
-               s += *ip++;
+       i = sizeof(union u_spcl) / (4*sizeof(int));
+       while (--i >= 0) {
+               s += *ip++; s += *ip++;
+               s += *ip++; s += *ip++;
+       }
        spcl.c_checksum = CHECKSUM - s;
        taprec((char *)&spcl);
 }
 
        spcl.c_checksum = CHECKSUM - s;
        taprec((char *)&spcl);
 }
 
-dsrch(d, size)
+dsrch(d, size, filesize)
        daddr_t d;
        daddr_t d;
-       int size;
+       int size, filesize;
 {
        register struct direct *dp;
        long loc;
 {
        register struct direct *dp;
        long loc;
@@ -241,11 +259,15 @@ dsrch(d, size)
 
        if(dadded)
                return;
 
        if(dadded)
                return;
-       bread(fsbtodb(sblock, d), dblk, size);
-       for (loc = 0; loc < size; ) {
+       if (filesize > size)
+               filesize = size;
+       bread(fsbtodb(sblock, d), dblk, filesize);
+       for (loc = 0; loc < filesize; ) {
                dp = (struct direct *)(dblk + loc);
                dp = (struct direct *)(dblk + loc);
-               if (dp->d_reclen == 0)
+               if (dp->d_reclen == 0) {
+                       msg("corrupted directory, inumber %d\n", ino);
                        break;
                        break;
+               }
                loc += dp->d_reclen;
                if(dp->d_ino == 0)
                        continue;
                loc += dp->d_reclen;
                if(dp->d_ino == 0)
                        continue;
@@ -283,35 +305,45 @@ getino(ino)
 int    breaderrors = 0;                
 #define        BREADEMAX 32
 
 int    breaderrors = 0;                
 #define        BREADEMAX 32
 
-bread(da, ba, c)
+bread(da, ba, cnt)
        daddr_t da;
        char *ba;
        daddr_t da;
        char *ba;
-       int     c;      
+       int     cnt;    
 {
 {
-       register n;
-       register        regc;
+       int n;
 
 
-       if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
+loop:
+       if (lseek(fi, (long)(da * dev_bsize), 0) < 0){
                msg("bread: lseek fails\n");
        }
                msg("bread: lseek fails\n");
        }
-       regc = c;       /* put c someplace safe; it gets clobbered */
-       n = read(fi, ba, 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("Notify Robert Henry of this error.\n");
-#endif
-               if (++breaderrors > BREADEMAX){
-                       msg("More than %d block read errors from %d\n",
-                               BREADEMAX, disk);
-                       broadcast("DUMP IS AILING!\n");
-                       msg("This is an unrecoverable error.\n");
-                       if (!query("Do you want to attempt to continue?")){
-                               dumpabort();
-                               /*NOTREACHED*/
-                       } else
-                               breaderrors = 0;
-               }
+       n = read(fi, ba, cnt);
+       if (n == cnt)
+               return;
+       if (da + (cnt / dev_bsize) > fsbtodb(sblock, sblock->fs_size)) {
+               /*
+                * Trying to read the final fragment.
+                *
+                * NB - dump only works in TP_BSIZE blocks, hence
+                * rounds `dev_bsize' fragments up to TP_BSIZE pieces.
+                * It should be smarter about not actually trying to
+                * read more than it can get, but for the time being
+                * we punt and scale back the read only when it gets
+                * us into trouble. (mkm 9/25/83)
+                */
+               cnt -= dev_bsize;
+               goto loop;
+       }
+       msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n",
+               disk, da, cnt, n);
+       if (++breaderrors > BREADEMAX){
+               msg("More than %d block read errors from %d\n",
+                       BREADEMAX, disk);
+               broadcast("DUMP IS AILING!\n");
+               msg("This is an unrecoverable error.\n");
+               if (!query("Do you want to attempt to continue?")){
+                       dumpabort();
+                       /*NOTREACHED*/
+               } else
+                       breaderrors = 0;
        }
 }
        }
 }