xref: /csrg-svn/sbin/dump/traverse.c (revision 16134)
1*16134Smckusick static	char *sccsid = "@(#)traverse.c	1.16 (Berkeley) 03/08/84";
25329Smckusic 
31426Sroot #include "dump.h"
41426Sroot 
51426Sroot pass(fn, map)
64702Smckusic 	int (*fn)();
75329Smckusic 	char *map;
81426Sroot {
94702Smckusic 	struct dinode *dp;
101426Sroot 	int bits;
114702Smckusic 	ino_t maxino;
121426Sroot 
135329Smckusic 	maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
144702Smckusic 	for (ino = 0; ino < maxino; ) {
155329Smckusic 		if((ino % NBBY) == 0) {
164702Smckusic 			bits = ~0;
174702Smckusic 			if(map != NULL)
184702Smckusic 				bits = *map++;
191426Sroot 		}
204702Smckusic 		ino++;
214702Smckusic 		if(bits & 1) {
224702Smckusic 			dp = getino(ino);
234702Smckusic 			(*fn)(dp);
244702Smckusic 		}
254702Smckusic 		bits >>= 1;
261426Sroot 	}
271426Sroot }
281426Sroot 
291426Sroot mark(ip)
304777Smckusic 	struct dinode *ip;
311426Sroot {
321426Sroot 	register f;
331426Sroot 
341426Sroot 	f = ip->di_mode & IFMT;
351426Sroot 	if(f == 0)
361426Sroot 		return;
371426Sroot 	BIS(ino, clrmap);
381426Sroot 	if(f == IFDIR)
391426Sroot 		BIS(ino, dirmap);
405329Smckusic 	if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
415329Smckusic 	    !BIT(ino, nodmap)) {
421426Sroot 		BIS(ino, nodmap);
436288Smckusick 		if (f != IFREG && f != IFDIR && f != IFLNK) {
441426Sroot 			esize += 1;
451426Sroot 			return;
461426Sroot 		}
471426Sroot 		est(ip);
481426Sroot 	}
491426Sroot }
501426Sroot 
511426Sroot add(ip)
525329Smckusic 	register struct	dinode	*ip;
531426Sroot {
545329Smckusic 	register int i;
5514928Smckusick 	long filesize;
561426Sroot 
571426Sroot 	if(BIT(ino, nodmap))
581426Sroot 		return;
591426Sroot 	nsubdir = 0;
601426Sroot 	dadded = 0;
6114928Smckusick 	filesize = ip->di_size;
625329Smckusic 	for (i = 0; i < NDADDR; i++) {
635329Smckusic 		if (ip->di_db[i] != 0)
6414928Smckusick 			dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize);
6514928Smckusick 		filesize -= sblock->fs_bsize;
665329Smckusic 	}
675329Smckusic 	for (i = 0; i < NIADDR; i++) {
685329Smckusic 		if (ip->di_ib[i] != 0)
6914928Smckusick 			indir(ip->di_ib[i], i, &filesize);
705329Smckusic 	}
711426Sroot 	if(dadded) {
721426Sroot 		nadded++;
735329Smckusic 		if (!BIT(ino, nodmap)) {
745329Smckusic 			BIS(ino, nodmap);
755329Smckusic 			est(ip);
765329Smckusic 		}
771426Sroot 	}
781426Sroot 	if(nsubdir == 0)
791426Sroot 		if(!BIT(ino, nodmap))
801426Sroot 			BIC(ino, dirmap);
811426Sroot }
821426Sroot 
8314928Smckusick indir(d, n, filesize)
845329Smckusic 	daddr_t d;
8514928Smckusick 	int n, *filesize;
865329Smckusic {
875329Smckusic 	register i;
885329Smckusic 	daddr_t	idblk[MAXNINDIR];
895329Smckusic 
905329Smckusic 	bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize);
915329Smckusic 	if(n <= 0) {
925329Smckusic 		for(i=0; i < NINDIR(sblock); i++) {
935329Smckusic 			d = idblk[i];
945329Smckusic 			if(d != 0)
9514928Smckusick 				dsrch(d, sblock->fs_bsize, *filesize);
9614928Smckusick 			*filesize -= sblock->fs_bsize;
975329Smckusic 		}
985329Smckusic 	} else {
995329Smckusic 		n--;
1005329Smckusic 		for(i=0; i < NINDIR(sblock); i++) {
1015329Smckusic 			d = idblk[i];
1025329Smckusic 			if(d != 0)
10314928Smckusick 				indir(d, n, filesize);
1045329Smckusic 		}
1055329Smckusic 	}
1065329Smckusic }
1075329Smckusic 
1081426Sroot dump(ip)
1094777Smckusic 	struct dinode *ip;
1101426Sroot {
1114777Smckusic 	register int i;
1124777Smckusic 	long size;
1131426Sroot 
1141426Sroot 	if(newtape) {
1151426Sroot 		newtape = 0;
1161426Sroot 		bitmap(nodmap, TS_BITS);
1171426Sroot 	}
1181426Sroot 	BIC(ino, nodmap);
1191426Sroot 	spcl.c_dinode = *ip;
1201426Sroot 	spcl.c_type = TS_INODE;
1211426Sroot 	spcl.c_count = 0;
1221426Sroot 	i = ip->di_mode & IFMT;
1236288Smckusick 	if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
1241426Sroot 		spclrec();
1251426Sroot 		return;
1261426Sroot 	}
1275329Smckusic 	if (ip->di_size > NDADDR * sblock->fs_bsize)
1285329Smckusic 		i = NDADDR * sblock->fs_frag;
1294777Smckusic 	else
1305329Smckusic 		i = howmany(ip->di_size, sblock->fs_fsize);
1314777Smckusic 	blksout(&ip->di_db[0], i);
1325329Smckusic 	size = ip->di_size - NDADDR * sblock->fs_bsize;
1334777Smckusic 	if (size <= 0)
1344777Smckusic 		return;
1354777Smckusic 	for (i = 0; i < NIADDR; i++) {
1364777Smckusic 		dmpindir(ip->di_ib[i], i, &size);
1374777Smckusic 		if (size <= 0)
1384777Smckusic 			return;
1394777Smckusic 	}
1401426Sroot }
1411426Sroot 
1424777Smckusic dmpindir(blk, lvl, size)
1434777Smckusic 	daddr_t blk;
1444777Smckusic 	int lvl;
1454777Smckusic 	long *size;
1461426Sroot {
1474777Smckusic 	int i, cnt;
1485329Smckusic 	daddr_t idblk[MAXNINDIR];
1491426Sroot 
1504777Smckusic 	if (blk != 0)
1515329Smckusic 		bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
1524777Smckusic 	else
15310911Ssam 		bzero(idblk, sblock->fs_bsize);
1544777Smckusic 	if (lvl <= 0) {
1555329Smckusic 		if (*size < NINDIR(sblock) * sblock->fs_bsize)
1565329Smckusic 			cnt = howmany(*size, sblock->fs_fsize);
1574777Smckusic 		else
1585329Smckusic 			cnt = NINDIR(sblock) * sblock->fs_frag;
1595329Smckusic 		*size -= NINDIR(sblock) * sblock->fs_bsize;
1604777Smckusic 		blksout(&idblk[0], cnt);
1614777Smckusic 		return;
1621426Sroot 	}
1634777Smckusic 	lvl--;
1645329Smckusic 	for (i = 0; i < NINDIR(sblock); i++) {
1654777Smckusic 		dmpindir(idblk[i], lvl, size);
1664777Smckusic 		if (*size <= 0)
1674777Smckusic 			return;
1684777Smckusic 	}
1691426Sroot }
1701426Sroot 
1714777Smckusic blksout(blkp, frags)
1724777Smckusic 	daddr_t *blkp;
1734777Smckusic 	int frags;
1744777Smckusic {
1755329Smckusic 	int i, j, count, blks, tbperdb;
1764777Smckusic 
1779403Smckusick 	blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
1788537Smckusick 	tbperdb = sblock->fs_bsize / TP_BSIZE;
1794777Smckusic 	for (i = 0; i < blks; i += TP_NINDIR) {
1804777Smckusic 		if (i + TP_NINDIR > blks)
1814777Smckusic 			count = blks;
1824777Smckusic 		else
1834777Smckusic 			count = i + TP_NINDIR;
1844777Smckusic 		for (j = i; j < count; j++)
1855329Smckusic 			if (blkp[j / tbperdb] != 0)
1864777Smckusic 				spcl.c_addr[j - i] = 1;
1874777Smckusic 			else
1884777Smckusic 				spcl.c_addr[j - i] = 0;
1894777Smckusic 		spcl.c_count = count - i;
1904777Smckusic 		spclrec();
1915329Smckusic 		for (j = i; j < count; j += tbperdb)
1925329Smckusic 			if (blkp[j / tbperdb] != 0)
1935329Smckusic 				if (j + tbperdb <= count)
1945329Smckusic 					dmpblk(blkp[j / tbperdb],
1955329Smckusic 					    sblock->fs_bsize);
1964777Smckusic 				else
1975329Smckusic 					dmpblk(blkp[j / tbperdb],
1984777Smckusic 					    (count - j) * TP_BSIZE);
1994777Smckusic 		spcl.c_type = TS_ADDR;
2004777Smckusic 	}
2014777Smckusic }
2024777Smckusic 
2031426Sroot bitmap(map, typ)
2045329Smckusic 	char *map;
2051426Sroot {
206*16134Smckusick 	register i;
2071426Sroot 	char *cp;
2081426Sroot 
2091426Sroot 	spcl.c_type = typ;
210*16134Smckusick 	spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE);
2111426Sroot 	spclrec();
2125329Smckusic 	for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
2131426Sroot 		taprec(cp);
2141426Sroot }
2151426Sroot 
2161426Sroot spclrec()
2171426Sroot {
2184777Smckusic 	register int s, i, *ip;
2191426Sroot 
2201426Sroot 	spcl.c_inumber = ino;
2218368Smckusick 	spcl.c_magic = NFS_MAGIC;
2221426Sroot 	spcl.c_checksum = 0;
2231426Sroot 	ip = (int *)&spcl;
2241426Sroot 	s = 0;
2254777Smckusic 	for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++)
2261426Sroot 		s += *ip++;
2271426Sroot 	spcl.c_checksum = CHECKSUM - s;
2281426Sroot 	taprec((char *)&spcl);
2291426Sroot }
2301426Sroot 
23114928Smckusick dsrch(d, size, filesize)
2324777Smckusic 	daddr_t d;
23314928Smckusick 	int size, filesize;
2341426Sroot {
2355942Smckusic 	register struct direct *dp;
2365942Smckusic 	long loc;
2375942Smckusic 	char dblk[MAXBSIZE];
2381426Sroot 
2391426Sroot 	if(dadded)
2401426Sroot 		return;
24114928Smckusick 	if (filesize > size)
24214928Smckusick 		filesize = size;
24315095Smckusick 	bread(fsbtodb(sblock, d), dblk, filesize);
24414928Smckusick 	for (loc = 0; loc < filesize; ) {
2455942Smckusic 		dp = (struct direct *)(dblk + loc);
24614928Smckusick 		if (dp->d_reclen == 0) {
24714928Smckusick 			msg("corrupted directory, inumber %d\n", ino);
2485942Smckusic 			break;
24914928Smckusick 		}
2505942Smckusic 		loc += dp->d_reclen;
2515942Smckusic 		if(dp->d_ino == 0)
2521426Sroot 			continue;
2535942Smckusic 		if(dp->d_name[0] == '.') {
2545942Smckusic 			if(dp->d_name[1] == '\0')
2551426Sroot 				continue;
2565942Smckusic 			if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
2571426Sroot 				continue;
2581426Sroot 		}
2595942Smckusic 		if(BIT(dp->d_ino, nodmap)) {
2601426Sroot 			dadded++;
2611426Sroot 			return;
2621426Sroot 		}
2635942Smckusic 		if(BIT(dp->d_ino, dirmap))
2641426Sroot 			nsubdir++;
2651426Sroot 	}
2661426Sroot }
2671426Sroot 
2684702Smckusic struct dinode *
2694702Smckusic getino(ino)
2704702Smckusic 	daddr_t ino;
2714702Smckusic {
2724702Smckusic 	static daddr_t minino, maxino;
2735329Smckusic 	static struct dinode itab[MAXINOPB];
2744702Smckusic 
2754702Smckusic 	if (ino >= minino && ino < maxino) {
2764702Smckusic 		return (&itab[ino - minino]);
2774702Smckusic 	}
2785386Smckusic 	bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize);
2795329Smckusic 	minino = ino - (ino % INOPB(sblock));
2805329Smckusic 	maxino = minino + INOPB(sblock);
2814702Smckusic 	return (&itab[ino - minino]);
2824702Smckusic }
2834702Smckusic 
2841426Sroot int	breaderrors = 0;
2851426Sroot #define	BREADEMAX 32
2861426Sroot 
28715095Smckusick bread(da, ba, cnt)
2881426Sroot 	daddr_t da;
2891426Sroot 	char *ba;
29015095Smckusick 	int	cnt;
2911426Sroot {
29215095Smckusick 	int n;
2931426Sroot 
29415095Smckusick loop:
2955329Smckusic 	if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
2961426Sroot 		msg("bread: lseek fails\n");
2971426Sroot 	}
29815095Smckusick 	n = read(fi, ba, cnt);
29915095Smckusick 	if (n == cnt)
30015095Smckusick 		return;
30115095Smckusick 	if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) {
30215095Smckusick 		/*
30315095Smckusick 		 * Trying to read the final fragment.
30415095Smckusick 		 *
30515095Smckusick 		 * NB - dump only works in TP_BSIZE blocks, hence
30615095Smckusick 		 * rounds DEV_BSIZE fragments up to TP_BSIZE pieces.
30715095Smckusick 		 * It should be smarter about not actually trying to
30815095Smckusick 		 * read more than it can get, but for the time being
30915095Smckusick 		 * we punt and scale back the read only when it gets
31015095Smckusick 		 * us into trouble. (mkm 9/25/83)
31115095Smckusick 		 */
31215095Smckusick 		cnt -= DEV_BSIZE;
31315095Smckusick 		goto loop;
3141426Sroot 	}
31515095Smckusick 	msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n",
31615095Smckusick 		disk, da, cnt, n);
31715095Smckusick 	if (++breaderrors > BREADEMAX){
31815095Smckusick 		msg("More than %d block read errors from %d\n",
31915095Smckusick 			BREADEMAX, disk);
32015095Smckusick 		broadcast("DUMP IS AILING!\n");
32115095Smckusick 		msg("This is an unrecoverable error.\n");
32215095Smckusick 		if (!query("Do you want to attempt to continue?")){
32315095Smckusick 			dumpabort();
32415095Smckusick 			/*NOTREACHED*/
32515095Smckusick 		} else
32615095Smckusick 			breaderrors = 0;
32715095Smckusick 	}
3281426Sroot }
329