|
|
1.1 root 1: /*
2: * dumpdir [af [dumpfile]]
3: * a Show all entries (include `.' and `..').
4: * f Use `dumpfile', not default.
5: */
6: #include <stdio.h>
7: #include <dumptape.h>
8: #include <canon.h>
9: #include <mdata.h>
10: #include <signal.h>
11:
12: /*
13: * Structure used to remember
14: * things about all the directories
15: * on the tape.
16: */
17: struct dlist
18: {
19: struct dlist *dl_dlp; /* Link to next */
20: ino_t dl_ino; /* Inumber */
21: int dl_dejavu; /* Already seen flag */
22: long dl_seek; /* Tempfile base */
23: long dl_size; /* Size */
24: };
25:
26: char *dtn = DTAPE; /* Tape name */
27: FILE *dtp; /* Tape file pointer */
28: char tfn[30] = "/tmp/ddXXXXXX"; /* Temp file name */
29: FILE *tfp; /* Temp file pointer */
30: int aflag; /* All flag */
31: fsize_t length = 1; /* Length in bytes of volume */
32: fsize_t nread; /* Number of bytes read from volume */
33: struct dlist *dlist; /* List of remembered directories */
34: struct dlist *droot; /* Pointer to first directory */
35: char dstr[1000]; /* Name string */
36: char *dstrp = &dstr[0]; /* Pointer into the above */
37: int reel = 1; /* Reel # */
38: char *ddbuf; /* Dump data buffer */
39: char *ddend; /* Ptr to end of dump data buffer */
40: int ddnbuf; /* Size of buffer (bytes) */
41: union dumpdata *ddptr; /* Ptr to current record in buffer */
42: char *map; /* Inode map */
43:
44: union dumpdata *readdump();
45: struct dlist *findnode();
46: int cleanup();
47: char *calloc();
48:
49: main(argc, argv)
50: char *argv[];
51: {
52: register char *p;
53: register c, i;
54:
55: if (argc > 1) {
56: i = 1;
57: p = argv[1];
58: while ((c = *p++) != '\0') {
59: switch (c) {
60:
61: case 'a':
62: aflag = 1;
63: break;
64:
65: case 'f':
66: if (++i >= argc)
67: usage();
68: dtn = argv[i];
69: break;
70:
71: default:
72: usage();
73: }
74: }
75: }
76: if ((dtp=fopen(dtn, "r")) == NULL)
77: fatal("%s: cannot open dump file", dtn);
78: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
79: signal(SIGINT, cleanup);
80: mktemp(tfn);
81: if ((tfp=fopen(tfn, "w")) == NULL
82: || (tfp=freopen(tfn, "r+w", tfp)) == NULL)
83: fatal("%s: cannot create temporary file", tfn);
84: nextvol();
85: readdirs();
86: if (droot == NULL)
87: fatal("no directories");
88: dumpdirs(droot);
89: delexit(0);
90: }
91:
92: /*
93: * This routine has two jobs.
94: * It reads in the dump file header and
95: * checks it out, looking for strangenesses
96: * in format. It also is responsible for
97: * using information in the header to
98: * allocate the necessary map and dump I/O
99: * buffers.
100: */
101: readhead()
102: {
103: static struct dumpheader dh;
104: register char *p;
105: register checksum;
106:
107: if (read(fileno(dtp), &dh, sizeof dh) != sizeof dh)
108: fatal("header read error");
109: nread = sizeof dh;
110: canint(dh.dh_magic);
111: canino(dh.dh_nino);
112: cantime(dh.dh_bdate);
113: cantime(dh.dh_ddate);
114: canint(dh.dh_level);
115: canint(dh.dh_reel);
116: canint(dh.dh_blocking);
117: cansize(dh.dh_nbyte);
118: canint(dh.dh_checksum);
119: if (dh.dh_magic != DH_MAG)
120: fatal("not a dump");
121: p = (char *) &dh;
122: checksum = 0;
123: while (p < (char *) &dh.dh_checksum)
124: checksum += (*p++) & 0377;
125: if (checksum != dh.dh_checksum)
126: fatal("header checksum error");
127: if (dh.dh_reel != reel)
128: fatal("wrong reel (is %d, not %d)", dh.dh_reel, reel);
129: ++reel;
130: if (map != NULL)
131: free(map);
132: if (ddbuf != NULL)
133: free(ddbuf);
134: if ((map = calloc(sizeof(char), (dh.dh_nino+NBCHAR-1)/NBCHAR)) == NULL)
135: fatal("out of memory (map)");
136: ddnbuf = dh.dh_blocking * sizeof(union dumpdata);
137: if ((ddbuf = malloc(ddnbuf)) == NULL)
138: fatal("out of memory (buffer)");
139: ddend = &ddbuf[ddnbuf];
140: ddptr = (union dumpdata *) ddend;
141: length = dh.dh_nbyte;
142: }
143:
144: /*
145: * Read in all the directories.
146: * This routine assumes that the map entries
147: * have been put out before the inodes and
148: * that all the directories have been put out
149: * before the files.
150: */
151: readdirs()
152: {
153: register union dumpdata *ddp;
154: register struct dlist *dlp;
155:
156: while ((ddp=readdump()) != NULL) {
157: canint(ddp->dd_type);
158: switch (ddp->dd_type) {
159:
160: case DD_EOT:
161: return;
162:
163: case DD_DATA:
164: canino(ddp->dd_ino);
165: candaddr(ddp->dd_block);
166: canint(ddp->dd_size);
167: if (dlist==NULL || dlist->dl_ino!=ddp->dd_ino)
168: fatal("out of sync");
169: fseek(tfp, dlist->dl_seek+(BUFSIZ*ddp->dd_block), 0);
170: fwrite(ddp->dd_data, sizeof(char), BUFSIZ, tfp);
171: if (ferror(tfp))
172: fatal("temporary file write error");
173: break;
174:
175: case DD_INO:
176: canino(ddp->dd_ino);
177: canshort(ddp->dd_dinode.di_mode);
178: cansize(ddp->dd_dinode.di_size);
179: if ((ddp->dd_dinode.di_mode&IFMT) != IFDIR)
180: return;
181: dlp = (struct dlist *) malloc(sizeof(struct dlist));
182: if (dlp == NULL)
183: fatal("out of memory (directory)");
184: dlp->dl_dlp = dlist;
185: dlist = dlp;
186: if (droot == NULL)
187: droot = dlp;
188: dlp->dl_ino = ddp->dd_ino;
189: dlp->dl_dejavu = 0;
190: dlp->dl_seek = ftell(tfp);
191: dlp->dl_size = ddp->dd_dinode.di_size;
192: break;
193:
194: case DD_MAP:
195: canino(ddp->dd_ino);
196: canint(ddp->dd_nmap);
197: setmap(ddp);
198: break;
199:
200: default:
201: fatal("bad type %d", ddp->dd_type);
202: }
203: }
204: }
205:
206: /*
207: * Process a map entry.
208: * Set a bit in the map for every inode
209: * whose dump map entry has the DD_DUMP flag
210: * set.
211: */
212: setmap(ddp)
213: union dumpdata *ddp;
214: {
215: register char *mmapp, *dmapp;
216: register mmask;
217: register nmapb;
218:
219: mmapp = &map[--ddp->dd_ino/NBCHAR];
220: mmask = 01 << (ddp->dd_ino%NBCHAR);
221: dmapp = &ddp->dd_map[0];
222: nmapb = ddp->dd_nmap;
223: while (nmapb--) {
224: if (((*dmapp++)&DD_DUMP) != 0)
225: *mmapp |= mmask;
226: if ((mmask <<= 1) == (01<<NBCHAR)) {
227: ++mmapp;
228: mmask = 01;
229: }
230: }
231: }
232:
233: /*
234: * Return a pointer to the
235: * next dump file item. This routine
236: * knows all about reading the
237: * next tape in a multitape dump.
238: */
239: union dumpdata *
240: readdump()
241: {
242: register nb;
243:
244: while ((char *) ddptr == ddend) {
245: if (length != 0 && (nread+ddnbuf) > length) {
246: nextvol();
247: continue;
248: }
249: if ((nb = read(fileno(dtp), ddbuf, ddnbuf)) != ddnbuf) {
250: if (nb != 0)
251: fatal("dump read error");
252: nextvol();
253: continue;
254: }
255: nread += nb;
256: ddptr = (union dumpdata *) ddbuf;
257: break;
258: }
259: return (ddptr++);
260: }
261:
262: /*
263: * Read the next reel or volume.
264: */
265: nextvol()
266: {
267: fclose(dtp);
268: fprintf(stderr, "dumpdir: mount %s %d, type return key ...",
269: length ? "volume" : "reel", reel);
270: if (fgets(dstr, sizeof(dstr), stdin) == NULL)
271: delexit(1);
272: if ((dtp = fopen(dtn, "r")) == NULL)
273: fatal("%s: cannot open dump tape", dtn);
274: readhead();
275: }
276:
277: /*
278: * Start at the root and
279: * print all of the directories.
280: * Don't print the names of things that
281: * the map says are not on the tape.
282: */
283: dumpdirs(dlp)
284: register struct dlist *dlp;
285: {
286: char *sdstrp;
287: struct direct dirbuf;
288: register char *p1, *p2;
289: register c;
290: register struct dlist *sdlp;
291: ino_t ino;
292:
293: dlp->dl_dejavu = 1;
294: while (dlp->dl_size != 0) {
295: fseek(tfp, dlp->dl_seek, 0);
296: if (fread(&dirbuf, sizeof(dirbuf), 1, tfp) != 1)
297: fatal("temporary file read error");
298: dlp->dl_seek += sizeof(struct direct);
299: dlp->dl_size -= sizeof(struct direct);
300: if (aflag == 0) {
301: if (strncmp(dirbuf.d_name, ".", DIRSIZ) == 0)
302: continue;
303: if (strncmp(dirbuf.d_name, "..", DIRSIZ) == 0)
304: continue;
305: }
306: canino(dirbuf.d_ino);
307: if ((ino = dirbuf.d_ino)!=0 && getbit(ino)!=0) {
308: p1 = sdstrp = dstrp;
309: if (p1 != dstr)
310: *p1++ = '/';
311: p2 = dirbuf.d_name;
312: while (p2<&dirbuf.d_name[DIRSIZ] && (c=*p2++))
313: *p1++ = c;
314: *p1 = '\0';
315: dstrp = p1;
316: printf("%u\t%s\n", ino, dstr);
317: if ((sdlp=findnode(ino))!=NULL && sdlp->dl_dejavu==0)
318: dumpdirs(sdlp);
319: dstrp = sdstrp;
320: *dstrp = '\0';
321: }
322: }
323: dlp->dl_dejavu = 0;
324: }
325:
326: /*
327: * Get the dumped bit for
328: * inode `ino' from the big bit map.
329: */
330: getbit(ino)
331: ino_t ino;
332: {
333: register mapent;
334:
335: mapent = map[--ino/NBCHAR];
336: return (mapent & (01<<ino%NBCHAR));
337: }
338:
339: /*
340: * Return the dlist pointer
341: * for directory inode `ino', or NULL
342: * if it is not there. Not there means
343: * not a directory.
344: */
345: struct dlist *
346: findnode(ino)
347: register ino_t ino;
348: {
349: register struct dlist *dlp;
350:
351: dlp = dlist;
352: while (dlp != NULL) {
353: if (dlp->dl_ino == ino)
354: break;
355: dlp = dlp->dl_dlp;
356: }
357: return (dlp);
358: }
359:
360: /*
361: * Nasty nasty nasty.
362: */
363: fatal(a)
364: {
365: fprintf(stderr, "dumpdir: %r", &a);
366: fprintf(stderr, "\n");
367: delexit(1);
368: }
369:
370: /*
371: * This routine is called from the
372: * interupt signal. It points off to dumpdir
373: * who deletes the temp file and returns
374: * the error status.
375: */
376: cleanup()
377: {
378: delexit(1);
379: }
380:
381: /*
382: * A special version of `exit' that
383: * cleans up by unlinking the temporary
384: * file.
385: */
386: delexit(s)
387: {
388: if (tfp != NULL)
389: unlink(tfn);
390: exit(s);
391: }
392:
393: /*
394: * Print the usage message and
395: * exit.
396: */
397: usage()
398: {
399: fprintf(stderr, "Usage: dumpdir [af [dumpfile]]\n");
400: exit(1);
401: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.