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