date and time created 88/10/19 11:01:43 by bostic
[unix-history] / usr / src / sbin / dump / traverse.c
index 7798ba9..8decd11 100644 (file)
-static char *sccsid = "@(#)traverse.c  1.3 (Berkeley) %G%";
-#include "dump.h"
+/*
+ * Copyright (c) 1980, 1988 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[] = "@(#)traverse.c 5.5 (Berkeley) %G%";
+#endif not lint
 
 
-struct fs      sblock;
+#include "dump.h"
 
 pass(fn, map)
 
 pass(fn, map)
-       int (*fn)();
-       short *map;
+       register int (*fn)();
+       register char *map;
 {
 {
-       struct dinode *dp;
-       int bits;
+       register int bits;
        ino_t maxino;
 
        ino_t maxino;
 
-       sync();
-       bread(SBLOCK, &sblock, sizeof sblock);
-       if (sblock.fs_magic != FS_MAGIC) {
-               msg("bad sblock magic number\n");
-               dumpabort();
-       }
-       maxino = sblock.fs_ipg * sblock.fs_ncg;
+       maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
        for (ino = 0; ino < maxino; ) {
        for (ino = 0; ino < maxino; ) {
-               if((ino % MLEN) == 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;
        }
 }
 
-icat(dp, fn1)
-       register struct dinode  *dp;
-       int (*fn1)();
-{
-       register int i;
-
-       for (i = 0; i < NDADDR; i++) {
-               if (dp->di_db[i] != 0)
-                       (*fn1)(dp->di_db[i]);
-       }
-       for (i = 0; i < NIADDR; i++) {
-               if (dp->di_ib[i] != 0)
-                       indir(dp->di_ib[i], fn1, i);
-       }
-}
-
-indir(d, fn1, n)
-       daddr_t d;
-       int (*fn1)();
-       int n;
-{
-       register i;
-       daddr_t idblk[NINDIR];
-
-       bread(d, (char *)idblk, sizeof(idblk));
-       if(n <= 0) {
-               for(i=0; i<NINDIR; i++) {
-                       d = idblk[i];
-                       if(d != 0)
-                               (*fn1)(d);
-               }
-       } else {
-               n--;
-               for(i=0; i<NINDIR; i++) {
-                       d = idblk[i];
-                       if(d != 0)
-                               indir(d, fn1, n);
-               }
-       }
-}
-
 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);
                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;
                }
                est(ip);
                        esize += 1;
                        return;
                }
                est(ip);
-       }
+       } else if (f == IFDIR)
+               anydskipped = 1;
 }
 
 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);
+       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);
 }
 
+indir(d, n, filesize)
+       daddr_t d;
+       int n, *filesize;
+{
+       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);
+               }
+       }
+}
+
+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;
 {
@@ -130,16 +136,18 @@ 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 != IFDIR && i != IFREG) || ip->di_size == 0) {
+       if (i == 0) /* free inode */
+               return;
+       if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
                spclrec();
                return;
        }
                spclrec();
                return;
        }
-       if (ip->di_size > NDADDR * BSIZE)
-               i = NDADDR * FRAG;
+       if (ip->di_size > NDADDR * sblock->fs_bsize)
+               i = NDADDR * sblock->fs_frag;
        else
        else
-               i = howmany(ip->di_size, FSIZE);
+               i = howmany(ip->di_size, sblock->fs_fsize);
        blksout(&ip->di_db[0], i);
        blksout(&ip->di_db[0], i);
