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