|
|
1.1 root 1: /*
2: * Copyright (c) 1983 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)tape.c 5.19 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: #include "restore.h"
25: #include <protocols/dumprestore.h>
26: #include <sys/ioctl.h>
27: #include <sys/mtio.h>
28: #include <sys/file.h>
29: #include <setjmp.h>
30: #include <sys/stat.h>
31: #include "pathnames.h"
32:
33: static long fssize = MAXBSIZE;
34: static int mt = -1;
35: static int pipein = 0;
36: static char magtape[BUFSIZ];
37: static int bct;
38: static char *tbf;
39: static union u_spcl endoftapemark;
40: static long blksread;
41: static long tapesread;
42: static jmp_buf restart;
43: static int gettingfile = 0; /* restart has a valid frame */
44:
45: static int ofile;
46: static char *map;
47: static char lnkbuf[MAXPATHLEN + 1];
48: static int pathlen;
49:
50: int Bcvt; /* Swap Bytes (for CCI or sun) */
51: static int Qcvt; /* Swap quads (for sun) */
52: /*
53: * Set up an input source
54: */
55: setinput(source)
56: char *source;
57: {
58: extern int errno;
59: #ifdef RRESTORE
60: char *host, *tape;
61: #endif RRESTORE
62: char *strerror();
63:
64: flsht();
65: if (bflag)
66: newtapebuf(ntrec);
67: else
68: newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC);
69: terminal = stdin;
70: #ifdef RRESTORE
71: host = source;
72: tape = index(host, ':');
73: if (tape == 0) {
74: nohost:
75: msg("need keyletter ``f'' and device ``host:tape''\n");
76: done(1);
77: }
78: *tape++ = '\0';
79: (void) strcpy(magtape, tape);
80: if (rmthost(host) == 0)
81: done(1);
82: setuid(getuid()); /* no longer need or want root privileges */
83: #else
84: if (strcmp(source, "-") == 0) {
85: /*
86: * Since input is coming from a pipe we must establish
87: * our own connection to the terminal.
88: */
89: terminal = fopen(_PATH_TTY, "r");
90: if (terminal == NULL) {
91: (void)fprintf(stderr, "Cannot open %s: %s\n",
92: _PATH_TTY, strerror(errno));
93: terminal = fopen(_PATH_DEVNULL, "r");
94: if (terminal == NULL) {
95: (void)fprintf(stderr, "Cannot open %s: %s\n",
96: _PATH_DEVNULL, strerror(errno));
97: done(1);
98: }
99: }
100: pipein++;
101: }
102: (void) strcpy(magtape, source);
103: #endif RRESTORE
104: }
105:
106: newtapebuf(size)
107: long size;
108: {
109: static tbfsize = -1;
110:
111: ntrec = size;
112: if (size <= tbfsize)
113: return;
114: if (tbf != NULL)
115: free(tbf);
116: tbf = (char *)malloc(size * TP_BSIZE);
117: if (tbf == NULL) {
118: fprintf(stderr, "Cannot allocate space for tape buffer\n");
119: done(1);
120: }
121: tbfsize = size;
122: }
123:
124: /*
125: * Verify that the tape drive can be accessed and
126: * that it actually is a dump tape.
127: */
128: setup()
129: {
130: int i, j, *ip;
131: struct stat stbuf;
132: extern int xtrmap(), xtrmapskip();
133:
134: vprintf(stdout, "Verify tape and initialize maps\n");
135: #ifdef RRESTORE
136: if ((mt = rmtopen(magtape, 0)) < 0)
137: #else
138: if (pipein)
139: mt = 0;
140: else if ((mt = open(magtape, 0)) < 0)
141: #endif
142: {
143: perror(magtape);
144: done(1);
145: }
146: volno = 1;
147: setdumpnum();
148: flsht();
149: if (!pipein && !bflag)
150: findtapeblksize();
151: if (gethead(&spcl) == FAIL) {
152: bct--; /* push back this block */
153: cvtflag++;
154: if (gethead(&spcl) == FAIL) {
155: fprintf(stderr, "Tape is not a dump tape\n");
156: done(1);
157: }
158: fprintf(stderr, "Converting to new file system format.\n");
159: }
160: if (pipein) {
161: endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
162: endoftapemark.s_spcl.c_type = TS_END;
163: ip = (int *)&endoftapemark;
164: j = sizeof(union u_spcl) / sizeof(int);
165: i = 0;
166: do
167: i += *ip++;
168: while (--j);
169: endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
170: }
171: if (vflag || command == 't')
172: printdumpinfo();
173: dumptime = spcl.c_ddate;
174: dumpdate = spcl.c_date;
175: if (stat(".", &stbuf) < 0) {
176: perror("cannot stat .");
177: done(1);
178: }
179: if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE)
180: fssize = stbuf.st_blksize;
181: if (((fssize - 1) & fssize) != 0) {
182: fprintf(stderr, "bad block size %d\n", fssize);
183: done(1);
184: }
185: if (checkvol(&spcl, (long)1) == FAIL) {
186: fprintf(stderr, "Tape is not volume 1 of the dump\n");
187: done(1);
188: }
189: if (readhdr(&spcl) == FAIL)
190: panic("no header after volume mark!\n");
191: findinode(&spcl);
192: if (checktype(&spcl, TS_CLRI) == FAIL) {
193: fprintf(stderr, "Cannot find file removal list\n");
194: done(1);
195: }
196: maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
197: dprintf(stdout, "maxino = %d\n", maxino);
198: map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
199: if (map == (char *)NIL)
200: panic("no memory for file removal list\n");
201: clrimap = map;
202: curfile.action = USING;
203: getfile(xtrmap, xtrmapskip);
204: if (checktype(&spcl, TS_BITS) == FAIL) {
205: fprintf(stderr, "Cannot find file dump list\n");
206: done(1);
207: }
208: map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
209: if (map == (char *)NULL)
210: panic("no memory for file dump list\n");
211: dumpmap = map;
212: curfile.action = USING;
213: getfile(xtrmap, xtrmapskip);
214: }
215:
216: /*
217: * Prompt user to load a new dump volume.
218: * "Nextvol" is the next suggested volume to use.
219: * This suggested volume is enforced when doing full
220: * or incremental restores, but can be overrridden by
221: * the user when only extracting a subset of the files.
222: */
223: getvol(nextvol)
224: long nextvol;
225: {
226: long newvol;
227: long savecnt, i;
228: union u_spcl tmpspcl;
229: # define tmpbuf tmpspcl.s_spcl
230: char buf[TP_BSIZE];
231: extern char *ctime();
232:
233: if (nextvol == 1) {
234: tapesread = 0;
235: gettingfile = 0;
236: }
237: if (pipein) {
238: if (nextvol != 1)
239: panic("Changing volumes on pipe input?\n");
240: if (volno == 1)
241: return;
242: goto gethdr;
243: }
244: savecnt = blksread;
245: again:
246: if (pipein)
247: done(1); /* pipes do not get a second chance */
248: if (command == 'R' || command == 'r' || curfile.action != SKIP)
249: newvol = nextvol;
250: else
251: newvol = 0;
252: while (newvol <= 0) {
253: if (tapesread == 0) {
254: fprintf(stderr, "%s%s%s%s%s",
255: "You have not read any tapes yet.\n",
256: "Unless you know which volume your",
257: " file(s) are on you should start\n",
258: "with the last volume and work",
259: " towards towards the first.\n");
260: } else {
261: fprintf(stderr, "You have read volumes");
262: strcpy(tbf, ": ");
263: for (i = 1; i < 32; i++)
264: if (tapesread & (1 << i)) {
265: fprintf(stderr, "%s%d", tbf, i);
266: strcpy(tbf, ", ");
267: }
268: fprintf(stderr, "\n");
269: }
270: do {
271: fprintf(stderr, "Specify next volume #: ");
272: (void) fflush(stderr);
273: (void) fgets(tbf, BUFSIZ, terminal);
274: } while (!feof(terminal) && tbf[0] == '\n');
275: if (feof(terminal))
276: done(1);
277: newvol = atoi(tbf);
278: if (newvol <= 0) {
279: fprintf(stderr,
280: "Volume numbers are positive numerics\n");
281: }
282: }
283: if (newvol == volno) {
284: tapesread |= 1 << volno;
285: return;
286: }
287: closemt();
288: fprintf(stderr, "Mount tape volume %d\n", newvol);
289: fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
290: fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
291: (void) fflush(stderr);
292: (void) fgets(tbf, BUFSIZ, terminal);
293: if (feof(terminal))
294: done(1);
295: if (!strcmp(tbf, "none\n")) {
296: curfile.name = "<name unknown>";
297: curfile.action = UNKNOWN;
298: curfile.dip = (struct dinode *)NIL;
299: curfile.ino = maxino;
300: if (gettingfile) {
301: gettingfile = 0;
302: longjmp(restart, 1);
303: }
304: }
305: if (tbf[0] != '\n') {
306: (void) strcpy(magtape, tbf);
307: magtape[strlen(magtape) - 1] = '\0';
308: }
309: #ifdef RRESTORE
310: if ((mt = rmtopen(magtape, 0)) == -1)
311: #else
312: if ((mt = open(magtape, 0)) == -1)
313: #endif
314: {
315: fprintf(stderr, "Cannot open %s\n", magtape);
316: volno = -1;
317: goto again;
318: }
319: gethdr:
320: volno = newvol;
321: setdumpnum();
322: flsht();
323: if (readhdr(&tmpbuf) == FAIL) {
324: fprintf(stderr, "tape is not dump tape\n");
325: volno = 0;
326: goto again;
327: }
328: if (checkvol(&tmpbuf, volno) == FAIL) {
329: fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
330: volno = 0;
331: goto again;
332: }
333: if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) {
334: fprintf(stderr, "Wrong dump date\n\tgot: %s",
335: ctime(&tmpbuf.c_date));
336: fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
337: volno = 0;
338: goto again;
339: }
340: tapesread |= 1 << volno;
341: blksread = savecnt;
342: if (curfile.action == USING) {
343: if (volno == 1)
344: panic("active file into volume 1\n");
345: return;
346: }
347: /*
348: * Skip up to the beginning of the next record
349: */
350: if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER))
351: for (i = tmpbuf.c_count; i > 0; i--)
352: readtape(buf);
353: (void) gethead(&spcl);
354: findinode(&spcl);
355: if (gettingfile) {
356: gettingfile = 0;
357: longjmp(restart, 1);
358: }
359: }
360:
361: /*
362: * handle multiple dumps per tape by skipping forward to the
363: * appropriate one.
364: */
365: setdumpnum()
366: {
367: struct mtop tcom;
368:
369: if (dumpnum == 1 || volno != 1)
370: return;
371: if (pipein) {
372: fprintf(stderr, "Cannot have multiple dumps on pipe input\n");
373: done(1);
374: }
375: tcom.mt_op = MTFSF;
376: tcom.mt_count = dumpnum - 1;
377: #ifdef RRESTORE
378: rmtioctl(MTFSF, dumpnum - 1);
379: #else
380: if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0)
381: perror("ioctl MTFSF");
382: #endif
383: }
384:
385: printdumpinfo()
386: {
387: extern char *ctime();
388:
389: fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date));
390: fprintf(stdout, "Dumped from: %s",
391: (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&spcl.c_ddate));
392: if (spcl.c_host[0] == '\0')
393: return;
394: fprintf(stderr, "Level %d dump of %s on %s:%s\n",
395: spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev);
396: fprintf(stderr, "Label: %s\n", spcl.c_label);
397: }
398:
399: extractfile(name)
400: char *name;
401: {
402: int mode;
403: struct timeval timep[2];
404: struct entry *ep;
405: extern int xtrlnkfile(), xtrlnkskip();
406: extern int xtrfile(), xtrskip();
407:
408: curfile.name = name;
409: curfile.action = USING;
410: timep[0].tv_sec = curfile.dip->di_atime;
411: timep[0].tv_usec = 0;
412: timep[1].tv_sec = curfile.dip->di_mtime;
413: timep[1].tv_usec = 0;
414: mode = curfile.dip->di_mode;
415: switch (mode & IFMT) {
416:
417: default:
418: fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
419: skipfile();
420: return (FAIL);
421:
422: case IFSOCK:
423: vprintf(stdout, "skipped socket %s\n", name);
424: skipfile();
425: return (GOOD);
426:
427: case IFDIR:
428: if (mflag) {
429: ep = lookupname(name);
430: if (ep == NIL || ep->e_flags & EXTRACT)
431: panic("unextracted directory %s\n", name);
432: skipfile();
433: return (GOOD);
434: }
435: vprintf(stdout, "extract file %s\n", name);
436: return (genliteraldir(name, curfile.ino));
437:
438: case IFLNK:
439: lnkbuf[0] = '\0';
440: pathlen = 0;
441: getfile(xtrlnkfile, xtrlnkskip);
442: if (pathlen == 0) {
443: vprintf(stdout,
444: "%s: zero length symbolic link (ignored)\n", name);
445: return (GOOD);
446: }
447: return (linkit(lnkbuf, name, SYMLINK));
448:
449: case IFCHR:
450: case IFBLK:
451: vprintf(stdout, "extract special file %s\n", name);
452: if (Nflag) {
453: skipfile();
454: return (GOOD);
455: }
456: if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
457: fprintf(stderr, "%s: ", name);
458: (void) fflush(stderr);
459: perror("cannot create special file");
460: skipfile();
461: return (FAIL);
462: }
463: (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
464: (void) chmod(name, mode);
465: skipfile();
466: utimes(name, timep);
467: return (GOOD);
468:
469: case IFREG:
470: vprintf(stdout, "extract file %s\n", name);
471: if (Nflag) {
472: skipfile();
473: return (GOOD);
474: }
475: if ((ofile = creat(name, 0666)) < 0) {
476: fprintf(stderr, "%s: ", name);
477: (void) fflush(stderr);
478: perror("cannot create file");
479: skipfile();
480: return (FAIL);
481: }
482: (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
483: (void) fchmod(ofile, mode);
484: getfile(xtrfile, xtrskip);
485: (void) close(ofile);
486: utimes(name, timep);
487: return (GOOD);
488: }
489: /* NOTREACHED */
490: }
491:
492: /*
493: * skip over bit maps on the tape
494: */
495: skipmaps()
496: {
497:
498: while (checktype(&spcl, TS_CLRI) == GOOD ||
499: checktype(&spcl, TS_BITS) == GOOD)
500: skipfile();
501: }
502:
503: /*
504: * skip over a file on the tape
505: */
506: skipfile()
507: {
508: extern int null();
509:
510: curfile.action = SKIP;
511: getfile(null, null);
512: }
513:
514: /*
515: * Do the file extraction, calling the supplied functions
516: * with the blocks
517: */
518: getfile(f1, f2)
519: int (*f2)(), (*f1)();
520: {
521: register int i;
522: int curblk = 0;
523: off_t size = spcl.c_dinode.di_size;
524: static char clearedbuf[MAXBSIZE];
525: char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
526: char junk[TP_BSIZE];
527:
528: if (checktype(&spcl, TS_END) == GOOD)
529: panic("ran off end of tape\n");
530: if (ishead(&spcl) == FAIL)
531: panic("not at beginning of a file\n");
532: if (!gettingfile && setjmp(restart) != 0)
533: return;
534: gettingfile++;
535: loop:
536: for (i = 0; i < spcl.c_count; i++) {
537: if (spcl.c_addr[i]) {
538: readtape(&buf[curblk++][0]);
539: if (curblk == fssize / TP_BSIZE) {
540: (*f1)(buf, size > TP_BSIZE ?
541: (long) (fssize) :
542: (curblk - 1) * TP_BSIZE + size);
543: curblk = 0;
544: }
545: } else {
546: if (curblk > 0) {
547: (*f1)(buf, size > TP_BSIZE ?
548: (long) (curblk * TP_BSIZE) :
549: (curblk - 1) * TP_BSIZE + size);
550: curblk = 0;
551: }
552: (*f2)(clearedbuf, size > TP_BSIZE ?
553: (long) TP_BSIZE : size);
554: }
555: if ((size -= TP_BSIZE) <= 0) {
556: for (i++; i < spcl.c_count; i++)
557: if (spcl.c_addr[i])
558: readtape(junk);
559: break;
560: }
561: }
562: if (readhdr(&spcl) == GOOD && size > 0) {
563: if (checktype(&spcl, TS_ADDR) == GOOD)
564: goto loop;
565: dprintf(stdout, "Missing address (header) block for %s\n",
566: curfile.name);
567: }
568: if (curblk > 0)
569: (*f1)(buf, (curblk * TP_BSIZE) + size);
570: findinode(&spcl);
571: gettingfile = 0;
572: }
573:
574: /*
575: * The next routines are called during file extraction to
576: * put the data into the right form and place.
577: */
578: xtrfile(buf, size)
579: char *buf;
580: long size;
581: {
582:
583: if (Nflag)
584: return;
585: if (write(ofile, buf, (int) size) == -1) {
586: fprintf(stderr, "write error extracting inode %d, name %s\n",
587: curfile.ino, curfile.name);
588: perror("write");
589: done(1);
590: }
591: }
592:
593: xtrskip(buf, size)
594: char *buf;
595: long size;
596: {
597:
598: #ifdef lint
599: buf = buf;
600: #endif
601: if (lseek(ofile, size, 1) == (long)-1) {
602: fprintf(stderr, "seek error extracting inode %d, name %s\n",
603: curfile.ino, curfile.name);
604: perror("lseek");
605: done(1);
606: }
607: }
608:
609: xtrlnkfile(buf, size)
610: char *buf;
611: long size;
612: {
613:
614: pathlen += size;
615: if (pathlen > MAXPATHLEN) {
616: fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n",
617: curfile.name, lnkbuf, buf, pathlen);
618: done(1);
619: }
620: (void) strcat(lnkbuf, buf);
621: }
622:
623: xtrlnkskip(buf, size)
624: char *buf;
625: long size;
626: {
627:
628: #ifdef lint
629: buf = buf, size = size;
630: #endif
631: fprintf(stderr, "unallocated block in symbolic link %s\n",
632: curfile.name);
633: done(1);
634: }
635:
636: xtrmap(buf, size)
637: char *buf;
638: long size;
639: {
640:
641: bcopy(buf, map, size);
642: map += size;
643: }
644:
645: xtrmapskip(buf, size)
646: char *buf;
647: long size;
648: {
649:
650: #ifdef lint
651: buf = buf;
652: #endif
653: panic("hole in map\n");
654: map += size;
655: }
656:
657: null() {;}
658:
659: /*
660: * Do the tape i/o, dealing with volume changes
661: * etc..
662: */
663: readtape(b)
664: char *b;
665: {
666: register long i;
667: long rd, newvol;
668: int cnt;
669:
670: if (bct < ntrec) {
671: bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
672: blksread++;
673: return;
674: }
675: for (i = 0; i < ntrec; i++)
676: ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
677: bct = 0;
678: cnt = ntrec*TP_BSIZE;
679: rd = 0;
680: getmore:
681: #ifdef RRESTORE
682: i = rmtread(&tbf[rd], cnt);
683: #else
684: i = read(mt, &tbf[rd], cnt);
685: #endif
686: if (i > 0 && i != ntrec*TP_BSIZE) {
687: if (pipein) {
688: rd += i;
689: cnt -= i;
690: if (cnt > 0)
691: goto getmore;
692: i = rd;
693: } else {
694: if (i % TP_BSIZE != 0)
695: panic("partial block read: %d should be %d\n",
696: i, ntrec * TP_BSIZE);
697: bcopy((char *)&endoftapemark, &tbf[i],
698: (long)TP_BSIZE);
699: }
700: }
701: if (i < 0) {
702: fprintf(stderr, "Tape read error while ");
703: switch (curfile.action) {
704: default:
705: fprintf(stderr, "trying to set up tape\n");
706: break;
707: case UNKNOWN:
708: fprintf(stderr, "trying to resynchronize\n");
709: break;
710: case USING:
711: fprintf(stderr, "restoring %s\n", curfile.name);
712: break;
713: case SKIP:
714: fprintf(stderr, "skipping over inode %d\n",
715: curfile.ino);
716: break;
717: }
718: if (!yflag && !reply("continue"))
719: done(1);
720: i = ntrec*TP_BSIZE;
721: bzero(tbf, i);
722: #ifdef RRESTORE
723: if (rmtseek(i, 1) < 0)
724: #else
725: if (lseek(mt, i, 1) == (long)-1)
726: #endif
727: {
728: perror("continuation failed");
729: done(1);
730: }
731: }
732: if (i == 0) {
733: if (!pipein) {
734: newvol = volno + 1;
735: volno = 0;
736: getvol(newvol);
737: readtape(b);
738: return;
739: }
740: if (rd % TP_BSIZE != 0)
741: panic("partial block read: %d should be %d\n",
742: rd, ntrec * TP_BSIZE);
743: bcopy((char *)&endoftapemark, &tbf[rd], (long)TP_BSIZE);
744: }
745: bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
746: blksread++;
747: }
748:
749: findtapeblksize()
750: {
751: register long i;
752:
753: for (i = 0; i < ntrec; i++)
754: ((struct s_spcl *)&tbf[i * TP_BSIZE])->c_magic = 0;
755: bct = 0;
756: #ifdef RRESTORE
757: i = rmtread(tbf, ntrec * TP_BSIZE);
758: #else
759: i = read(mt, tbf, ntrec * TP_BSIZE);
760: #endif
761: if (i <= 0) {
762: perror("Tape read error");
763: done(1);
764: }
765: if (i % TP_BSIZE != 0) {
766: fprintf(stderr, "Tape block size (%d) %s (%d)\n",
767: i, "is not a multiple of dump block size", TP_BSIZE);
768: done(1);
769: }
770: ntrec = i / TP_BSIZE;
771: vprintf(stdout, "Tape block size is %d\n", ntrec);
772: }
773:
774: flsht()
775: {
776:
777: bct = ntrec+1;
778: }
779:
780: closemt()
781: {
782: if (mt < 0)
783: return;
784: #ifdef RRESTORE
785: rmtclose();
786: #else
787: (void) close(mt);
788: #endif
789: }
790:
791: checkvol(b, t)
792: struct s_spcl *b;
793: long t;
794: {
795:
796: if (b->c_volume != t)
797: return(FAIL);
798: return(GOOD);
799: }
800:
801: readhdr(b)
802: struct s_spcl *b;
803: {
804:
805: if (gethead(b) == FAIL) {
806: dprintf(stdout, "readhdr fails at %d blocks\n", blksread);
807: return(FAIL);
808: }
809: return(GOOD);
810: }
811:
812: /*
813: * read the tape into buf, then return whether or
814: * or not it is a header block.
815: */
816: gethead(buf)
817: struct s_spcl *buf;
818: {
819: long i;
820: u_long *j;
821: union u_ospcl {
822: char dummy[TP_BSIZE];
823: struct s_ospcl {
824: long c_type;
825: long c_date;
826: long c_ddate;
827: long c_volume;
828: long c_tapea;
829: u_short c_inumber;
830: long c_magic;
831: long c_checksum;
832: struct odinode {
833: unsigned short odi_mode;
834: u_short odi_nlink;
835: u_short odi_uid;
836: u_short odi_gid;
837: long odi_size;
838: long odi_rdev;
839: char odi_addr[36];
840: long odi_atime;
841: long odi_mtime;
842: long odi_ctime;
843: } c_dinode;
844: long c_count;
845: char c_addr[256];
846: } s_ospcl;
847: } u_ospcl;
848:
849: if (!cvtflag) {
850: readtape((char *)buf);
851: if (buf->c_magic != NFS_MAGIC) {
852: if (swabl(buf->c_magic) != NFS_MAGIC)
853: return (FAIL);
854: if (!Bcvt) {
855: vprintf(stdout, "Note: Doing Byte swapping\n");
856: Bcvt = 1;
857: }
858: }
859: if (checksum((int *)buf) == FAIL)
860: return (FAIL);
861: if (Bcvt)
862: swabst("8l4s31l", (char *)buf);
863: goto good;
864: }
865: readtape((char *)(&u_ospcl.s_ospcl));
866: bzero((char *)buf, (long)TP_BSIZE);
867: buf->c_type = u_ospcl.s_ospcl.c_type;
868: buf->c_date = u_ospcl.s_ospcl.c_date;
869: buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
870: buf->c_volume = u_ospcl.s_ospcl.c_volume;
871: buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
872: buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
873: buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
874: buf->c_magic = u_ospcl.s_ospcl.c_magic;
875: buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
876: buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
877: buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
878: buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
879: buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
880: buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
881: buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
882: buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
883: buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
884: buf->c_count = u_ospcl.s_ospcl.c_count;
885: bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, (long)256);
886: if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
887: checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)
888: return(FAIL);
889: buf->c_magic = NFS_MAGIC;
890:
891: good:
892: j = buf->c_dinode.di_qsize.val;
893: i = j[1];
894: if (buf->c_dinode.di_size == 0 &&
895: (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt==0) {
896: if (*j || i) {
897: printf("Note: Doing Quad swapping\n");
898: Qcvt = 1;
899: }
900: }
901: if (Qcvt) {
902: j[1] = *j; *j = i;
903: }
904: switch (buf->c_type) {
905:
906: case TS_CLRI:
907: case TS_BITS:
908: /*
909: * Have to patch up missing information in bit map headers
910: */
911: buf->c_inumber = 0;
912: buf->c_dinode.di_size = buf->c_count * TP_BSIZE;
913: for (i = 0; i < buf->c_count; i++)
914: buf->c_addr[i]++;
915: break;
916:
917: case TS_TAPE:
918: case TS_END:
919: buf->c_inumber = 0;
920: break;
921:
922: case TS_INODE:
923: case TS_ADDR:
924: break;
925:
926: default:
927: panic("gethead: unknown inode type %d\n", buf->c_type);
928: break;
929: }
930: if (dflag)
931: accthdr(buf);
932: return(GOOD);
933: }
934:
935: /*
936: * Check that a header is where it belongs and predict the next header
937: */
938: accthdr(header)
939: struct s_spcl *header;
940: {
941: static ino_t previno = 0x7fffffff;
942: static int prevtype;
943: static long predict;
944: long blks, i;
945:
946: if (header->c_type == TS_TAPE) {
947: fprintf(stderr, "Volume header\n");
948: previno = 0x7fffffff;
949: return;
950: }
951: if (previno == 0x7fffffff)
952: goto newcalc;
953: switch (prevtype) {
954: case TS_BITS:
955: fprintf(stderr, "Dump mask header");
956: break;
957: case TS_CLRI:
958: fprintf(stderr, "Remove mask header");
959: break;
960: case TS_INODE:
961: fprintf(stderr, "File header, ino %d", previno);
962: break;
963: case TS_ADDR:
964: fprintf(stderr, "File continuation header, ino %d", previno);
965: break;
966: case TS_END:
967: fprintf(stderr, "End of tape header");
968: break;
969: }
970: if (predict != blksread - 1)
971: fprintf(stderr, "; predicted %d blocks, got %d blocks",
972: predict, blksread - 1);
973: fprintf(stderr, "\n");
974: newcalc:
975: blks = 0;
976: if (header->c_type != TS_END)
977: for (i = 0; i < header->c_count; i++)
978: if (header->c_addr[i] != 0)
979: blks++;
980: predict = blks;
981: blksread = 0;
982: prevtype = header->c_type;
983: previno = header->c_inumber;
984: }
985:
986: /*
987: * Find an inode header.
988: * Complain if had to skip, and complain is set.
989: */
990: findinode(header)
991: struct s_spcl *header;
992: {
993: static long skipcnt = 0;
994: long i;
995: char buf[TP_BSIZE];
996:
997: curfile.name = "<name unknown>";
998: curfile.action = UNKNOWN;
999: curfile.dip = (struct dinode *)NIL;
1000: curfile.ino = 0;
1001: if (ishead(header) == FAIL) {
1002: skipcnt++;
1003: while (gethead(header) == FAIL || header->c_date != dumpdate)
1004: skipcnt++;
1005: }
1006: for (;;) {
1007: if (checktype(header, TS_ADDR) == GOOD) {
1008: /*
1009: * Skip up to the beginning of the next record
1010: */
1011: for (i = 0; i < header->c_count; i++)
1012: if (header->c_addr[i])
1013: readtape(buf);
1014: (void) gethead(header);
1015: continue;
1016: }
1017: if (checktype(header, TS_INODE) == GOOD) {
1018: curfile.dip = &header->c_dinode;
1019: curfile.ino = header->c_inumber;
1020: break;
1021: }
1022: if (checktype(header, TS_END) == GOOD) {
1023: curfile.ino = maxino;
1024: break;
1025: }
1026: if (checktype(header, TS_CLRI) == GOOD) {
1027: curfile.name = "<file removal list>";
1028: break;
1029: }
1030: if (checktype(header, TS_BITS) == GOOD) {
1031: curfile.name = "<file dump list>";
1032: break;
1033: }
1034: while (gethead(header) == FAIL)
1035: skipcnt++;
1036: }
1037: if (skipcnt > 0)
1038: fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt);
1039: skipcnt = 0;
1040: }
1041:
1042: /*
1043: * return whether or not the buffer contains a header block
1044: */
1045: ishead(buf)
1046: struct s_spcl *buf;
1047: {
1048:
1049: if (buf->c_magic != NFS_MAGIC)
1050: return(FAIL);
1051: return(GOOD);
1052: }
1053:
1054: checktype(b, t)
1055: struct s_spcl *b;
1056: int t;
1057: {
1058:
1059: if (b->c_type != t)
1060: return(FAIL);
1061: return(GOOD);
1062: }
1063:
1064: checksum(b)
1065: register int *b;
1066: {
1067: register int i, j;
1068:
1069: j = sizeof(union u_spcl) / sizeof(int);
1070: i = 0;
1071: if(!Bcvt) {
1072: do
1073: i += *b++;
1074: while (--j);
1075: } else {
1076: /* What happens if we want to read restore tapes
1077: for a 16bit int machine??? */
1078: do
1079: i += swabl(*b++);
1080: while (--j);
1081: }
1082:
1083: if (i != CHECKSUM) {
1084: fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,
1085: curfile.ino, curfile.name);
1086: return(FAIL);
1087: }
1088: return(GOOD);
1089: }
1090:
1091: #ifdef RRESTORE
1092: /* VARARGS1 */
1093: msg(cp, a1, a2, a3)
1094: char *cp;
1095: {
1096:
1097: fprintf(stderr, cp, a1, a2, a3);
1098: }
1099: #endif RRESTORE
1100:
1101: swabst(cp, sp)
1102: register char *cp, *sp;
1103: {
1104: int n = 0;
1105: char c;
1106: while(*cp) {
1107: switch (*cp) {
1108: case '0': case '1': case '2': case '3': case '4':
1109: case '5': case '6': case '7': case '8': case '9':
1110: n = (n * 10) + (*cp++ - '0');
1111: continue;
1112:
1113: case 's': case 'w': case 'h':
1114: c = sp[0]; sp[0] = sp[1]; sp[1] = c;
1115: sp++;
1116: break;
1117:
1118: case 'l':
1119: c = sp[0]; sp[0] = sp[3]; sp[3] = c;
1120: c = sp[2]; sp[2] = sp[1]; sp[1] = c;
1121: sp += 3;
1122: }
1123: sp++; /* Any other character, like 'b' counts as byte. */
1124: if (n <= 1) {
1125: n = 0; cp++;
1126: } else
1127: n--;
1128: }
1129: }
1130: swabl(x) { unsigned long l = x; swabst("l", (char *)&l); return l; }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.