|
|
1.1 root 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.3 (Berkeley) 1/9/86";
9: #endif not lint
10:
11: #include "dump.h"
12:
13: pass(fn, map)
14: register int (*fn)();
15: register char *map;
16: {
17: register int bits;
18: ino_t maxino;
19:
20: maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
21: for (ino = 0; ino < maxino; ) {
22: if ((ino % NBBY) == 0) {
23: bits = ~0;
24: if (map != NULL)
25: bits = *map++;
26: }
27: ino++;
28: if (bits & 1)
29: (*fn)(getino(ino));
30: bits >>= 1;
31: }
32: }
33:
34: mark(ip)
35: struct dinode *ip;
36: {
37: register int f;
38: extern int anydskipped;
39:
40: f = ip->di_mode & IFMT;
41: if (f == 0)
42: return;
43: BIS(ino, clrmap);
44: if (f == IFDIR)
45: BIS(ino, dirmap);
46: if ((ip->di_mtime >= spcl.c_ddate || ip->di_ctime >= spcl.c_ddate) &&
47: !BIT(ino, nodmap)) {
48: BIS(ino, nodmap);
49: if (f != IFREG && f != IFDIR && f != IFLNK) {
50: esize += 1;
51: return;
52: }
53: est(ip);
54: } else if (f == IFDIR)
55: anydskipped = 1;
56: }
57:
58: add(ip)
59: register struct dinode *ip;
60: {
61: register int i;
62: long filesize;
63:
64: if(BIT(ino, nodmap))
65: return;
66: nsubdir = 0;
67: dadded = 0;
68: filesize = ip->di_size;
69: for (i = 0; i < NDADDR; i++) {
70: if (ip->di_db[i] != 0)
71: dsrch(ip->di_db[i], dblksize(sblock, ip, i), filesize);
72: filesize -= sblock->fs_bsize;
73: }
74: for (i = 0; i < NIADDR; i++) {
75: if (ip->di_ib[i] != 0)
76: indir(ip->di_ib[i], i, &filesize);
77: }
78: if(dadded) {
79: nadded++;
80: if (!BIT(ino, nodmap)) {
81: BIS(ino, nodmap);
82: est(ip);
83: }
84: }
85: if(nsubdir == 0)
86: if(!BIT(ino, nodmap))
87: BIC(ino, dirmap);
88: }
89:
90: indir(d, n, filesize)
91: daddr_t d;
92: int n, *filesize;
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)
102: dsrch(d, sblock->fs_bsize, *filesize);
103: *filesize -= sblock->fs_bsize;
104: }
105: } else {
106: n--;
107: for(i=0; i < NINDIR(sblock); i++) {
108: d = idblk[i];
109: if(d != 0)
110: indir(d, n, filesize);
111: }
112: }
113: }
114:
115: dirdump(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:
124: dump(ip)
125: struct dinode *ip;
126: {
127: register int i;
128: long size;
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;
139: if (i == 0) /* free inode */
140: return;
141: if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) {
142: spclrec();
143: return;
144: }
145: if (ip->di_size > NDADDR * sblock->fs_bsize)
146: i = NDADDR * sblock->fs_frag;
147: else
148: i = howmany(ip->di_size, sblock->fs_fsize);
149: blksout(&ip->di_db[0], i);
150: size = ip->di_size - NDADDR * sblock->fs_bsize;
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: }
158: }
159:
160: dmpindir(blk, lvl, size)
161: daddr_t blk;
162: int lvl;
163: long *size;
164: {
165: int i, cnt;
166: daddr_t idblk[MAXNINDIR];
167:
168: if (blk != 0)
169: bread(fsbtodb(sblock, blk), (char *)idblk, sblock->fs_bsize);
170: else
171: bzero(idblk, sblock->fs_bsize);
172: if (lvl <= 0) {
173: if (*size < NINDIR(sblock) * sblock->fs_bsize)
174: cnt = howmany(*size, sblock->fs_fsize);
175: else
176: cnt = NINDIR(sblock) * sblock->fs_frag;
177: *size -= NINDIR(sblock) * sblock->fs_bsize;
178: blksout(&idblk[0], cnt);
179: return;
180: }
181: lvl--;
182: for (i = 0; i < NINDIR(sblock); i++) {
183: dmpindir(idblk[i], lvl, size);
184: if (*size <= 0)
185: return;
186: }
187: }
188:
189: blksout(blkp, frags)
190: daddr_t *blkp;
191: int frags;
192: {
193: int i, j, count, blks, tbperdb;
194:
195: blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
196: tbperdb = sblock->fs_bsize / TP_BSIZE;
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++)
203: if (blkp[j / tbperdb] != 0)
204: spcl.c_addr[j - i] = 1;
205: else
206: spcl.c_addr[j - i] = 0;
207: spcl.c_count = count - i;
208: spclrec();
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);
214: else
215: dmpblk(blkp[j / tbperdb],
216: (count - j) * TP_BSIZE);
217: spcl.c_type = TS_ADDR;
218: }
219: }
220:
221: bitmap(map, typ)
222: char *map;
223: {
224: register i;
225: char *cp;
226:
227: spcl.c_type = typ;
228: spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE);
229: spclrec();
230: for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
231: taprec(cp);
232: }
233:
234: spclrec()
235: {
236: register int s, i, *ip;
237:
238: spcl.c_inumber = ino;
239: spcl.c_magic = NFS_MAGIC;
240: spcl.c_checksum = 0;
241: ip = (int *)&spcl;
242: s = 0;
243: i = sizeof(union u_spcl) / (4*sizeof(int));
244: while (--i >= 0) {
245: s += *ip++; s += *ip++;
246: s += *ip++; s += *ip++;
247: }
248: spcl.c_checksum = CHECKSUM - s;
249: taprec((char *)&spcl);
250: }
251:
252: dsrch(d, size, filesize)
253: daddr_t d;
254: int size, filesize;
255: {
256: register struct direct *dp;
257: long loc;
258: char dblk[MAXBSIZE];
259:
260: if(dadded)
261: return;
262: if (filesize > size)
263: filesize = size;
264: bread(fsbtodb(sblock, d), dblk, filesize);
265: for (loc = 0; loc < filesize; ) {
266: dp = (struct direct *)(dblk + loc);
267: if (dp->d_reclen == 0) {
268: msg("corrupted directory, inumber %d\n", ino);
269: break;
270: }
271: loc += dp->d_reclen;
272: if(dp->d_ino == 0)
273: continue;
274: if(dp->d_name[0] == '.') {
275: if(dp->d_name[1] == '\0')
276: continue;
277: if(dp->d_name[1] == '.' && dp->d_name[2] == '\0')
278: continue;
279: }
280: if(BIT(dp->d_ino, nodmap)) {
281: dadded++;
282: return;
283: }
284: if(BIT(dp->d_ino, dirmap))
285: nsubdir++;
286: }
287: }
288:
289: struct dinode *
290: getino(ino)
291: daddr_t ino;
292: {
293: static daddr_t minino, maxino;
294: static struct dinode itab[MAXINOPB];
295:
296: if (ino >= minino && ino < maxino) {
297: return (&itab[ino - minino]);
298: }
299: bread(fsbtodb(sblock, itod(sblock, ino)), itab, sblock->fs_bsize);
300: minino = ino - (ino % INOPB(sblock));
301: maxino = minino + INOPB(sblock);
302: return (&itab[ino - minino]);
303: }
304:
305: int breaderrors = 0;
306: #define BREADEMAX 32
307:
308: bread(da, ba, cnt)
309: daddr_t da;
310: char *ba;
311: int cnt;
312: {
313: int n;
314:
315: loop:
316: if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){
317: msg("bread: lseek fails\n");
318: }
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;
348: }
349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.