-       size = ip->di_size - NDADDR * BSIZE;
+       size = ip->di_size - NDADDR * sblock->fs_bsize;
        if (size <= 0)
                return;
        for (i = 0; i < NIADDR; i++) {
        if (size <= 0)
                return;
        for (i = 0; i < NIADDR; i++) {
@@ -155,23 +163,23 @@ dmpindir(blk, lvl, size)
        long *size;
 {
        int i, cnt;
        long *size;
 {
        int i, cnt;
-       daddr_t idblk[NINDIR];
+       daddr_t idblk[MAXNINDIR];
 
        if (blk != 0)
 
        if (blk != 0)
-               bread(blk, (char *)idblk, sizeof(idblk));
+               bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
        else
        else
-               blkclr(idblk, sizeof(idblk));
+               bzero(idblk, sblock->fs_bsize);
        if (lvl <= 0) {
        if (lvl <= 0) {
-               if (*size < NINDIR * BSIZE)
-                       cnt = howmany(*size, TP_BSIZE);
+               if (*size < NINDIR(sblock) * sblock->fs_bsize)
+                       cnt = howmany(*size, sblock->fs_fsize);
                else
                else
-                       cnt = NINDIR * BLKING * FRAG;
-               *size -= NINDIR * BSIZE;
+                       cnt = NINDIR(sblock) * sblock->fs_frag;
+               *size -= NINDIR(sblock) * sblock->fs_bsize;
                blksout(&idblk[0], cnt);
                return;
        }
        lvl--;
                blksout(&idblk[0], cnt);
                return;
        }
        lvl--;
-       for (i = 0; i < NINDIR; i++) {
+       for (i = 0; i < NINDIR(sblock); i++) {
                dmpindir(idblk[i], lvl, size);
                if (*size <= 0)
                        return;
                dmpindir(idblk[i], lvl, size);
                if (*size <= 0)
                        return;
@@ -182,53 +190,45 @@ blksout(blkp, frags)
        daddr_t *blkp;
        int frags;
 {
        daddr_t *blkp;
        int frags;
 {
-       int i, j, count, blks;
+       int i, j, count, blks, tbperdb;
 
 
-       blks = frags * BLKING;
+       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++)
        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 / (BLKING * FRAG)] != 0)
+                       if (blkp[j / tbperdb] != 0)
                                spcl.c_addr[j - i] = 1;
                        else
                                spcl.c_addr[j - i] = 0;
                spcl.c_count = count - i;
                spclrec();
                                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 += (BLKING * FRAG))
-                       if (blkp[j / (BLKING * FRAG)] != 0)
-                               if (j + (BLKING * FRAG) <= count)
-                                       dmpblk(blkp[j / (BLKING * FRAG)],
-                                           BSIZE);
+               for (j = i; j < count; j += tbperdb)
+                       if (blkp[j / tbperdb] != 0)
+                               if (j + tbperdb <= count)
+                                       dmpblk(blkp[j / tbperdb],
+                                           sblock->fs_bsize);
                                else
                                else
-                                       dmpblk(blkp[j / (BLKING * FRAG)],
+                                       dmpblk(blkp[j / tbperdb],
                                            (count - j) * TP_BSIZE);
                spcl.c_type = TS_ADDR;
        }
 }
 
 bitmap(map, typ)
                                            (count - j) * TP_BSIZE);
                spcl.c_type = TS_ADDR;
        }
 }
 
 bitmap(map, typ)
-       short *map;
+       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;
        spcl.c_type = typ;
        spcl.c_type = typ;
-       spcl.c_count = (n*sizeof(map[0]) + TP_BSIZE)/TP_BSIZE;
+       spcl.c_count = howmany(msiz * 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 += TP_BSIZE;
-       }
 }
 
 spclrec()
 }
 
 spclrec()
@@ -236,43 +236,52 @@ spclrec()
        register int s, i, *ip;
 
        spcl.c_inumber = ino;
        register int s, i, *ip;
 
        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 < 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)
+dsrch(d, size, filesize)
        daddr_t d;
        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)
+       if (filesize > size)
+               filesize = size;
+       bread(fsbtodb(sblock, d), dblk, filesize);
+       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++;
        }
 }
@@ -282,67 +291,72 @@ getino(ino)
        daddr_t ino;
 {
        static daddr_t minino, maxino;
        daddr_t ino;
 {
        static daddr_t minino, maxino;
-       static struct dinode itab[INOPB];
+       static struct dinode itab[MAXINOPB];
 
        if (ino >= minino && ino < maxino) {
                return (&itab[ino - minino]);
        }
 
        if (ino >= minino && ino < maxino) {
                return (&itab[ino - minino]);
        }
-       bread(itod(ino, &sblock), itab, BSIZE);
-       minino = ino - (ino % INOPB);
-       maxino = minino + INOPB;
+       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;                
 #define        BREADEMAX 32
 
        return (&itab[ino - minino]);
 }
 
 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, i;
+       extern int errno;
 
 
-       if (lseek(fi, (long)(da*FSIZE), 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("read error from %s [block %d]: count=%d, got=%d, errno=%d\n",
+               disk, da, cnt, n, errno);
+       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;
+       }
+       /*
+        * Zero buffer, then try to read each sector of buffer separately.
+        */
+       bzero(ba, cnt);
+       for (i = 0; i < cnt; i += dev_bsize, ba += dev_bsize, da++) {
+               if (lseek(fi, (long)(da * dev_bsize), 0) < 0)
+                       msg("bread: lseek2 fails!\n");
+               n = read(fi, ba, dev_bsize);
+               if (n != dev_bsize)
+                       msg("    read error from %s [sector %d, errno %d]\n",
+                           disk, da, errno);
        }
        }
-}
-
-CLR(map)
-       register short *map;
-{
-       register n;
-
-       n = MSIZ;
-       do
-               *map++ = 0;
-       while(--n);
-}
-
-blkclr(cp, size)
-       char *cp;
-       long size;
-{
-       asm("movc5      $0,(r0),$0,8(ap),*4(ap)");
 }
 }