132011Spc /*
232011Spc * Copyright (c) 1980 Regents of the University of California.
332011Spc * All rights reserved. The Berkeley software License Agreement
432011Spc * specifies the terms and conditions for redistribution.
532011Spc */
632011Spc
732011Spc #ifndef lint
8*32028Spc static char sccsid[] = "@(#)dumptraverse.c 1.2 (UKC) 08/08/87 5.3 (Berkeley) 1/9/86";
932011Spc #endif not lint
1032011Spc
1132011Spc #include "dump.h"
1232011Spc
1332011Spc pass(fn, map)
1432011Spc register int (*fn)();
1532011Spc register char *map;
1632011Spc {
1732011Spc register int bits;
1832011Spc ino_t maxino;
1932011Spc
2032011Spc maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
2132011Spc for (ino = 0; ino < maxino; ) {
2232011Spc if ((ino % NBBY) == 0) {
2332011Spc bits = ~0;
2432011Spc if (map != NULL)
2532011Spc bits = *map++;
2632011Spc }
2732011Spc ino++;
2832011Spc if (bits & 1)
2932011Spc (*fn)(getino(ino));
3032011Spc bits >>= 1;
3132011Spc }
3232011Spc }
3332011Spc
3432011Spc mark(ip)
3532011Spc struct dinode *ip;
3632011Spc {
3732011Spc register int f;
3832011Spc extern int anydskipped;
3932011Spc
4032011Spc f = ip->di_mode & IFMT;
4132011Spc if (f == 0)
4232011Spc return;
4332011Spc BIS(ino, clrmap);
4432011Spc if (f == IFDIR)
4532011Spc BIS(ino, dirmap);
4632011Spc if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
4732011Spc !BIT(ino, nodmap)) {
4832011Spc BIS(ino, nodmap);
4932011Spc if (f != IFREG && f != IFDIR && f != IFLNK) {
5032011Spc esize += 1;
5132011Spc return;
5232011Spc }
5332011Spc est(ip);
5432011Spc } else if (f == IFDIR)
5532011Spc anydskipped = 1;
5632011Spc }
5732011Spc
add(ip)5832011Spc add(ip)
5932011Spc register struct dinode *ip;
6032011Spc {
6132011Spc register int i;
6232011Spc long filesize;
6332011Spc
6432011Spc if(BIT(ino, nodmap))
6532011Spc return;
6632011Spc nsubdir = 0;
6732011Spc dadded = 0;
6832011Spc filesize = ip->di_size;
6932011Spc for (i = 0; i < NDADDR; i++) {
7032011Spc if (ip->di_db[i] != 0)
7132011Spc dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize);
7232011Spc filesize -= sblock->fs_bsize;
7332011Spc }
7432011Spc for (i = 0; i < NIADDR; i++) {
7532011Spc if (ip->di_ib[i] != 0)
7632011Spc indir(ip->di_ib[i], i, &filesize);
7732011Spc }
7832011Spc if(dadded) {
7932011Spc nadded++;
8032011Spc if (!BIT(ino, nodmap)) {
8132011Spc BIS(ino, nodmap);
8232011Spc est(ip);
8332011Spc }
8432011Spc }
8532011Spc if(nsubdir == 0)
8632011Spc if(!BIT(ino, nodmap))
8732011Spc BIC(ino, dirmap);
8832011Spc }
8932011Spc
indir(d,n,filesize)9032011Spc indir(d, n, filesize)
9132011Spc daddr_t d;
9232011Spc int n, *filesize;
9332011Spc {
9432011Spc register i;
9532011Spc daddr_t idblk[MAXNINDIR];
9632011Spc
9732011Spc bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize);
9832011Spc if(n <= 0) {
9932011Spc for(i=0; i < NINDIR(sblock); i++) {
10032011Spc d = idblk[i];
10132011Spc if(d != 0)
10232011Spc dsrch(d, sblock->fs_bsize, *filesize);
10332011Spc *filesize -= sblock->fs_bsize;
10432011Spc }
10532011Spc } else {
10632011Spc n--;
10732011Spc for(i=0; i < NINDIR(sblock); i++) {
10832011Spc d = idblk[i];
10932011Spc if(d != 0)
11032011Spc indir(d, n, filesize);
11132011Spc }
11232011Spc }
11332011Spc }
11432011Spc
11532011Spc dirdump(ip)
11632011Spc struct dinode *ip;
11732011Spc {
11832011Spc /* watchout for dir inodes deleted and maybe reallocated */
11932011Spc if ((ip->di_mode & IFMT) != IFDIR)
12032011Spc return;
12132011Spc dump(ip);
12232011Spc }
12332011Spc
12432011Spc dump(ip)
12532011Spc struct dinode *ip;
12632011Spc {
12732011Spc register int i;
12832011Spc long size;
12932011Spc
13032011Spc if(newtape) {
13132011Spc newtape = 0;
13232011Spc bitmap(nodmap, TS_BITS);
13332011Spc }
13432011Spc BIC(ino, nodmap);
13532011Spc spcl.c_dinode = *ip;
13632011Spc spcl.c_type = TS_INODE;
13732011Spc spcl.c_count = 0;
13832011Spc i = ip->di_mode & IFMT;
13932011Spc if (i == 0) /* free inode */
14032011Spc return;
14132011Spc if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
14232011Spc spclrec();
14332011Spc return;
14432011Spc }
14532011Spc if (ip->di_size > NDADDR * sblock->fs_bsize)
14632011Spc i = NDADDR * sblock->fs_frag;
14732011Spc else
14832011Spc i = howmany(ip->di_size, sblock->fs_fsize);
14932011Spc blksout(&ip->di_db[0], i);
15032011Spc size = ip->di_size - NDADDR * sblock->fs_bsize;
15132011Spc if (size <= 0)
15232011Spc return;
15332011Spc for (i = 0; i < NIADDR; i++) {
15432011Spc dmpindir(ip->di_ib[i], i, &size);
15532011Spc if (size <= 0)
15632011Spc return;
15732011Spc }
15832011Spc }
15932011Spc
dmpindir(blk,lvl,size)16032011Spc dmpindir(blk, lvl, size)
16132011Spc daddr_t blk;
16232011Spc int lvl;
16332011Spc long *size;
16432011Spc {
16532011Spc int i, cnt;
16632011Spc daddr_t idblk[MAXNINDIR];
16732011Spc
16832011Spc if (blk != 0)
16932011Spc bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
17032011Spc else
17132011Spc bzero(idblk, sblock->fs_bsize);
17232011Spc if (lvl <= 0) {
17332011Spc if (*size < NINDIR(sblock) * sblock->fs_bsize)
17432011Spc cnt = howmany(*size, sblock->fs_fsize);
17532011Spc else
17632011Spc cnt = NINDIR(sblock) * sblock->fs_frag;
17732011Spc *size -= NINDIR(sblock) * sblock->fs_bsize;
17832011Spc blksout(&idblk[0], cnt);
17932011Spc return;
18032011Spc }
18132011Spc lvl--;
18232011Spc for (i = 0; i < NINDIR(sblock); i++) {
18332011Spc dmpindir(idblk[i], lvl, size);
18432011Spc if (*size <= 0)
18532011Spc return;
18632011Spc }
18732011Spc }
18832011Spc
blksout(blkp,frags)18932011Spc blksout(blkp, frags)
19032011Spc daddr_t *blkp;
19132011Spc int frags;
19232011Spc {
19332011Spc int i, j, count, blks, tbperdb;
19432011Spc
19532011Spc blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
19632011Spc tbperdb = sblock->fs_bsize / TP_BSIZE;
19732011Spc for (i = 0; i < blks; i += TP_NINDIR) {
19832011Spc if (i + TP_NINDIR > blks)
19932011Spc count = blks;
20032011Spc else
20132011Spc count = i + TP_NINDIR;
20232011Spc for (j = i; j < count; j++)
20332011Spc if (blkp[j / tbperdb] != 0)
20432011Spc spcl.c_addr[j - i] = 1;
20532011Spc else
20632011Spc spcl.c_addr[j - i] = 0;
20732011Spc spcl.c_count = count - i;
20832011Spc spclrec();
20932011Spc for (j = i; j < count; j += tbperdb)
21032011Spc if (blkp[j / tbperdb] != 0)
21132011Spc if (j + tbperdb <= count)
21232011Spc dmpblk(blkp[j / tbperdb],
21332011Spc sblock->fs_bsize);
21432011Spc else
21532011Spc dmpblk(blkp[j / tbperdb],
21632011Spc (count - j) * TP_BSIZE);
21732011Spc spcl.c_type = TS_ADDR;
21832011Spc }
21932011Spc }
22032011Spc
bitmap(map,typ)22132011Spc bitmap(map, typ)
22232011Spc char *map;
22332011Spc {
22432011Spc register i;
22532011Spc char *cp;
22632011Spc
22732011Spc spcl.c_type = typ;
22832011Spc spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE);
22932011Spc spclrec();
23032011Spc for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
23132011Spc taprec(cp);
23232011Spc }
23332011Spc
spclrec()23432011Spc spclrec()
23532011Spc {
23632011Spc register int s, i, *ip;
23732011Spc
23832011Spc spcl.c_inumber = ino;
23932011Spc spcl.c_magic = NFS_MAGIC;
240*32028Spc if(newtape) /* add label */
241*32028Spc strcpy(spcl.c_label, createlabel(tapeno));
24232011Spc spcl.c_checksum = 0;
24332011Spc ip = (int *)&spcl;
24432011Spc s = 0;
24532011Spc i = sizeof(union u_spcl) / (4*sizeof(int));
24632011Spc while (--i >= 0) {
24732011Spc s += *ip++; s += *ip++;
24832011Spc s += *ip++; s += *ip++;
24932011Spc }
25032011Spc spcl.c_checksum = CHECKSUM - s;
25132011Spc taprec((char *)&spcl);
25232011Spc }
25332011Spc
dsrch(d,size,filesize)25432011Spc dsrch(d, size, filesize)
25532011Spc daddr_t d;
25632011Spc int size, filesize;
25732011Spc {
25832011Spc register struct direct *dp;
25932011Spc long loc;
26032011Spc char dblk[MAXBSIZE];
26132011Spc
26232011Spc if(dadded)
26332011Spc return;
26432011Spc if (filesize > size)
26532011Spc filesize = size;
26632011Spc bread(fsbtodb(sblock, d), dblk, filesize);
26732011Spc for (loc = 0; loc < filesize; ) {
26832011Spc dp = (struct direct *)(dblk + loc);
26932011Spc if (dp->d_reclen == 0) {
27032011Spc msg("corrupted directory, inumber %d\n", ino);
27132011Spc break;
27232011Spc }
27332011Spc loc += dp->d_reclen;
27432011Spc if(dp->d_ino == 0)
27532011Spc continue;
27632011Spc if(dp->d_name[0] == '.') {
27732011Spc if(dp->d_name[1] == '\0')
27832011Spc continue;
27932011Spc if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
28032011Spc continue;
28132011Spc }
28232011Spc if(BIT(dp->d_ino, nodmap)) {
28332011Spc dadded++;
28432011Spc return;
28532011Spc }
28632011Spc if(BIT(dp->d_ino, dirmap))
28732011Spc nsubdir++;
28832011Spc }
28932011Spc }
29032011Spc
29132011Spc struct dinode *
getino(ino)29232011Spc getino(ino)
29332011Spc daddr_t ino;
29432011Spc {
29532011Spc static daddr_t minino, maxino;
29632011Spc static struct dinode itab[MAXINOPB];
29732011Spc
29832011Spc if (ino >= minino && ino < maxino) {
29932011Spc return (&itab[ino - minino]);
30032011Spc }
30132011Spc bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize);
30232011Spc minino = ino - (ino % INOPB(sblock));
30332011Spc maxino = minino + INOPB(sblock);
30432011Spc return (&itab[ino - minino]);
30532011Spc }
30632011Spc
30732011Spc int breaderrors = 0;
30832011Spc #define BREADEMAX 32
30932011Spc
bread(da,ba,cnt)31032011Spc bread(da, ba, cnt)
31132011Spc daddr_t da;
31232011Spc char *ba;
31332011Spc int cnt;
31432011Spc {
31532011Spc int n;
31632011Spc
31732011Spc loop:
31832011Spc if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
31932011Spc msg("bread: lseek fails\n");
32032011Spc }
32132011Spc n = read(fi, ba, cnt);
32232011Spc if (n == cnt)
32332011Spc return;
32432011Spc if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) {
32532011Spc /*
32632011Spc * Trying to read the final fragment.
32732011Spc *
32832011Spc * NB - dump only works in TP_BSIZE blocks, hence
32932011Spc * rounds DEV_BSIZE fragments up to TP_BSIZE pieces.
33032011Spc * It should be smarter about not actually trying to
33132011Spc * read more than it can get, but for the time being
33232011Spc * we punt and scale back the read only when it gets
33332011Spc * us into trouble. (mkm 9/25/83)
33432011Spc */
33532011Spc cnt -= DEV_BSIZE;
33632011Spc goto loop;
33732011Spc }
33832011Spc msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n",
33932011Spc disk, da, cnt, n);
34032011Spc if (++breaderrors > BREADEMAX){
34132011Spc msg("More than %d block read errors from %d\n",
34232011Spc BREADEMAX, disk);
34332011Spc broadcast("DUMP IS AILING!\n");
34432011Spc msg("This is an unrecoverable error.\n");
34532011Spc if (!query("Do you want to attempt to continue?")){
34632011Spc dumpabort();
34732011Spc /*NOTREACHED*/
34832011Spc } else
34932011Spc breaderrors = 0;
35032011Spc }
35132011Spc }
352