|
|
1.1 root 1: static char *sccsid = "@(#)dumptraverse.c 1.15 (Berkeley) 9/25/83";
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: long filesize;
56:
57: if(BIT(ino, nodmap))
58: return;
59: nsubdir = 0;
60: dadded = 0;
61: filesize = ip->di_size;
62: for (i = 0; i < NDADDR; i++) {
63: if (ip->di_db[i] != 0)
64: dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize);
65: filesize -= sblock->fs_bsize;
66: }
67: for (i = 0; i < NIADDR; i++) {
68: if (ip->di_ib[i] != 0)
69: indir(ip->di_ib[i], i, &filesize);
70: }
71: if(dadded) {
72: nadded++;
73: if (!BIT(ino, nodmap)) {
74: BIS(ino, nodmap);
75: est(ip);
76: }
77: }
78: if(nsubdir == 0)
79: if(!BIT(ino, nodmap))
80: BIC(ino, dirmap);
81: }
82:
83: indir(d, n, filesize)
84: daddr_t d;
85: int n, *filesize;
86: {
87: register i;
88: daddr_t idblk[MAXNINDIR];
89:
90: bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize);
91: if(n <= 0) {
92: for(i=0; i < NINDIR(sblock); i++) {
93: d = idblk[i];
94: if(d != 0)
95: dsrch(d, sblock->fs_bsize, *filesize);
96: *filesize -= sblock->fs_bsize;
97: }
98: } else {
99: n--;
100: for(i=0; i < NINDIR(sblock); i++) {
101: d = idblk[i];
102: if(d != 0)
103: indir(d, n, filesize);
104: }
105: }
106: }
107:
108: dirdump(ip)
109: struct dinode *ip;
110: {
111: /* watchout for dir inodes deleted and maybe reallocated */
112: if ((ip->di_mode & IFMT) != IFDIR)
113: return;
114: dump(ip);
115: }
116:
117: dump(ip)
118: struct dinode *ip;
119: {
120: register int i;
121: long size;
122:
123: if(newtape) {
124: newtape = 0;
125: bitmap(nodmap, TS_BITS);
126: }
127: BIC(ino, nodmap);
128: spcl.c_dinode = *ip;
129: spcl.c_type = TS_INODE;
130: spcl.c_count = 0;
131: i = ip->di_mode & IFMT;
132: if (i == 0) /* free inode */
133: return;
134: if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
135: spclrec();
136: return;
137: }
138: if (ip->di_size > NDADDR * sblock->fs_bsize)
139: i = NDADDR * sblock->fs_frag;
140: else
141: i = howmany(ip->di_size, sblock->fs_fsize);
142: blksout(&ip->di_db[0], i);
143: size = ip->di_size - NDADDR * sblock->fs_bsize;
144: if (size <= 0)
145: return;
146: for (i = 0; i < NIADDR; i++) {
147: dmpindir(ip->di_ib[i], i, &size);
148: if (size <= 0)
149: return;
150: }
151: }
152:
153: dmpindir(blk, lvl, size)
154: daddr_t blk;
155: int lvl;
156: long *size;
157: {
158: int i, cnt;
159: daddr_t idblk[MAXNINDIR];
160:
161: if (blk != 0)
162: bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
163: else
164: bzero(idblk, sblock->fs_bsize);
165: if (lvl <= 0) {
166: if (*size < NINDIR(sblock) * sblock->fs_bsize)
167: cnt = howmany(*size, sblock->fs_fsize);
168: else
169: cnt = NINDIR(sblock) * sblock->fs_frag;
170: *size -= NINDIR(sblock) * sblock->fs_bsize;
171: blksout(&idblk[0], cnt);
172: return;
173: }
174: lvl--;
175: for (i = 0; i < NINDIR(sblock); i++) {
176: dmpindir(idblk[i], lvl, size);
177: if (*size <= 0)
178: return;
179: }
180: }
181:
182: blksout(blkp, frags)
183: daddr_t *blkp;
184: int frags;
185: {
186: int i, j, count, blks, tbperdb;
187:
188: blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
189: tbperdb = sblock->fs_bsize / TP_BSIZE;
190: for (i = 0; i < blks; i += TP_NINDIR) {
191: if (i + TP_NINDIR > blks)
192: count = blks;
193: else
194: count = i + TP_NINDIR;
195: for (j = i; j < count; j++)
196: if (blkp[j / tbperdb] != 0)
197: spcl.c_addr[j - i] = 1;
198: else
199: spcl.c_addr[j - i] = 0;
200: spcl.c_count = count - i;
201: spclrec();
202: for (j = i; j < count; j += tbperdb)
203: if (blkp[j / tbperdb] != 0)
204: if (j + tbperdb <= count)
205: dmpblk(blkp[j / tbperdb],
206: sblock->fs_bsize);
207: else
208: dmpblk(blkp[j / tbperdb],
209: (count - j) * TP_BSIZE);
210: spcl.c_type = TS_ADDR;
211: }
212: }
213:
214: bitmap(map, typ)
215: char *map;
216: {
217: register i, n;
218: char *cp;
219:
220: spcl.c_type = typ;
221: spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE);
222: spclrec();
223: for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
224: taprec(cp);
225: }
226:
227: spclrec()
228: {
229: register int s, i, *ip;
230:
231: spcl.c_inumber = ino;
232: spcl.c_magic = NFS_MAGIC;
233: spcl.c_checksum = 0;
234: ip = (int *)&spcl;
235: s = 0;
236: for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++)
237: s += *ip++;
238: spcl.c_checksum = CHECKSUM - s;
239: taprec((char *)&spcl);
240: }
241:
242: dsrch(d, size, filesize)
243: daddr_t d;
244: int size, filesize;
245: {
246: register struct direct *dp;
247: long loc;
248: char dblk[MAXBSIZE];
249:
250: if(dadded)
251: return;
252: if (filesize > size)
253: filesize = size;
254: bread(fsbtodb(sblock, d), dblk, filesize);
255: for (loc = 0; loc < filesize; ) {
256: dp = (struct direct *)(dblk + loc);
257: if (dp->d_reclen == 0) {
258: msg("corrupted directory, inumber %d\n", ino);
259: break;
260: }
261: loc += dp->d_reclen;
262: if(dp->d_ino == 0)
263: continue;
264: if(dp->d_name[0] == '.') {
265: if(dp->d_name[1] == '\0')
266: continue;
267: if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
268: continue;
269: }
270: if(BIT(dp->d_ino, nodmap)) {
271: dadded++;
272: return;
273: }
274: if(BIT(dp->d_ino, dirmap))
275: nsubdir++;
276: }
277: }
278:
279: struct dinode *
280: getino(ino)
281: daddr_t ino;
282: {
283: static daddr_t minino, maxino;
284: static struct dinode itab[MAXINOPB];
285:
286: if (ino >= minino && ino < maxino) {
287: return (&itab[ino - minino]);
288: }
289: bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize);
290: minino = ino - (ino % INOPB(sblock));
291: maxino = minino + INOPB(sblock);
292: return (&itab[ino - minino]);
293: }
294:
295: int breaderrors = 0;
296: #define BREADEMAX 32
297:
298: bread(da, ba, cnt)
299: daddr_t da;
300: char *ba;
301: int cnt;
302: {
303: int n;
304:
305: loop:
306: if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
307: msg("bread: lseek fails\n");
308: }
309: n = read(fi, ba, cnt);
310: if (n == cnt)
311: return;
312: if (da + (cnt / DEV_BSIZE) > fsbtodb(sblock, sblock->fs_size)) {
313: /*
314: * Trying to read the final fragment.
315: *
316: * NB - dump only works in TP_BSIZE blocks, hence
317: * rounds DEV_BSIZE fragments up to TP_BSIZE pieces.
318: * It should be smarter about not actually trying to
319: * read more than it can get, but for the time being
320: * we punt and scale back the read only when it gets
321: * us into trouble. (mkm 9/25/83)
322: */
323: cnt -= DEV_BSIZE;
324: goto loop;
325: }
326: msg("(This should not happen)bread from %s [block %d]: count=%d, got=%d\n",
327: disk, da, cnt, n);
328: if (++breaderrors > BREADEMAX){
329: msg("More than %d block read errors from %d\n",
330: BREADEMAX, disk);
331: broadcast("DUMP IS AILING!\n");
332: msg("This is an unrecoverable error.\n");
333: if (!query("Do you want to attempt to continue?")){
334: dumpabort();
335: /*NOTREACHED*/
336: } else
337: breaderrors = 0;
338: }
339: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.