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