xref: /original-bsd/old/dump.4.1/dumptraverse.c (revision e21485a6)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)dumptraverse.c	5.1 (Berkeley) 06/05/85";
9 #endif not lint
10 
11 #include "dump.h"
12 
13 struct	filsys	sblock;
14 struct	dinode	itab[INOPB * NI];
15 
16 pass(fn, map)
17 int (*fn)();
18 short *map;
19 {
20 	register i, j;
21 	int bits;
22 	ino_t mino;
23 	daddr_t d;
24 
25 	sync();
26 	bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
27 	mino = (sblock.s_isize-2) * INOPB;
28 	ino = 0;
29 	for(i=2;; i+=NI) {
30 		if(ino >= mino)
31 			break;
32 		d = (unsigned)i;
33 		for(j=0; j<INOPB*NI; j++) {
34 			if(ino >= mino)
35 				break;
36 			if((ino % MLEN) == 0) {
37 				bits = ~0;
38 				if(map != NULL)
39 					bits = *map++;
40 			}
41 			ino++;
42 			if(bits & 1) {
43 				if(d != 0) {
44 					bread(d, (char *)itab, sizeof(itab));
45 					d = 0;
46 				}
47 				(*fn)(&itab[j]);
48 			}
49 			bits >>= 1;
50 		}
51 	}
52 }
53 
54 icat(ip, fn1, fn2)
55 struct	dinode	*ip;
56 int (*fn1)(), (*fn2)();
57 {
58 	register i;
59 	daddr_t d[NADDR];
60 
61 	l3tol(&d[0], &ip->di_addr[0], NADDR);
62 	(*fn2)(d, NADDR-3);
63 	for(i=0; i<NADDR; i++) {
64 		if(d[i] != 0) {
65 			if(i < NADDR-3)
66 				(*fn1)(d[i]); else
67 				indir(d[i], fn1, fn2, i-(NADDR-3));
68 		}
69 	}
70 }
71 
72 indir(d, fn1, fn2, n)
73 daddr_t d;
74 int (*fn1)(), (*fn2)();
75 {
76 	register i;
77 	daddr_t	idblk[NINDIR];
78 
79 	bread(d, (char *)idblk, sizeof(idblk));
80 	if(n <= 0) {
81 		spcl.c_type = TS_ADDR;
82 		(*fn2)(idblk, NINDIR);
83 		for(i=0; i<NINDIR; i++) {
84 			d = idblk[i];
85 			if(d != 0)
86 				(*fn1)(d);
87 		}
88 	} else {
89 		n--;
90 		for(i=0; i<NINDIR; i++) {
91 			d = idblk[i];
92 			if(d != 0)
93 				indir(d, fn1, fn2, n);
94 		}
95 	}
96 }
97 
98 mark(ip)
99 struct dinode *ip;
100 {
101 	register f;
102 
103 	f = ip->di_mode & IFMT;
104 	if(f == 0)
105 		return;
106 	BIS(ino, clrmap);
107 	if(f == IFDIR)
108 		BIS(ino, dirmap);
109 	if(ip->di_mtime >= spcl.c_ddate ||
110 	   ip->di_ctime >= spcl.c_ddate) {
111 		BIS(ino, nodmap);
112 		if (f != IFREG){
113 			esize += 1;
114 			return;
115 		}
116 		est(ip);
117 	}
118 }
119 
120 add(ip)
121 struct dinode *ip;
122 {
123 
124 	if(BIT(ino, nodmap))
125 		return;
126 	nsubdir = 0;
127 	dadded = 0;
128 	icat(ip, dsrch, nullf);
129 	if(dadded) {
130 		BIS(ino, nodmap);
131 		est(ip);
132 		nadded++;
133 	}
134 	if(nsubdir == 0)
135 		if(!BIT(ino, nodmap))
136 			BIC(ino, dirmap);
137 }
138 
139 dump(ip)
140 struct dinode *ip;
141 {
142 	register i;
143 
144 	if(newtape) {
145 		newtape = 0;
146 		bitmap(nodmap, TS_BITS);
147 	}
148 	BIC(ino, nodmap);
149 	spcl.c_dinode = *ip;
150 	spcl.c_type = TS_INODE;
151 	spcl.c_count = 0;
152 	i = ip->di_mode & IFMT;
153 	if(i != IFDIR && i != IFREG) {
154 		spclrec();
155 		return;
156 	}
157 	icat(ip, tapsrec, dmpspc);
158 }
159 
160 dmpspc(dp, n)
161 daddr_t *dp;
162 {
163 	register i, t;
164 
165 	spcl.c_count = n;
166 	for(i=0; i<n; i++) {
167 		t = 0;
168 		if(dp[i] != 0)
169 			t++;
170 		spcl.c_addr[i] = t;
171 	}
172 	spclrec();
173 }
174 
175 bitmap(map, typ)
176 short *map;
177 {
178 	register i, n;
179 	char *cp;
180 
181 	n = -1;
182 	for(i=0; i<MSIZ; i++)
183 		if(map[i])
184 			n = i;
185 	if(n < 0)
186 		return;
187 	spcl.c_type = typ;
188 	spcl.c_count = (n*sizeof(map[0]) + BSIZE)/BSIZE;
189 	spclrec();
190 	cp = (char *)map;
191 	for(i=0; i<spcl.c_count; i++) {
192 		taprec(cp);
193 		cp += BSIZE;
194 	}
195 }
196 
197 spclrec()
198 {
199 	register i, *ip, s;
200 
201 	spcl.c_inumber = ino;
202 	spcl.c_magic = MAGIC;
203 	spcl.c_checksum = 0;
204 	ip = (int *)&spcl;
205 	s = 0;
206 	for(i=0; i<BSIZE/sizeof(*ip); i++)
207 		s += *ip++;
208 	spcl.c_checksum = CHECKSUM - s;
209 	taprec((char *)&spcl);
210 }
211 
212 dsrch(d)
213 daddr_t d;
214 {
215 	register char *cp;
216 	register i;
217 	register ino_t in;
218 	struct direct dblk[DIRPB];
219 
220 	if(dadded)
221 		return;
222 	bread(d, (char *)dblk, sizeof(dblk));
223 	for(i=0; i<DIRPB; i++) {
224 		in = dblk[i].d_ino;
225 		if(in == 0)
226 			continue;
227 		cp = dblk[i].d_name;
228 		if(cp[0] == '.') {
229 			if(cp[1] == '\0')
230 				continue;
231 			if(cp[1] == '.' && cp[2] == '\0')
232 				continue;
233 		}
234 		if(BIT(in, nodmap)) {
235 			dadded++;
236 			return;
237 		}
238 		if(BIT(in, dirmap))
239 			nsubdir++;
240 	}
241 }
242 
243 nullf()
244 {
245 }
246 
247 int	breaderrors = 0;
248 #define	BREADEMAX 32
249 
250 bread(da, ba, c)
251 	daddr_t da;
252 	char *ba;
253 	int	c;
254 {
255 	register n;
256 	register	regc;
257 
258 	if (lseek(fi, (long)(da*BSIZE), 0) < 0){
259 		msg("bread: lseek fails\n");
260 	}
261 	regc = c;	/* put c someplace safe; it gets clobbered */
262 	n = read(fi, ba, c);
263 	if(n != c || regc != c){
264 		msg("(This should not happen)bread from %s [block %d]: c=0x%x, regc=0x%x, &c=0x%x, n=0x%x\n",
265 			disk, da, c, regc, &c, n);
266 #ifdef ERNIE
267 		msg("Notify Robert Henry of this error.\n");
268 #endif
269 		if (++breaderrors > BREADEMAX){
270 			msg("More than %d block read errors from %d\n",
271 				BREADEMAX, disk);
272 			broadcast("DUMP IS AILING!\n");
273 			msg("This is an unrecoverable error.\n");
274 			if (!query("Do you want to attempt to continue?")){
275 				dumpabort();
276 				/*NOTREACHED*/
277 			} else
278 				breaderrors = 0;
279 		}
280 	}
281 }
282 
283 CLR(map)
284 register short *map;
285 {
286 	register n;
287 
288 	n = MSIZ;
289 	do
290 		*map++ = 0;
291 	while(--n);
292 }
293 
294