use SBOFF instead of SBLOCK
[unix-history] / usr / src / sbin / dump / traverse.c
CommitLineData
76797561
DF
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
9c787c21 8static char sccsid[] = "@(#)traverse.c 5.3 (Berkeley) %G%";
76797561 9#endif not lint
35fb2af5 10
b6407c9d 11#include "dump.h"
35fb2af5
BJ
12
13pass(fn, map)
9c787c21
KM
14 register int (*fn)();
15 register char *map;
35fb2af5 16{
9c787c21 17 register int bits;
003a2a9e 18 ino_t maxino;
35fb2af5 19
b6407c9d 20 maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
003a2a9e 21 for (ino = 0; ino < maxino; ) {
9c787c21 22 if ((ino % NBBY) == 0) {
003a2a9e 23 bits = ~0;
9c787c21 24 if (map != NULL)
003a2a9e
KM
25 bits = *map++;
26 }
27 ino++;
9c787c21
KM
28 if (bits & 1)
29 (*fn)(getino(ino));
003a2a9e 30 bits >>= 1;
35fb2af5
BJ
31 }
32}
33
35fb2af5 34mark(ip)
1a350083 35 struct dinode *ip;
35fb2af5 36{
9c787c21
KM
37 register int f;
38 extern int anydskipped;
35fb2af5
BJ
39
40 f = ip->di_mode & IFMT;
9c787c21 41 if (f == 0)
35fb2af5
BJ
42 return;
43 BIS(ino, clrmap);
9c787c21 44 if (f == IFDIR)
35fb2af5 45 BIS(ino, dirmap);
b6407c9d
KM
46 if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
47 !BIT(ino, nodmap)) {
35fb2af5 48 BIS(ino, nodmap);
a6b18791 49 if (f != IFREG && f != IFDIR && f != IFLNK) {
35fb2af5
BJ
50 esize += 1;
51 return;
52 }
53 est(ip);
9c787c21
KM
54 } else if (f == IFDIR)
55 anydskipped = 1;
35fb2af5
BJ
56}
57
58add(ip)
b6407c9d 59 register struct dinode *ip;
35fb2af5 60{
b6407c9d 61 register int i;
89f939b6 62 long filesize;
35fb2af5
BJ
63
64 if(BIT(ino, nodmap))
65 return;
66 nsubdir = 0;
67 dadded = 0;
89f939b6 68 filesize = ip->di_size;
b6407c9d
KM
69 for (i = 0; i < NDADDR; i++) {
70 if (ip->di_db[i] != 0)
89f939b6
KM
71 dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize);
72 filesize -= sblock->fs_bsize;
b6407c9d
KM
73 }
74 for (i = 0; i < NIADDR; i++) {
75 if (ip->di_ib[i] != 0)
89f939b6 76 indir(ip->di_ib[i], i, &filesize);
b6407c9d 77 }
35fb2af5 78 if(dadded) {
35fb2af5 79 nadded++;
b6407c9d
KM
80 if (!BIT(ino, nodmap)) {
81 BIS(ino, nodmap);
82 est(ip);
83 }
35fb2af5
BJ
84 }
85 if(nsubdir == 0)
86 if(!BIT(ino, nodmap))
87 BIC(ino, dirmap);
88}
89
89f939b6 90indir(d, n, filesize)
b6407c9d 91 daddr_t d;
89f939b6 92 int n, *filesize;
b6407c9d
KM
93{
94 register i;
95 daddr_t idblk[MAXNINDIR];
96
97 bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize);
98 if(n <= 0) {
99 for(i=0; i < NINDIR(sblock); i++) {
100 d = idblk[i];
101 if(d != 0)
89f939b6
KM
102 dsrch(d, sblock->fs_bsize, *filesize);
103 *filesize -= sblock->fs_bsize;
b6407c9d
KM
104 }
105 } else {
106 n--;
107 for(i=0; i < NINDIR(sblock); i++) {
108 d = idblk[i];
109 if(d != 0)
89f939b6 110 indir(d, n, filesize);
b6407c9d
KM
111 }
112 }
113}
114
7b0c1d85
KM
115dirdump(ip)
116 struct dinode *ip;
117{
118 /* watchout for dir inodes deleted and maybe reallocated */
119 if ((ip->di_mode & IFMT) != IFDIR)
120 return;
121 dump(ip);
122}
123
35fb2af5 124dump(ip)
1a350083 125 struct dinode *ip;
35fb2af5 126{
1a350083
KM
127 register int i;
128 long size;
35fb2af5
BJ
129
130 if(newtape) {
131 newtape = 0;
132 bitmap(nodmap, TS_BITS);
133 }
134 BIC(ino, nodmap);
135 spcl.c_dinode = *ip;
136 spcl.c_type = TS_INODE;
137 spcl.c_count = 0;
138 i = ip->di_mode & IFMT;
7b0c1d85
KM
139 if (i == 0) /* free inode */
140 return;
a6b18791 141 if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
35fb2af5
BJ
142 spclrec();
143 return;
144 }
b6407c9d
KM
145 if (ip->di_size > NDADDR * sblock->fs_bsize)
146 i = NDADDR * sblock->fs_frag;
1a350083 147 else
b6407c9d 148 i = howmany(ip->di_size, sblock->fs_fsize);
1a350083 149 blksout(&ip->di_db[0], i);
b6407c9d 150 size = ip->di_size - NDADDR * sblock->fs_bsize;
1a350083
KM
151 if (size <= 0)
152 return;
153 for (i = 0; i < NIADDR; i++) {
154 dmpindir(ip->di_ib[i], i, &size);
155 if (size <= 0)
156 return;
157 }
35fb2af5
BJ
158}
159
1a350083
KM
160dmpindir(blk, lvl, size)
161 daddr_t blk;
162 int lvl;
163 long *size;
35fb2af5 164{
1a350083 165 int i, cnt;
b6407c9d 166 daddr_t idblk[MAXNINDIR];
35fb2af5 167
1a350083 168 if (blk != 0)
b6407c9d 169 bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
1a350083 170 else
1ddebffe 171 bzero(idblk, sblock->fs_bsize);
1a350083 172 if (lvl <= 0) {
b6407c9d
KM
173 if (*size < NINDIR(sblock) * sblock->fs_bsize)
174 cnt = howmany(*size, sblock->fs_fsize);
1a350083 175 else
b6407c9d
KM
176 cnt = NINDIR(sblock) * sblock->fs_frag;
177 *size -= NINDIR(sblock) * sblock->fs_bsize;
1a350083
KM
178 blksout(&idblk[0], cnt);
179 return;
180 }
181 lvl--;
b6407c9d 182 for (i = 0; i < NINDIR(sblock); i++) {
1a350083
KM
183 dmpindir(idblk[i], lvl, size);
184 if (*size <= 0)
185 return;
186 }
187}
188
189blksout(blkp, frags)
190 daddr_t *blkp;
191 int frags;
192{
b6407c9d 193 int i, j, count, blks, tbperdb;
1a350083 194
184c56be 195 blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
092ee994 196 tbperdb = sblock->fs_bsize / TP_BSIZE;
1a350083
KM
197 for (i = 0; i < blks; i += TP_NINDIR) {
198 if (i + TP_NINDIR > blks)
199 count = blks;
200 else
201 count = i + TP_NINDIR;
202 for (j = i; j < count; j++)
b6407c9d 203 if (blkp[j / tbperdb] != 0)
1a350083
KM
204 spcl.c_addr[j - i] = 1;
205 else
206 spcl.c_addr[j - i] = 0;
207 spcl.c_count = count - i;
208 spclrec();
b6407c9d
KM
209 for (j = i; j < count; j += tbperdb)
210 if (blkp[j / tbperdb] != 0)
211 if (j + tbperdb <= count)
212 dmpblk(blkp[j / tbperdb],
213 sblock->fs_bsize);
1a350083 214 else
b6407c9d 215 dmpblk(blkp[j / tbperdb],
1a350083
KM
216 (count - j) * TP_BSIZE);
217 spcl.c_type = TS_ADDR;
35fb2af5 218 }
35fb2af5
BJ
219}
220
221bitmap(map, typ)
b6407c9d 222 char *map;
35fb2af5 223{
312da552 224 register i;
35fb2af5
BJ
225 char *cp;
226
35fb2af5 227 spcl.c_type = typ;
312da552 228 spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE);
35fb2af5 229 spclrec();
b6407c9d 230 for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
35fb2af5 231 taprec(cp);
35fb2af5
BJ
232}
233
234spclrec()
235{
1a350083 236 register int s, i, *ip;
35fb2af5
BJ
237
238 spcl.c_inumber = ino;
75c26040 239 spcl.c_magic = NFS_MAGIC;
35fb2af5
BJ
240 spcl.c_checksum = 0;
241 ip = (int *)&spcl;
242 s = 0;
878f0fb2
KM
243 i = sizeof(union u_spcl) / (4*sizeof(int));
244 while (--i >= 0) {
245 s += *ip++; s += *ip++;
246 s += *ip++; s += *ip++;
247 }
35fb2af5
BJ
248 spcl.c_checksum = CHECKSUM - s;
249 taprec((char *)&spcl);
250}
251
89f939b6 252dsrch(d, size, filesize)
1a350083 253 daddr_t d;
89f939b6 254 int size, filesize;
35fb2af5 255{
b45e25c0
KM
256 register struct direct *dp;
257 long loc;
258 char dblk[MAXBSIZE];
35fb2af5
BJ
259
260 if(dadded)
261 return;
89f939b6
KM
262 if (filesize > size)
263 filesize = size;
d4c718f6 264 bread(fsbtodb(sblock, d), dblk, filesize);
89f939b6 265 for (loc = 0; loc < filesize; ) {
b45e25c0 266 dp = (struct direct *)(dblk + loc);
89f939b6
KM
267 if (dp->d_reclen == 0) {
268 msg("corrupted directory, inumber %d\n", ino);
b45e25c0 269 break;
89f939b6 270 }
b45e25c0
KM
271 loc += dp->d_reclen;
272 if(dp->d_ino == 0)
35fb2af5 273 continue;
b45e25c0
KM
274 if(dp->d_name[0] == '.') {
275 if(dp->d_name[1] == '\0')
35fb2af5 276 continue;
b45e25c0 277 if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
35fb2af5
BJ
278 continue;
279 }
b45e25c0 280 if(BIT(dp->d_ino, nodmap)) {
35fb2af5
BJ
281 dadded++;
282 return;
283 }
b45e25c0 284 if(BIT(dp->d_ino, dirmap))
35fb2af5
BJ
285 nsubdir++;
286 }
287}
288
003a2a9e
KM
289struct dinode *
290getino(ino)
291 daddr_t ino;
292{
293 static daddr_t minino, maxino;
b6407c9d 294 static struct dinode itab[MAXINOPB];
003a2a9e
KM
295
296 if (ino >= minino && ino < maxino) {
297 return (&itab[ino - minino]);
298 }
6994bf5d 299 bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize);
b6407c9d
KM
300 minino = ino - (ino % INOPB(sblock));
301 maxino = minino + INOPB(sblock);
003a2a9e
KM
302 return (&itab[ino - minino]);
303}
304
35fb2af5
BJ
305int breaderrors = 0;
306#define BREADEMAX 32
307
d4c718f6 308bread(da, ba, cnt)
35fb2af5
BJ
309 daddr_t da;
310 char *ba;
d4c718f6 311 int cnt;
35fb2af5 312{
d4c718f6 313 int n;
35fb2af5 314
d4c718f6 315loop:
b6407c9d 316 if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
35fb2af5
BJ
317 msg("bread: lseek fails\n");
318 }
d4c718f6
KM
319 n = read(fi, ba, cnt);
320 if (n == cnt)
321 return;
322 if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) {
323 /*
324 * Trying to read the final fragment.
325 *
326 * NB - dump only works in TP_BSIZE blocks, hence
327 * rounds DEV_BSIZE fragments up to TP_BSIZE pieces.
328 * It should be smarter about not actually trying to
329 * read more than it can get, but for the time being
330 * we punt and scale back the read only when it gets
331 * us into trouble. (mkm 9/25/83)
332 */
333 cnt -= DEV_BSIZE;
334 goto loop;
335 }
336 msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n",
337 disk, da, cnt, n);
338 if (++breaderrors > BREADEMAX){
339 msg("More than %d block read errors from %d\n",
340 BREADEMAX, disk);
341 broadcast("DUMP IS AILING!\n");
342 msg("This is an unrecoverable error.\n");
343 if (!query("Do you want to attempt to continue?")){
344 dumpabort();
345 /*NOTREACHED*/
346 } else
347 breaderrors = 0;
35fb2af5
BJ
348 }
349}