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

Defined functions

accthdr defined in line 877; used 1 times
checksum defined in line 991; used 2 times
checktype defined in line 981; used 10 times
checkvol defined in line 731; used 2 times
closemt defined in line 720; used 2 times
extractfile defined in line 351; used 2 times
findinode defined in line 928; used 3 times
findtapeblksize defined in line 689; used 1 times
flsht defined in line 714; used 3 times
getfile defined in line 460; used 6 times
gethead defined in line 756; used 6 times
getvol defined in line 208; used 4 times
ishead defined in line 972; used 2 times
msg defined in line 1020; used 1 times
  • in line 59
newtapebuf defined in line 88; used 3 times
null defined in line 597; used 5 times
readhdr defined in line 741; used 3 times
readtape defined in line 603; used 5 times
setdumpnum defined in line 331; used 2 times
setinput defined in line 41; used 1 times
setup defined in line 110; used 4 times
skipfile defined in line 448; used 10 times
skipmaps defined in line 437; used 6 times
swabl defined in line 1057; used 2 times
swabst defined in line 1028; used 3 times
xtrfile defined in line 520; used 2 times
xtrlnkfile defined in line 549; used 2 times
xtrlnkskip defined in line 563; used 2 times
xtrmap defined in line 576; used 3 times
xtrmapskip defined in line 585; used 3 times
xtrskip defined in line 533; used 2 times

Defined variables

Bcvt defined in line 36; used 4 times
Qcvt defined in line 37; used 3 times
bct defined in line 23; used 7 times
blksread defined in line 26; used 8 times
endoftapemark defined in line 25; used 6 times
fssize defined in line 19; used 6 times
gettingfile defined in line 29; used 6 times
lnkbuf defined in line 33; used 4 times
magtape defined in line 22; used 12 times
map defined in line 32; used 9 times
mt defined in line 20; used 11 times
ofile defined in line 31; used 6 times
pathlen defined in line 34; used 5 times
pipein defined in line 21; used 9 times
restart defined in line 28; used 2 times
sccsid defined in line 8; never used
tapesread defined in line 27; used 5 times
tbf defined in line 24; used 24 times

Defined struct's

odinode defined in line 771; never used
s_ospcl defined in line 762; never used

Defined union's

u_ospcl defined in line 760; never used

Defined macros

tmpbuf defined in line 214; used 6 times
Last modified: 1986-05-02
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3322
Valid CSS Valid XHTML 1.0 Strict