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