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