X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/75c260400bc8f350c60574eb92836e0e49e0eae6..05cd4ae7f2de5ffa37cbcf90b515126852adce0e:/usr/src/sbin/dump/traverse.c diff --git a/usr/src/sbin/dump/traverse.c b/usr/src/sbin/dump/traverse.c index fb89bc3a27..8decd11a54 100644 --- a/usr/src/sbin/dump/traverse.c +++ b/usr/src/sbin/dump/traverse.c @@ -1,28 +1,32 @@ -static char *sccsid = "@(#)traverse.c 1.9 (Berkeley) %G%"; +/* + * 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 #include "dump.h" -#include 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; ) { - if((ino % NBBY) == 0) { + if ((ino % NBBY) == 0) { bits = ~0; - if(map != NULL) + if (map != NULL) bits = *map++; } ino++; - if(bits & 1) { - dp = getino(ino); - (*fn)(dp); - } + if (bits & 1) + (*fn)(getino(ino)); bits >>= 1; } } @@ -30,13 +34,14 @@ pass(fn, map) mark(ip) struct dinode *ip; { - register f; + register int f; + extern int anydskipped; f = ip->di_mode & IFMT; - if(f == 0) + if (f == 0) 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)) { @@ -46,25 +51,29 @@ mark(ip) return; } est(ip); - } + } else if (f == IFDIR) + anydskipped = 1; } add(ip) register struct dinode *ip; { register int i; + long filesize; 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) - 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) - indir(ip->di_ib[i], i); + indir(ip->di_ib[i], i, &filesize); } if(dadded) { nadded++; @@ -78,9 +87,9 @@ add(ip) BIC(ino, dirmap); } -indir(d, n) +indir(d, n, filesize) daddr_t d; - int n; + int n, *filesize; { register i; daddr_t idblk[MAXNINDIR]; @@ -90,18 +99,28 @@ indir(d, n) 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) - 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; { @@ -117,6 +136,8 @@ dump(ip) 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; @@ -147,7 +168,7 @@ dmpindir(blk, lvl, size) if (blk != 0) bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize); else - blkclr(idblk, sblock->fs_bsize); + bzero(idblk, sblock->fs_bsize); if (lvl <= 0) { if (*size < NINDIR(sblock) * sblock->fs_bsize) cnt = howmany(*size, sblock->fs_fsize); @@ -171,8 +192,8 @@ blksout(blkp, frags) { int i, j, count, blks, tbperdb; - blks = frags * BLKING(sblock); - tbperdb = BLKING(sblock) * sblock->fs_frag; + 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; @@ -200,18 +221,11 @@ blksout(blkp, frags) bitmap(map, typ) char *map; { - register i, n; + register i; 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_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); @@ -226,15 +240,18 @@ spclrec() 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); } -dsrch(d, size) +dsrch(d, size, filesize) daddr_t d; - int size; + int size, filesize; { register struct direct *dp; long loc; @@ -242,11 +259,15 @@ dsrch(d, size) 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); - if (dp->d_reclen == 0) + if (dp->d_reclen == 0) { + msg("corrupted directory, inumber %d\n", ino); break; + } loc += dp->d_reclen; if(dp->d_ino == 0) continue; @@ -284,42 +305,58 @@ getino(ino) int breaderrors = 0; #define BREADEMAX 32 -bread(da, ba, c) +bread(da, ba, cnt) daddr_t da; char *ba; - int c; + int cnt; { - register n; - register regc; + int n, i; + extern int errno; - if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ +loop: + 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); - 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); } -} - -blkclr(cp, size) - char *cp; - long size; -{ - asm("movc5 $0,(r0),$0,8(ap),*4(ap)"); }