xref: /original-bsd/sbin/dump/traverse.c (revision fbed46ce)
1 static	char *sccsid = "@(#)traverse.c	1.7 (Berkeley) 03/23/82";
2 
3 #include "dump.h"
4 #include <ndir.h>
5 
6 pass(fn, map)
7 	int (*fn)();
8 	char *map;
9 {
10 	struct dinode *dp;
11 	int bits;
12 	ino_t maxino;
13 
14 	maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
15 	for (ino = 0; ino < maxino; ) {
16 		if((ino % NBBY) == 0) {
17 			bits = ~0;
18 			if(map != NULL)
19 				bits = *map++;
20 		}
21 		ino++;
22 		if(bits & 1) {
23 			dp = getino(ino);
24 			(*fn)(dp);
25 		}
26 		bits >>= 1;
27 	}
28 }
29 
30 mark(ip)
31 	struct dinode *ip;
32 {
33 	register f;
34 
35 	f = ip->di_mode & IFMT;
36 	if(f == 0)
37 		return;
38 	BIS(ino, clrmap);
39 	if(f == IFDIR)
40 		BIS(ino, dirmap);
41 	if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
42 	    !BIT(ino, nodmap)) {
43 		BIS(ino, nodmap);
44 		if (f != IFREG && f != IFDIR && f != IFLNK) {
45 			esize += 1;
46 			return;
47 		}
48 		est(ip);
49 	}
50 }
51 
52 add(ip)
53 	register struct	dinode	*ip;
54 {
55 	register int i;
56 
57 	if(BIT(ino, nodmap))
58 		return;
59 	nsubdir = 0;
60 	dadded = 0;
61 	for (i = 0; i < NDADDR; i++) {
62 		if (ip->di_db[i] != 0)
63 			dsrch(ip->di_db[i], dblksize(sblock, ip, i));
64 	}
65 	for (i = 0; i < NIADDR; i++) {
66 		if (ip->di_ib[i] != 0)
67 			indir(ip->di_ib[i], i);
68 	}
69 	if(dadded) {
70 		nadded++;
71 		if (!BIT(ino, nodmap)) {
72 			BIS(ino, nodmap);
73 			est(ip);
74 		}
75 	}
76 	if(nsubdir == 0)
77 		if(!BIT(ino, nodmap))
78 			BIC(ino, dirmap);
79 }
80 
81 indir(d, n)
82 	daddr_t d;
83 	int n;
84 {
85 	register i;
86 	daddr_t	idblk[MAXNINDIR];
87 
88 	bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize);
89 	if(n <= 0) {
90 		for(i=0; i < NINDIR(sblock); i++) {
91 			d = idblk[i];
92 			if(d != 0)
93 				dsrch(d, sblock->fs_bsize);
94 		}
95 	} else {
96 		n--;
97 		for(i=0; i < NINDIR(sblock); i++) {
98 			d = idblk[i];
99 			if(d != 0)
100 				indir(d, n);
101 		}
102 	}
103 }
104 
105 dump(ip)
106 	struct dinode *ip;
107 {
108 	register int i;
109 	long size;
110 
111 	if(newtape) {
112 		newtape = 0;
113 		bitmap(nodmap, TS_BITS);
114 	}
115 	BIC(ino, nodmap);
116 	spcl.c_dinode = *ip;
117 	spcl.c_type = TS_INODE;
118 	spcl.c_count = 0;
119 	i = ip->di_mode & IFMT;
120 	if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
121 		spclrec();
122 		return;
123 	}
124 	if (ip->di_size > NDADDR * sblock->fs_bsize)
125 		i = NDADDR * sblock->fs_frag;
126 	else
127 		i = howmany(ip->di_size, sblock->fs_fsize);
128 	blksout(&ip->di_db[0], i);
129 	size = ip->di_size - NDADDR * sblock->fs_bsize;
130 	if (size <= 0)
131 		return;
132 	for (i = 0; i < NIADDR; i++) {
133 		dmpindir(ip->di_ib[i], i, &size);
134 		if (size <= 0)
135 			return;
136 	}
137 }
138 
139 dmpindir(blk, lvl, size)
140 	daddr_t blk;
141 	int lvl;
142 	long *size;
143 {
144 	int i, cnt;
145 	daddr_t idblk[MAXNINDIR];
146 
147 	if (blk != 0)
148 		bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
149 	else
150 		blkclr(idblk, sblock->fs_bsize);
151 	if (lvl <= 0) {
152 		if (*size < NINDIR(sblock) * sblock->fs_bsize)
153 			cnt = howmany(*size, sblock->fs_fsize);
154 		else
155 			cnt = NINDIR(sblock) * sblock->fs_frag;
156 		*size -= NINDIR(sblock) * sblock->fs_bsize;
157 		blksout(&idblk[0], cnt);
158 		return;
159 	}
160 	lvl--;
161 	for (i = 0; i < NINDIR(sblock); i++) {
162 		dmpindir(idblk[i], lvl, size);
163 		if (*size <= 0)
164 			return;
165 	}
166 }
167 
168 blksout(blkp, frags)
169 	daddr_t *blkp;
170 	int frags;
171 {
172 	int i, j, count, blks, tbperdb;
173 
174 	blks = frags * BLKING(sblock);
175 	tbperdb = BLKING(sblock) * sblock->fs_frag;
176 	for (i = 0; i < blks; i += TP_NINDIR) {
177 		if (i + TP_NINDIR > blks)
178 			count = blks;
179 		else
180 			count = i + TP_NINDIR;
181 		for (j = i; j < count; j++)
182 			if (blkp[j / tbperdb] != 0)
183 				spcl.c_addr[j - i] = 1;
184 			else
185 				spcl.c_addr[j - i] = 0;
186 		spcl.c_count = count - i;
187 		spclrec();
188 		for (j = i; j < count; j += tbperdb)
189 			if (blkp[j / tbperdb] != 0)
190 				if (j + tbperdb <= count)
191 					dmpblk(blkp[j / tbperdb],
192 					    sblock->fs_bsize);
193 				else
194 					dmpblk(blkp[j / tbperdb],
195 					    (count - j) * TP_BSIZE);
196 		spcl.c_type = TS_ADDR;
197 	}
198 }
199 
200 bitmap(map, typ)
201 	char *map;
202 {
203 	register i, n;
204 	char *cp;
205 
206 	n = -1;
207 	for (i = 0; i < msiz; i++)
208 		if(map[i])
209 			n = i;
210 	if (n < 0)
211 		return;
212 	n++;
213 	spcl.c_type = typ;
214 	spcl.c_count = howmany(n * sizeof(map[0]), TP_BSIZE);
215 	spclrec();
216 	for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
217 		taprec(cp);
218 }
219 
220 spclrec()
221 {
222 	register int s, i, *ip;
223 
224 	spcl.c_inumber = ino;
225 	spcl.c_magic = MAGIC;
226 	spcl.c_checksum = 0;
227 	ip = (int *)&spcl;
228 	s = 0;
229 	for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++)
230 		s += *ip++;
231 	spcl.c_checksum = CHECKSUM - s;
232 	taprec((char *)&spcl);
233 }
234 
235 dsrch(d, size)
236 	daddr_t d;
237 	int size;
238 {
239 	register struct direct *dp;
240 	long loc;
241 	char dblk[MAXBSIZE];
242 
243 	if(dadded)
244 		return;
245 	bread(fsbtodb(sblock, d), dblk, size);
246 	for (loc = 0; loc < size; ) {
247 		dp = (struct direct *)(dblk + loc);
248 		if (dp->d_reclen == 0)
249 			break;
250 		loc += dp->d_reclen;
251 		if(dp->d_ino == 0)
252 			continue;
253 		if(dp->d_name[0] == '.') {
254 			if(dp->d_name[1] == '\0')
255 				continue;
256 			if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
257 				continue;
258 		}
259 		if(BIT(dp->d_ino, nodmap)) {
260 			dadded++;
261 			return;
262 		}
263 		if(BIT(dp->d_ino, dirmap))
264 			nsubdir++;
265 	}
266 }
267 
268 struct dinode *
269 getino(ino)
270 	daddr_t ino;
271 {
272 	static daddr_t minino, maxino;
273 	static struct dinode itab[MAXINOPB];
274 
275 	if (ino >= minino && ino < maxino) {
276 		return (&itab[ino - minino]);
277 	}
278 	bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize);
279 	minino = ino - (ino % INOPB(sblock));
280 	maxino = minino + INOPB(sblock);
281 	return (&itab[ino - minino]);
282 }
283 
284 int	breaderrors = 0;
285 #define	BREADEMAX 32
286 
287 bread(da, ba, c)
288 	daddr_t da;
289 	char *ba;
290 	int	c;
291 {
292 	register n;
293 	register	regc;
294 
295 	if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
296 		msg("bread: lseek fails\n");
297 	}
298 	regc = c;	/* put c someplace safe; it gets clobbered */
299 	n = read(fi, ba, c);
300 	if (n != c || regc != c) {
301 		msg("(This should not happen)bread from %s [block %d]: c=0x%x, regc=0x%x, &c=0x%x, n=0x%x\n",
302 			disk, da, c, regc, &c, n);
303 #ifdef ERNIE
304 		msg("Notify Robert Henry of this error.\n");
305 #endif
306 		if (++breaderrors > BREADEMAX){
307 			msg("More than %d block read errors from %d\n",
308 				BREADEMAX, disk);
309 			broadcast("DUMP IS AILING!\n");
310 			msg("This is an unrecoverable error.\n");
311 			if (!query("Do you want to attempt to continue?")){
312 				dumpabort();
313 				/*NOTREACHED*/
314 			} else
315 				breaderrors = 0;
316 		}
317 	}
318 }
319 
320 blkclr(cp, size)
321 	char *cp;
322 	long size;
323 {
324 	asm("movc5	$0,(r0),$0,8(ap),*4(ap)");
325 }
326