xref: /csrg-svn/local/ukc/dump/dumptraverse.c (revision 32028)
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