335 lines
6.6 KiB
C
335 lines
6.6 KiB
C
/*
|
|
* 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 1.1 94/10/31 SMI"; /* from UCB 5.3 1/9/86 */
|
|
#endif not lint
|
|
|
|
#include "dump.h"
|
|
#include <sys/file.h>
|
|
|
|
pass(fn, map)
|
|
register int (*fn)();
|
|
register char *map;
|
|
{
|
|
register int bits;
|
|
ino_t maxino;
|
|
|
|
maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
|
|
for (ino = 0; ino < maxino; ) {
|
|
if ((ino % NBBY) == 0) {
|
|
bits = ~0;
|
|
if (map != NULL)
|
|
bits = *map++;
|
|
}
|
|
ino++;
|
|
if (bits & 1)
|
|
(*fn)(getino(ino));
|
|
bits >>= 1;
|
|
}
|
|
}
|
|
|
|
mark(ip)
|
|
struct dinode *ip;
|
|
{
|
|
register int f;
|
|
extern int anydskipped;
|
|
|
|
f = ip->di_mode & IFMT;
|
|
if (f == 0)
|
|
return;
|
|
BIS(ino, clrmap);
|
|
if (f == IFDIR)
|
|
BIS(ino, dirmap);
|
|
if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
|
|
!BIT(ino, nodmap)) {
|
|
BIS(ino, nodmap);
|
|
if (f != IFREG && f != IFDIR && f != IFLNK) {
|
|
esize += 1;
|
|
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 = roundup(ip->di_size, DEV_BSIZE);
|
|
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) {
|
|
nadded++;
|
|
if (!BIT(ino, nodmap)) {
|
|
BIS(ino, nodmap);
|
|
est(ip);
|
|
}
|
|
}
|
|
if(nsubdir == 0)
|
|
if(!BIT(ino, nodmap))
|
|
BIC(ino, dirmap);
|
|
}
|
|
|
|
indir(d, n, filesize)
|
|
daddr_t d;
|
|
int n;
|
|
long *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;
|
|
{
|
|
register int i;
|
|
long size;
|
|
|
|
if(newtape) {
|
|
newtape = 0;
|
|
bitmap(nodmap, TS_BITS);
|
|
}
|
|
BIC(ino, nodmap);
|
|
spcl.c_dinode = *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;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
dmpindir(blk, lvl, size)
|
|
daddr_t blk;
|
|
int lvl;
|
|
long *size;
|
|
{
|
|
int i, cnt;
|
|
daddr_t idblk[MAXNINDIR];
|
|
|
|
if (blk != 0)
|
|
bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
|
|
else
|
|
bzero((char *)idblk, (int)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],
|
|
(long)((count - j) * TP_BSIZE));
|
|
spcl.c_type = TS_ADDR;
|
|
}
|
|
}
|
|
|
|
bitmap(map, typ)
|
|
char *map;
|
|
{
|
|
register int i;
|
|
char *cp;
|
|
|
|
spcl.c_type = typ;
|
|
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);
|
|
}
|
|
|
|
dsrch(d, size, filesize)
|
|
daddr_t d;
|
|
long size, filesize;
|
|
{
|
|
register struct direct *dp;
|
|
long loc;
|
|
char dblk[MAXBSIZE];
|
|
|
|
if(dadded)
|
|
return;
|
|
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;
|
|
if(dp->d_name[0] == '.') {
|
|
if(dp->d_name[1] == '\0')
|
|
continue;
|
|
if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
|
|
continue;
|
|
}
|
|
if(BIT(dp->d_ino, nodmap)) {
|
|
dadded++;
|
|
return;
|
|
}
|
|
if(BIT(dp->d_ino, dirmap))
|
|
nsubdir++;
|
|
}
|
|
}
|
|
|
|
struct dinode *
|
|
getino(ino)
|
|
ino_t ino;
|
|
{
|
|
static ino_t minino, maxino;
|
|
static struct dinode itab[MAXINOPB];
|
|
|
|
if (ino >= minino && ino < maxino) {
|
|
return (&itab[ino - minino]);
|
|
}
|
|
bread(fsbtodb(sblock, itod(sblock, ino)),
|
|
(char *)itab, sblock->fs_bsize);
|
|
minino = ino - (ino % INOPB(sblock));
|
|
maxino = minino + INOPB(sblock);
|
|
return (&itab[ino - minino]);
|
|
}
|
|
|
|
int breaderrors = 0;
|
|
#define BREADEMAX 32
|
|
|
|
bread(da, ba, cnt)
|
|
daddr_t da;
|
|
char *ba;
|
|
long cnt;
|
|
{
|
|
int n;
|
|
|
|
loop:
|
|
if (lseek(fi, (long)(da * DEV_BSIZE), L_SET) < 0){
|
|
msg("bread: lseek fails\n");
|
|
}
|
|
n = read(fi, ba, (int)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;
|
|
}
|
|
}
|