xref: /csrg-svn/sbin/dump/traverse.c (revision 25797)
122041Sdist /*
222041Sdist  * Copyright (c) 1980 Regents of the University of California.
322041Sdist  * All rights reserved.  The Berkeley software License Agreement
422041Sdist  * specifies the terms and conditions for redistribution.
522041Sdist  */
65329Smckusic 
722041Sdist #ifndef lint
8*25797Smckusick static char sccsid[] = "@(#)traverse.c	5.3 (Berkeley) 01/09/86";
922041Sdist #endif not lint
1022041Sdist 
111426Sroot #include "dump.h"
121426Sroot 
131426Sroot pass(fn, map)
14*25797Smckusick 	register int (*fn)();
15*25797Smckusick 	register char *map;
161426Sroot {
17*25797Smckusick 	register int bits;
184702Smckusic 	ino_t maxino;
191426Sroot 
205329Smckusic 	maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
214702Smckusic 	for (ino = 0; ino < maxino; ) {
22*25797Smckusick 		if ((ino % NBBY) == 0) {
234702Smckusic 			bits = ~0;
24*25797Smckusick 			if (map != NULL)
254702Smckusic 				bits = *map++;
261426Sroot 		}
274702Smckusic 		ino++;
28*25797Smckusick 		if (bits & 1)
29*25797Smckusick 			(*fn)(getino(ino));
304702Smckusic 		bits >>= 1;
311426Sroot 	}
321426Sroot }
331426Sroot 
341426Sroot mark(ip)
354777Smckusic 	struct dinode *ip;
361426Sroot {
37*25797Smckusick 	register int f;
38*25797Smckusick 	extern int anydskipped;
391426Sroot 
401426Sroot 	f = ip->di_mode & IFMT;
41*25797Smckusick 	if (f == 0)
421426Sroot 		return;
431426Sroot 	BIS(ino, clrmap);
44*25797Smckusick 	if (f == IFDIR)
451426Sroot 		BIS(ino, dirmap);
465329Smckusic 	if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
475329Smckusic 	    !BIT(ino, nodmap)) {
481426Sroot 		BIS(ino, nodmap);
496288Smckusick 		if (f != IFREG && f != IFDIR && f != IFLNK) {
501426Sroot 			esize += 1;
511426Sroot 			return;
521426Sroot 		}
531426Sroot 		est(ip);
54*25797Smckusick 	} else if (f == IFDIR)
55*25797Smckusick 		anydskipped = 1;
561426Sroot }
571426Sroot 
581426Sroot add(ip)
595329Smckusic 	register struct	dinode	*ip;
601426Sroot {
615329Smckusic 	register int i;
6214928Smckusick 	long filesize;
631426Sroot 
641426Sroot 	if(BIT(ino, nodmap))
651426Sroot 		return;
661426Sroot 	nsubdir = 0;
671426Sroot 	dadded = 0;
6814928Smckusick 	filesize = ip->di_size;
695329Smckusic 	for (i = 0; i < NDADDR; i++) {
705329Smckusic 		if (ip->di_db[i] != 0)
7114928Smckusick 			dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize);
7214928Smckusick 		filesize -= sblock->fs_bsize;
735329Smckusic 	}
745329Smckusic 	for (i = 0; i < NIADDR; i++) {
755329Smckusic 		if (ip->di_ib[i] != 0)
7614928Smckusick 			indir(ip->di_ib[i], i, &filesize);
775329Smckusic 	}
781426Sroot 	if(dadded) {
791426Sroot 		nadded++;
805329Smckusic 		if (!BIT(ino, nodmap)) {
815329Smckusic 			BIS(ino, nodmap);
825329Smckusic 			est(ip);
835329Smckusic 		}
841426Sroot 	}
851426Sroot 	if(nsubdir == 0)
861426Sroot 		if(!BIT(ino, nodmap))
871426Sroot 			BIC(ino, dirmap);
881426Sroot }
891426Sroot 
9014928Smckusick indir(d, n, filesize)
915329Smckusic 	daddr_t d;
9214928Smckusick 	int n, *filesize;
935329Smckusic {
945329Smckusic 	register i;
955329Smckusic 	daddr_t	idblk[MAXNINDIR];
965329Smckusic 
975329Smckusic 	bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize);
985329Smckusic 	if(n <= 0) {
995329Smckusic 		for(i=0; i < NINDIR(sblock); i++) {
1005329Smckusic 			d = idblk[i];
1015329Smckusic 			if(d != 0)
10214928Smckusick 				dsrch(d, sblock->fs_bsize, *filesize);
10314928Smckusick 			*filesize -= sblock->fs_bsize;
1045329Smckusic 		}
1055329Smckusic 	} else {
1065329Smckusic 		n--;
1075329Smckusic 		for(i=0; i < NINDIR(sblock); i++) {
1085329Smckusic 			d = idblk[i];
1095329Smckusic 			if(d != 0)
11014928Smckusick 				indir(d, n, filesize);
1115329Smckusic 		}
1125329Smckusic 	}
1135329Smckusic }
1145329Smckusic 
11517234Smckusick dirdump(ip)
11617234Smckusick 	struct dinode *ip;
11717234Smckusick {
11817234Smckusick 	/* watchout for dir inodes deleted and maybe reallocated */
11917234Smckusick 	if ((ip->di_mode & IFMT) != IFDIR)
12017234Smckusick 		return;
12117234Smckusick 	dump(ip);
12217234Smckusick }
12317234Smckusick 
1241426Sroot dump(ip)
1254777Smckusic 	struct dinode *ip;
1261426Sroot {
1274777Smckusic 	register int i;
1284777Smckusic 	long size;
1291426Sroot 
1301426Sroot 	if(newtape) {
1311426Sroot 		newtape = 0;
1321426Sroot 		bitmap(nodmap, TS_BITS);
1331426Sroot 	}
1341426Sroot 	BIC(ino, nodmap);
1351426Sroot 	spcl.c_dinode = *ip;
1361426Sroot 	spcl.c_type = TS_INODE;
1371426Sroot 	spcl.c_count = 0;
1381426Sroot 	i = ip->di_mode & IFMT;
13917234Smckusick 	if (i == 0) /* free inode */
14017234Smckusick 		return;
1416288Smckusick 	if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
1421426Sroot 		spclrec();
1431426Sroot 		return;
1441426Sroot 	}
1455329Smckusic 	if (ip->di_size > NDADDR * sblock->fs_bsize)
1465329Smckusic 		i = NDADDR * sblock->fs_frag;
1474777Smckusic 	else
1485329Smckusic 		i = howmany(ip->di_size, sblock->fs_fsize);
1494777Smckusic 	blksout(&ip->di_db[0], i);
1505329Smckusic 	size = ip->di_size - NDADDR * sblock->fs_bsize;
1514777Smckusic 	if (size <= 0)
1524777Smckusic 		return;
1534777Smckusic 	for (i = 0; i < NIADDR; i++) {
1544777Smckusic 		dmpindir(ip->di_ib[i], i, &size);
1554777Smckusic 		if (size <= 0)
1564777Smckusic 			return;
1574777Smckusic 	}
1581426Sroot }
1591426Sroot 
1604777Smckusic dmpindir(blk, lvl, size)
1614777Smckusic 	daddr_t blk;
1624777Smckusic 	int lvl;
1634777Smckusic 	long *size;
1641426Sroot {
1654777Smckusic 	int i, cnt;
1665329Smckusic 	daddr_t idblk[MAXNINDIR];
1671426Sroot 
1684777Smckusic 	if (blk != 0)
1695329Smckusic 		bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
1704777Smckusic 	else
17110911Ssam 		bzero(idblk, sblock->fs_bsize);
1724777Smckusic 	if (lvl <= 0) {
1735329Smckusic 		if (*size < NINDIR(sblock) * sblock->fs_bsize)
1745329Smckusic 			cnt = howmany(*size, sblock->fs_fsize);
1754777Smckusic 		else
1765329Smckusic 			cnt = NINDIR(sblock) * sblock->fs_frag;
1775329Smckusic 		*size -= NINDIR(sblock) * sblock->fs_bsize;
1784777Smckusic 		blksout(&idblk[0], cnt);
1794777Smckusic 		return;
1801426Sroot 	}
1814777Smckusic 	lvl--;
1825329Smckusic 	for (i = 0; i < NINDIR(sblock); i++) {
1834777Smckusic 		dmpindir(idblk[i], lvl, size);
1844777Smckusic 		if (*size <= 0)
1854777Smckusic 			return;
1864777Smckusic 	}
1871426Sroot }
1881426Sroot 
1894777Smckusic blksout(blkp, frags)
1904777Smckusic 	daddr_t *blkp;
1914777Smckusic 	int frags;
1924777Smckusic {
1935329Smckusic 	int i, j, count, blks, tbperdb;
1944777Smckusic 
1959403Smckusick 	blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
1968537Smckusick 	tbperdb = sblock->fs_bsize / TP_BSIZE;
1974777Smckusic 	for (i = 0; i < blks; i += TP_NINDIR) {
1984777Smckusic 		if (i + TP_NINDIR > blks)
1994777Smckusic 			count = blks;
2004777Smckusic 		else
2014777Smckusic 			count = i + TP_NINDIR;
2024777Smckusic 		for (j = i; j < count; j++)
2035329Smckusic 			if (blkp[j / tbperdb] != 0)
2044777Smckusic 				spcl.c_addr[j - i] = 1;
2054777Smckusic 			else
2064777Smckusic 				spcl.c_addr[j - i] = 0;
2074777Smckusic 		spcl.c_count = count - i;
2084777Smckusic 		spclrec();
2095329Smckusic 		for (j = i; j < count; j += tbperdb)
2105329Smckusic 			if (blkp[j / tbperdb] != 0)
2115329Smckusic 				if (j + tbperdb <= count)
2125329Smckusic 					dmpblk(blkp[j / tbperdb],
2135329Smckusic 					    sblock->fs_bsize);
2144777Smckusic 				else
2155329Smckusic 					dmpblk(blkp[j / tbperdb],
2164777Smckusic 					    (count - j) * TP_BSIZE);
2174777Smckusic 		spcl.c_type = TS_ADDR;
2184777Smckusic 	}
2194777Smckusic }
2204777Smckusic 
2211426Sroot bitmap(map, typ)
2225329Smckusic 	char *map;
2231426Sroot {
22416134Smckusick 	register i;
2251426Sroot 	char *cp;
2261426Sroot 
2271426Sroot 	spcl.c_type = typ;
22816134Smckusick 	spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE);
2291426Sroot 	spclrec();
2305329Smckusic 	for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
2311426Sroot 		taprec(cp);
2321426Sroot }
2331426Sroot 
2341426Sroot spclrec()
2351426Sroot {
2364777Smckusic 	register int s, i, *ip;
2371426Sroot 
2381426Sroot 	spcl.c_inumber = ino;
2398368Smckusick 	spcl.c_magic = NFS_MAGIC;
2401426Sroot 	spcl.c_checksum = 0;
2411426Sroot 	ip = (int *)&spcl;
2421426Sroot 	s = 0;
24324168Smckusick 	i = sizeof(union u_spcl) / (4*sizeof(int));
24424168Smckusick 	while (--i >= 0) {
24524168Smckusick 		s += *ip++; s += *ip++;
24624168Smckusick 		s += *ip++; s += *ip++;
24724168Smckusick 	}
2481426Sroot 	spcl.c_checksum = CHECKSUM - s;
2491426Sroot 	taprec((char *)&spcl);
2501426Sroot }
2511426Sroot 
25214928Smckusick dsrch(d, size, filesize)
2534777Smckusic 	daddr_t d;
25414928Smckusick 	int size, filesize;
2551426Sroot {
2565942Smckusic 	register struct direct *dp;
2575942Smckusic 	long loc;
2585942Smckusic 	char dblk[MAXBSIZE];
2591426Sroot 
2601426Sroot 	if(dadded)
2611426Sroot 		return;
26214928Smckusick 	if (filesize > size)
26314928Smckusick 		filesize = size;
26415095Smckusick 	bread(fsbtodb(sblock, d), dblk, filesize);
26514928Smckusick 	for (loc = 0; loc < filesize; ) {
2665942Smckusic 		dp = (struct direct *)(dblk + loc);
26714928Smckusick 		if (dp->d_reclen == 0) {
26814928Smckusick 			msg("corrupted directory, inumber %d\n", ino);
2695942Smckusic 			break;
27014928Smckusick 		}
2715942Smckusic 		loc += dp->d_reclen;
2725942Smckusic 		if(dp->d_ino == 0)
2731426Sroot 			continue;
2745942Smckusic 		if(dp->d_name[0] == '.') {
2755942Smckusic 			if(dp->d_name[1] == '\0')
2761426Sroot 				continue;
2775942Smckusic 			if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
2781426Sroot 				continue;
2791426Sroot 		}
2805942Smckusic 		if(BIT(dp->d_ino, nodmap)) {
2811426Sroot 			dadded++;
2821426Sroot 			return;
2831426Sroot 		}
2845942Smckusic 		if(BIT(dp->d_ino, dirmap))
2851426Sroot 			nsubdir++;
2861426Sroot 	}
2871426Sroot }
2881426Sroot 
2894702Smckusic struct dinode *
2904702Smckusic getino(ino)
2914702Smckusic 	daddr_t ino;
2924702Smckusic {
2934702Smckusic 	static daddr_t minino, maxino;
2945329Smckusic 	static struct dinode itab[MAXINOPB];
2954702Smckusic 
2964702Smckusic 	if (ino >= minino && ino < maxino) {
2974702Smckusic 		return (&itab[ino - minino]);
2984702Smckusic 	}
2995386Smckusic 	bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize);
3005329Smckusic 	minino = ino - (ino % INOPB(sblock));
3015329Smckusic 	maxino = minino + INOPB(sblock);
3024702Smckusic 	return (&itab[ino - minino]);
3034702Smckusic }
3044702Smckusic 
3051426Sroot int	breaderrors = 0;
3061426Sroot #define	BREADEMAX 32
3071426Sroot 
30815095Smckusick bread(da, ba, cnt)
3091426Sroot 	daddr_t da;
3101426Sroot 	char *ba;
31115095Smckusick 	int	cnt;
3121426Sroot {
31315095Smckusick 	int n;
3141426Sroot 
31515095Smckusick loop:
3165329Smckusic 	if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
3171426Sroot 		msg("bread: lseek fails\n");
3181426Sroot 	}
31915095Smckusick 	n = read(fi, ba, cnt);
32015095Smckusick 	if (n == cnt)
32115095Smckusick 		return;
32215095Smckusick 	if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) {
32315095Smckusick 		/*
32415095Smckusick 		 * Trying to read the final fragment.
32515095Smckusick 		 *
32615095Smckusick 		 * NB - dump only works in TP_BSIZE blocks, hence
32715095Smckusick 		 * rounds DEV_BSIZE fragments up to TP_BSIZE pieces.
32815095Smckusick 		 * It should be smarter about not actually trying to
32915095Smckusick 		 * read more than it can get, but for the time being
33015095Smckusick 		 * we punt and scale back the read only when it gets
33115095Smckusick 		 * us into trouble. (mkm 9/25/83)
33215095Smckusick 		 */
33315095Smckusick 		cnt -= DEV_BSIZE;
33415095Smckusick 		goto loop;
3351426Sroot 	}
33615095Smckusick 	msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n",
33715095Smckusick 		disk, da, cnt, n);
33815095Smckusick 	if (++breaderrors > BREADEMAX){
33915095Smckusick 		msg("More than %d block read errors from %d\n",
34015095Smckusick 			BREADEMAX, disk);
34115095Smckusick 		broadcast("DUMP IS AILING!\n");
34215095Smckusick 		msg("This is an unrecoverable error.\n");
34315095Smckusick 		if (!query("Do you want to attempt to continue?")){
34415095Smckusick 			dumpabort();
34515095Smckusick 			/*NOTREACHED*/
34615095Smckusick 		} else
34715095Smckusick 			breaderrors = 0;
34815095Smckusick 	}
3491426Sroot }
350