1: /*
   2:  *
   3:  *  Title:
   4:  *	Backup
   5:  *
   6:  *  Decription:
   7:  *	Program to read VMS backup tape
   8:  *
   9:  *  Author:
  10:  *	John Douglas CAREY.
  11:  *	Sven-Ove Westberg    (version 3.0)
  12:  *
  13:  *  Net-addess:
  14:  *	john%monu1.oz@seismo.ARPA
  15:  *	luthcad!sow@enea.UUCP
  16:  *
  17:  *  History:
  18:  *	Version 1.0 - September 1984
  19:  *		Can only read variable length records
  20:  *	Version 1.1
  21:  *		Cleaned up the program from the original hack
  22:  *		Can now read stream files
  23:  *	Version 1.2
  24:  *		Now convert filename from VMS to UNIX
  25:  *			and creates sub-directories
  26:  *	Version 1.3
  27:  *		Works on the Pyramid if SWAP is defined
  28:  *	Version 1.4
  29:  *		Reads files spanning multiple tape blocks
  30:  *	Version 1.5
  31:  *		Always reset reclen = 0 on file open
  32:  *		Now output fixed length records
  33:  *
  34:  *      Version 2.0 - July 1985
  35:  *		VMS Version 4.0 causes a rethink !!
  36:  *		Now use mtio operations instead of opening and closing file
  37:  *		Blocksize now grabed from the label
  38:  *
  39:  *	Version 2.1 - September 1985
  40:  *		Handle variable length records of zero length.
  41:  *
  42:  *	Version 2.2 - July 1986
  43:  *		Handle FORTRAN records of zero length.
  44:  *		Inserted exit(0) at end of program.
  45:  *		Distributed program in aus.sources
  46:  *
  47:  *	Version 2.3 - August 1986
  48:  *		Handle FORTRAN records with record length fields
  49:  *		at the end of a block
  50:  *		Put debug output to a file.
  51:  *		Distributed program in net.sources
  52:  *
  53:  *	Version 3.0 - December 1986
  54:  *		Handle multiple saveset
  55:  *		Remote tape
  56:  *		Interactive mode
  57:  *		File name selection with meta-characters
  58:  *		Convert ; to : in VMS filenames
  59:  *		Flag for usage of VMS directory structure
  60:  *		Flag for "useless" files  eg. *.exe
  61:  *		Flag for use VMS version in file names
  62:  *		Flag for verbose mode
  63:  *		Flag to list the contents of the tape
  64:  *		Distributed to mod.sources
  65:  *
  66:  *
  67:  *  Installation:
  68:  *
  69:  *	Computer Centre
  70:  *	Monash University
  71:  *	Wellington Road
  72:  *	Clayton
  73:  *	Victoria	3168
  74:  *	AUSTRALIA
  75:  *
  76:  */
  77: #include    <stdio.h>
  78: #include    <ctype.h>
  79: 
  80: #include    <sys/ioctl.h>
  81: #include    <sys/types.h>
  82: #ifdef REMOTE
  83: #include    <local/rmt.h>
  84: #include    <sys/stat.h>
  85: #endif
  86: #include    <sys/mtio.h>
  87: #include    <sys/file.h>
  88: 
  89: #ifdef pyr
  90: #define SWAP
  91: #endif pyr
  92: 
  93: #ifdef sun
  94: #define SWAP
  95: #endif
  96: 
  97: #ifdef  pdp11
  98: #define bbh_dol_w_size _bdwopsize
  99: #define bbh_dol_w_opsys _bdwopsys
 100: #define bbh_dol_w_subsys _bdwsubsys
 101: #define bbh_dol_w_applic _bdwapplic
 102: #define bbh_dol_l_number _bdlnumber
 103: #define bbh_dol_t_spare_1 _bdtsp1
 104: #define bbh_dol_w_struclev _bdwstruclev
 105: #define bbh_dol_w_volnum _bdwvolnum
 106: #define bbh_dol_l_crc _bdlcrc
 107: #define bbh_dol_l_blocksize _bdlblocksize
 108: #define bbh_dol_l_flags _bdlflags
 109: #define bbh_dol_t_ssname _bdtssname
 110: #define bbh_dol_w_fid _bdwfid
 111: #define bbh_dol_w_did _bdwdid
 112: #define bbh_dol_t_filename _bdtfilename
 113: #define bbh_dol_b_rtype _bdbrtype
 114: #define bbh_dol_b_rattrib _bdbrattrib
 115: #define bbh_dol_w_rsize _bdwrsize
 116: #define bbh_dol_b_bktsize _bdbbktsize
 117: #define bbh_dol_b_vfcsize _bdbvfcsize
 118: #define bbh_dol_w_maxrec _bdwmaxrec
 119: #define bbh_dol_l_filesize _bdlfilesize
 120: #define bbh_dol_t_spare_2 _bdtsp2
 121: #define bbh_dol_w_checksum _bdwchecksum
 122: 
 123: #define brh_dol_w_rsize _bhdwrsize
 124: #define brh_dol_w_rtype _bhwrtyppe
 125: #define brh_dol_l_flags _bhlflags
 126: #define brh_dol_l_address _bhladdress
 127: #define brh_dol_l_spare _bhlspare
 128: 
 129: #define bsa_dol_w_size _bawsize
 130: #define bsa_dol_w_type _bawtype
 131: #define bsa_dol_t_text _battext
 132: 
 133: #define process_file __procf
 134: #define process_vbn __procv
 135: #endif
 136: 
 137: struct bbh {
 138:     short   bbh_dol_w_size;
 139:     short   bbh_dol_w_opsys;
 140:     short   bbh_dol_w_subsys;
 141:     short   bbh_dol_w_applic;
 142:     long    bbh_dol_l_number;
 143:     char    bbh_dol_t_spare_1[20];
 144:     short   bbh_dol_w_struclev;
 145:     short   bbh_dol_w_volnum;
 146:     long    bbh_dol_l_crc;
 147:     long    bbh_dol_l_blocksize;
 148:     long    bbh_dol_l_flags;
 149:     char    bbh_dol_t_ssname[32];
 150:     short   bbh_dol_w_fid[3];
 151:     short   bbh_dol_w_did[3];
 152:     char    bbh_dol_t_filename[128];
 153:     char    bbh_dol_b_rtype;
 154:     char    bbh_dol_b_rattrib;
 155:     short   bbh_dol_w_rsize;
 156:     char    bbh_dol_b_bktsize;
 157:     char    bbh_dol_b_vfcsize;
 158:     short   bbh_dol_w_maxrec;
 159:     long    bbh_dol_l_filesize;
 160:     char    bbh_dol_t_spare_2[22];
 161:     short   bbh_dol_w_checksum;
 162: } *block_header;
 163: 
 164: struct brh {
 165:     short   brh_dol_w_rsize;
 166:     short   brh_dol_w_rtype;
 167:     long    brh_dol_l_flags;
 168:     long    brh_dol_l_address;
 169:     long    brh_dol_l_spare;
 170: } *record_header;
 171: 
 172: /* define record types */
 173: 
 174: #define brh_dol_k_null  0
 175: #define brh_dol_k_summary   1
 176: #define brh_dol_k_volume    2
 177: #define brh_dol_k_file  3
 178: #define brh_dol_k_vbn   4
 179: #define brh_dol_k_physvol   5
 180: #define brh_dol_k_lbn   6
 181: #define brh_dol_k_fid   7
 182: 
 183: struct bsa {
 184:     short   bsa_dol_w_size;
 185:     short   bsa_dol_w_type;
 186:     char    bsa_dol_t_text[1];
 187: } *data_item;
 188: 
 189: #ifdef  STREAM
 190: char    *def_tapefile = "/dev/rts8";
 191: #else
 192: char    *def_tapefile = "/dev/rmt8";
 193: #endif
 194: char    *tapefile;
 195: 
 196: char    filename[128];
 197: int filesize;
 198: 
 199: char    recfmt;     /* record format */
 200: 
 201: #define         FAB_dol_C_UDF   0   /* undefined */
 202: #define         FAB_dol_C_FIX   1   /* fixed-length record */
 203: #define         FAB_dol_C_VAR   2   /* variable-length record */
 204: #define         FAB_dol_C_VFC   3   /* variable-length with fixed-length control record */
 205: #define         FAB_dol_C_STM   4   /* RMS-11 stream record (valid only for sequential org) */
 206: #define         FAB_dol_C_STMLF 5   /* stream record delimited by LF (sequential org only) */
 207: #define         FAB_dol_C_STMCR 6   /* stream record delimited by CR (sequential org only) */
 208: #define         FAB_dol_C_MAXRFM    6   /* maximum rfm supported */
 209: 
 210: char    recatt;     /* record attributes */
 211: 
 212: #define         FAB_dol_V_FTN   0   /* FORTRAN carriage control character */
 213: #define         FAB_dol_V_CR    1   /* line feed - record -carriage return */
 214: #define         FAB_dol_V_PRN   2   /* print-file carriage control */
 215: #define         FAB_dol_V_BLK   3   /* records don't cross block boundaries */
 216: 
 217: #define FANO    20
 218: 
 219: #ifdef  pyr
 220: static struct   bsa *file_table[FANO];
 221: #else
 222: struct  bsa *file_table[FANO];
 223: #endif
 224: 
 225: FILE    *f  = NULL;
 226: int file_count;
 227: short   reclen;
 228: short   fix;
 229: short   recsize;
 230: int vfcsize;
 231: 
 232: #ifdef  NEWD
 233: FILE    *lf;
 234: #endif	NEWD
 235: 
 236: int fd;     /* tape file descriptor */
 237: int     cflag, dflag, eflag, iflag, sflag, tflag, vflag, wflag, xflag, nflag;
 238: int setnr;
 239: char    **gargv;
 240: int     goptind, gargc;
 241: 
 242: #define LABEL_SIZE  80
 243: char    label[LABEL_SIZE];
 244: 
 245: char    *block;
 246: int blocksize;
 247: 
 248: struct  mtop    op;
 249: 
 250: FILE *
 251: openfile(fn)
 252: char    *fn;
 253: {
 254:     char    ufn[256];
 255:     char    ans[80];
 256:     char    *p, *q, s, *ext;
 257:     int procf;
 258: 
 259:     procf = 1;
 260:     /* copy fn to ufn and convert to lower case */
 261:     p = fn;
 262:     q = ufn;
 263:     while (*p) {
 264:         if (isupper(*p))
 265:             *q = *p - 'A' + 'a';
 266:         else
 267:             *q = *p;
 268:         p++;
 269:         q++;
 270:     }
 271:     *q = '\0';
 272: 
 273:     /* convert the VMS to UNIX and make the directory path */
 274:     p = ufn;
 275:     q = ++p;
 276:     while (*q) {
 277:         if (*q == '.' || *q == ']') {
 278:             s = *q;
 279:             *q = '\0';
 280:             if(procf && dflag) mkdir(p, 0777);
 281:             *q = '/';
 282:             if (s == ']')
 283:                 break;
 284:         }
 285:         *q++;
 286:     }
 287:     *q++;
 288:     if(!dflag) p=q;
 289:     /* strip off the version number */
 290:     while (*q && *q != ';') {
 291:         if( *q == '.') ext = q;
 292:         q++;
 293:     }
 294:     if (cflag) {
 295:         *q = ':';
 296:     }
 297:     else {
 298:         *q = '\0';
 299:     }
 300:     if(!eflag && procf) procf = typecmp(++ext);
 301:     if(procf && wflag) {
 302:         printf("extract %s [ny]",filename);
 303:         fflush(stdout);
 304:         gets(ans);
 305:         if(*ans != 'y') procf = NULL;
 306:     }
 307:     if(procf)
 308:         /* open the file for writing */
 309:         return(fopen(p, "w"));
 310:     else
 311:         return(NULL);
 312: }
 313: 
 314: typecmp(str)    /* Compare the filename type in str with our list
 315:                    of file type to be ignored.  Return 0 if the
 316:                    file is to be ignored, return 1 if the
 317:                    file is not in our list and should not be ignored. */
 318: register char   *str;
 319: {
 320:         static char *type[] = {
 321:                 "exe",          /* vms executable image */
 322:                 "lib",          /* vms object library */
 323:                 "obj",          /* rsx object file */
 324:                 "odl",          /* rsx overlay description file */
 325:                 "olb",          /* rsx object library */
 326:                 "pmd",          /* rsx post mortem dump */
 327:                 "stb",          /* rsx symbol table */
 328:                 "sys",          /* rsx bootable system image */
 329:                 "tsk",          /* rsx executable image */
 330:         "dir",
 331:         "upd",
 332:         "tlo",
 333:         "tlb",
 334:                 ""              /* null string terminates list */
 335:         };
 336:         register int    i;
 337: 
 338:         i = -1;
 339:         while (*type[++i])
 340:                 if (strncmp(str, type[i],3) == 0)
 341:                         return(0);      /* found a match, file to be ignored */
 342:         return(1);                      /* no match found */
 343: }
 344: 
 345: process_file(buffer)
 346: char    *buffer;
 347: {
 348:     int i, n;
 349:     char    *p, *q;
 350:     short   dsize, nblk, lnch;
 351: 
 352:     int c;
 353:     short   *s;
 354: 
 355:     int     procf;
 356: 
 357:     s = (short *) buffer;
 358: 
 359:     /* check the header word */
 360:     if (*s != 257) {
 361:         printf("Snark: invalid data header\n");
 362:         exit(1);
 363:     }
 364: 
 365:     c = 2;
 366:     for (i = 0; i < FANO; i++) {
 367:         file_table[i] = (struct bsa *) &buffer[c];
 368: #ifndef SWAP
 369:         dsize = file_table[i]->bsa_dol_w_size;
 370: #else
 371:         swap(&file_table[i]->bsa_dol_w_size, &dsize, sizeof(short));
 372: #endif
 373:         c += dsize + 4;
 374:     }
 375: 
 376:     /* extract file name */
 377: #ifndef SWAP
 378:     dsize = file_table[0]->bsa_dol_w_size;
 379: #else
 380:     swap(&file_table[0]->bsa_dol_w_size, &dsize, sizeof(short));
 381: #endif
 382:     p = file_table[0]->bsa_dol_t_text;
 383:     q = filename;
 384:     for (i = 0; i < dsize; i++)
 385:         *q++ = *p++;
 386:     *q = '\0';
 387: 
 388:     /* extract file's record attributes */
 389: #ifndef SWAP
 390:     dsize = file_table[5]->bsa_dol_w_size;
 391: #else
 392:     swap(&file_table[5]->bsa_dol_w_size, &dsize, sizeof(short));
 393: #endif
 394:     p = file_table[5]->bsa_dol_t_text;
 395:     recfmt = p[0];
 396:     recatt = p[1];
 397: #ifndef SWAP
 398:     bcopy(&p[2], &recsize, sizeof(short));
 399: #else
 400:     swap(&p[2], &recsize, sizeof(short));
 401: #endif
 402:     vfcsize = p[15];
 403:     if (vfcsize == 0)
 404:         vfcsize = 2;
 405: #ifdef  DEBUG
 406:     printf("recfmt = %d\n", recfmt);
 407:     printf("recatt = %d\n", recatt);
 408:     printf("reclen = %d\n", recsize);
 409:     printf("vfcsize = %d\n", vfcsize);
 410: #endif
 411: #ifndef SWAP
 412:     bcopy(&p[10], &nblk, sizeof(short));
 413:     bcopy(&p[12], &lnch, sizeof(short));
 414: #else
 415:     swap(&p[10], &nblk, sizeof(short));
 416:     swap(&p[12], &lnch, sizeof(short));
 417: #endif
 418:     filesize = (nblk-1)*512 + lnch;
 419: #ifdef DEBUG
 420:     printf("nbk = %d, lnch = %d\n", nblk, lnch);
 421:     printf("filesize = 0x%x\n", filesize);
 422: #endif
 423: 
 424:     /* open the file */
 425:     if (f != NULL) {
 426:         fclose(f);
 427:         file_count = 0;
 428:         reclen = 0;
 429:     }
 430:     procf = 0;
 431:     if (goptind < gargc)
 432:         for(i=goptind; i < gargc; i++) {
 433:             procf |= match(filename,gargv[i]);
 434:         }
 435:     else
 436:         procf = 1;
 437:     if (tflag && procf)
 438:         printf( " %-35s %8d \n",filename,filesize);
 439:     if (xflag && procf) {
 440:         /* open file */
 441:         f = openfile(filename);
 442:         if(f != NULL && vflag) printf("extracting %s\n", filename);
 443:     }
 444: }
 445: /*
 446:  *
 447:  *  process a virtual block record (file record)
 448:  *
 449:  */
 450: process_vbn(buffer, rsize)
 451: char        *buffer;
 452: unsigned short  rsize;
 453: {
 454:     int c, i;
 455: 
 456:     if (f == NULL) {
 457:         return;
 458:     }
 459:     i = 0;
 460:     while (file_count+i < filesize && i < rsize) {
 461:         switch (recfmt) {
 462:         case FAB_dol_C_FIX:
 463:             if (reclen == 0) {
 464:                 reclen = recsize;
 465:             }
 466:             fputc(buffer[i], f);
 467:             i++;
 468:             reclen--;
 469:             break;
 470: 
 471:         case FAB_dol_C_VAR:
 472:         case FAB_dol_C_VFC:
 473:             if (reclen == 0) {
 474:                 reclen = *((short *) &buffer[i]);
 475: #ifdef  SWAP
 476:                 swap(&reclen, &reclen, sizeof(short));
 477: #endif
 478: #ifdef  NEWD
 479:                 fprintf(lf, "---\n");
 480:                 fprintf(lf, "reclen = %d\n", reclen);
 481:                 fprintf(lf, "i = %d\n", i);
 482:                 fprintf(lf, "rsize = %d\n", rsize);
 483: #endif	NEWD
 484:                 fix = reclen;
 485:                 i += 2;
 486:                 if (recfmt == FAB_dol_C_VFC) {
 487:                     i += vfcsize;
 488:                     reclen -= vfcsize;
 489:                 }
 490:             } else if (reclen == fix
 491:                     && recatt == (1 << FAB_dol_V_FTN)) {
 492:                     /****
 493: 					if (buffer[i] == '0')
 494: 						fputc('\n', f);
 495: 					else if (buffer[i] == '1')
 496: 						fputc('\f', f);
 497: 					*** sow ***/
 498:                     fputc(buffer[i],f); /** sow **/
 499:                     i++;
 500:                     reclen--;
 501:             } else {
 502:                 fputc(buffer[i], f);
 503:                 i++;
 504:                 reclen--;
 505:             }
 506:             if (reclen == 0) {
 507:                 if (!nflag)
 508:                     fputc('\n', f);
 509:                 if (i & 1)
 510:                     i++;
 511:             }
 512:             break;
 513: 
 514:         case FAB_dol_C_STM:
 515:         case FAB_dol_C_STMLF:
 516:             if (reclen < 0) {
 517:                 printf("SCREAM\n");
 518:             }
 519:             if (reclen == 0) {
 520:                 reclen = 512;
 521:             }
 522:             c = buffer[i++];
 523:             reclen--;
 524:             if (c == '\n') {
 525:                 reclen = 0;
 526:             }
 527:             fputc(c, f);
 528:             break;
 529: 
 530:         case FAB_dol_C_STMCR:
 531:             c = buffer[i++];
 532:             if (c == '\r')
 533:                 fputc('\n', f);
 534:             else
 535:                 fputc(c, f);
 536:             break;
 537: 
 538:         default:
 539:             fclose(f);
 540:             unlink(filename);
 541:             fprintf(stderr, "Invalid record format = %d\n", recfmt);
 542:             return;
 543:         }
 544:     }
 545:     file_count += i;
 546: }
 547: #ifdef  SWAP
 548: /*
 549:  *
 550:  *  do swapping for Motorola type architectures
 551:  *
 552:  */
 553: swap(from, to, nbytes)
 554: char    *from, *to;
 555: int nbytes;
 556: {
 557:     int i, j;
 558:     char    temp[100];
 559: 
 560:     for (i = 0; i < nbytes; i++)
 561:         temp[i] = from[i];
 562:     for (i = 0, j = nbytes-1; i < nbytes; i++, j--)
 563:         to[i] = temp[j];
 564: }
 565: #endif
 566: /*
 567:  *
 568:  *  process a backup block
 569:  *
 570:  */
 571: process_block(block, blocksize)
 572: char    *block;
 573: int blocksize;
 574: {
 575: 
 576:     unsigned short  bhsize, rsize, rtype;
 577:     u_long  bsize, i;
 578: 
 579:     i = 0;
 580: 
 581:     /* read the backup block header */
 582:     block_header = (struct bbh *) &block[i];
 583:     i += sizeof(struct bbh);
 584: 
 585:     bhsize = block_header->bbh_dol_w_size;
 586:     bsize = block_header->bbh_dol_l_blocksize;
 587: #ifdef  SWAP
 588:     swap(&bhsize, &bhsize, sizeof(short));
 589:     swap(&bsize, &bsize, sizeof(long));
 590: #endif
 591: 
 592:     /* check the validity of the header block */
 593:     if (bhsize != sizeof(struct bbh)) {
 594:         fprintf(stderr, "Snark: Invalid header block size\n");
 595:         exit(1);
 596:     }
 597:     if (bsize != 0 && bsize != blocksize) {
 598:         fprintf(stderr, "Snark: Invalid block size\n");
 599:         exit(1);
 600:     }
 601: #ifdef  DEBUG
 602:     printf("new block: i = %d, bsize = %d\n", i, bsize);
 603: #endif
 604: 
 605:     /* read the records */
 606:     while (i < bsize) {
 607:         /* read the backup record header */
 608:         record_header = (struct brh *) &block[i];
 609:         i += sizeof(struct brh);
 610: 
 611:         rtype = record_header->brh_dol_w_rtype;
 612:         rsize = record_header->brh_dol_w_rsize;
 613: #ifdef  SWAP
 614:         swap(&rtype, &rtype, sizeof(short));
 615:         swap(&rsize, &rsize, sizeof(short));
 616: #endif
 617: #ifdef  DEBUG
 618:         printf("rtype = %d\n", rtype);
 619:         printf("rsize = %d\n", rsize);
 620:         printf("flags = 0x%x\n", record_header->brh_dol_l_flags);
 621:         printf("addr = 0x%x\n", record_header->brh_dol_l_address);
 622:         printf("i = %d\n", i);
 623: #endif
 624: 
 625:         switch (rtype) {
 626: 
 627:         case brh_dol_k_null:
 628: #ifdef  DEBUG
 629:             printf("rtype = null\n");
 630: #endif
 631:             break;
 632: 
 633:         case brh_dol_k_summary:
 634: #ifdef  DEBUG
 635:             printf("rtype = summary\n");
 636: #endif
 637:             break;
 638: 
 639:         case brh_dol_k_file:
 640: #ifdef  DEBUG
 641:             printf("rtype = file\n");
 642: #endif
 643:             process_file(&block[i]);
 644:             break;
 645: 
 646:         case brh_dol_k_vbn:
 647: #ifdef  DEBUG
 648:             printf("rtype = vbn\n");
 649: #endif
 650:             process_vbn(&block[i], rsize);
 651:             break;
 652: 
 653:         case brh_dol_k_physvol:
 654: #ifdef  DEBUG
 655:             printf("rtype = physvol\n");
 656: #endif
 657:             break;
 658: 
 659:         case brh_dol_k_lbn:
 660: #ifdef  DEBUG
 661:             printf("rtype = lbn\n");
 662: #endif
 663:             break;
 664: 
 665:         case brh_dol_k_fid:
 666: #ifdef  DEBUG
 667:             printf("rtype = fid\n");
 668: #endif
 669:             break;
 670: 
 671:         default:
 672:             fprintf(stderr, " Snark: invalid record type\n");
 673:             fprintf(stderr, " record type = %d\n", rtype);
 674:             exit(1);
 675:         }
 676: #ifdef pyr
 677:         i = i + rsize;
 678: #else
 679:         i += rsize;
 680: #endif
 681:     }
 682: }
 683: 
 684: rdhead()
 685: {
 686:     int i, nfound;
 687:     char name[80];
 688:     nfound = 1;
 689:     /* read the tape label - 4 records of 80 bytes */
 690:     while ((i = read(fd, label, LABEL_SIZE)) != 0) {
 691:         if (i != LABEL_SIZE) {
 692:             fprintf(stderr, "Snark: bad label record\n");
 693:             exit(1);
 694:         }
 695:         if (strncmp(label, "VOL1",4) == 0) {
 696:             sscanf(label+4, "%14s", name);
 697:             if(vflag || tflag) printf("Volume: %s\n",name);
 698:         }
 699:         if (strncmp(label, "HDR1",4) == 0) {
 700:             sscanf(label+4, "%14s", name);
 701:             sscanf(label+31, "%4d", &setnr);
 702:         }
 703:         /* get the block size */
 704:         if (strncmp(label, "HDR2", 4) == 0) {
 705:             nfound = 0;
 706:             sscanf(label+5, "%5d", &blocksize);
 707: #ifdef  DEBUG
 708:             printf("blocksize = %d\n", blocksize);
 709: #endif
 710:         }
 711:     }
 712:     if((vflag || tflag) && !nfound)
 713:         printf("Saveset name: %s   number: %d\n",name,setnr);
 714:     /* get the block buffer */
 715:     block = (char *) malloc(blocksize);
 716:     if (block == (char *) 0) {
 717:         fprintf(stderr, "memory allocation for block failed\n");
 718:         exit(1);
 719:     }
 720:     return(nfound);
 721: }
 722: 
 723: rdtail()
 724: {
 725:     int i;
 726:     char name[80];
 727:     /* read the tape label - 4 records of 80 bytes */
 728:     while ((i = read(fd, label, LABEL_SIZE)) != 0) {
 729:         if (i != LABEL_SIZE) {
 730:             fprintf(stderr, "Snark: bad label record\n");
 731:             exit(1);
 732:         }
 733:         if (strncmp(label, "EOF1",4) == 0) {
 734:             sscanf(label+4, "%14s", name);
 735:             if(vflag || tflag)
 736:                 printf("End of saveset: %s\n\n\n",name);
 737:         }
 738:     }
 739: }
 740: 
 741: usage(progname)
 742: char    *progname;
 743: {
 744:     fprintf(stderr,
 745:       "Usage:  %s -{tx}[cdenvw][-s setnumber][-f tapefile]\n",progname);
 746: }
 747: main(argc, argv)
 748: int argc;
 749: char    *argv[];
 750: {
 751: 
 752:     char *progname;
 753:     int c, i, eoffl;
 754:     int selset;
 755:     extern int optind;
 756:     extern char *optarg;
 757: 
 758:     progname = argv[0];
 759:     if(argc < 2){
 760:         usage(progname);
 761:         exit(1);
 762:     }
 763:     gargv = argv;
 764:     gargc = argc;
 765:     tapefile = def_tapefile;
 766:     cflag=dflag=eflag=iflag=nflag=sflag=tflag=vflag=wflag=xflag=0;
 767:     while((c=getopt(argc,argv,"cdef:ins:tvwx")) != EOF)
 768:         switch(c){
 769:         case 'c':
 770:             cflag++;
 771:             break;
 772:         case 'd':
 773:             dflag++;
 774:             break;
 775:         case 'e':
 776:             eflag++;
 777:             break;
 778:         case 'f':
 779:             tapefile = optarg;
 780:             break;
 781:         case 'i':
 782:             iflag++;
 783:             break;
 784:         case 'n':
 785:             nflag++;
 786:             break;
 787:         case 's':
 788:             sflag++;
 789:             sscanf(optarg,"%d",&selset);
 790:             break;
 791:         case 't':
 792:             tflag++;
 793:             break;
 794:         case 'v':
 795:             vflag++;
 796:             break;
 797:         case 'w':
 798:             wflag++;
 799:             break;
 800:         case 'x':
 801:             xflag++;
 802:             break;
 803:         case '?':
 804:             usage(progname);
 805:             exit(1);
 806:             break;
 807:         };
 808:     if(!tflag && !xflag) {
 809:         usage(progname);
 810:         exit(1);
 811:     }
 812:     goptind = optind;
 813: 
 814: #ifdef  NEWD
 815:     /* open debug file */
 816:     lf = fopen("log", "w");
 817:     if (lf == NULL) {
 818:         perror("log");
 819:         exit(1);
 820:     }
 821: #endif
 822: 
 823:     /* open the tape file */
 824:     fd = open(tapefile, O_RDONLY);
 825:     if (fd < 0) {
 826:         perror(tapefile);
 827:         exit(1);
 828:     }
 829: 
 830:     /* rewind the tape */
 831:     op.mt_op = MTREW;
 832:     op.mt_count = 1;
 833:     i = ioctl(fd, MTIOCTOP, &op);
 834:     if (i < 0) {
 835:         perror(tapefile);
 836:         exit(1);
 837:     }
 838: 
 839:     eoffl = rdhead();
 840:     /* read the backup tape blocks until end of tape */
 841:     while (!eoffl) {
 842:         if(sflag && setnr != selset) {
 843:             op.mt_op = MTFSF;
 844:             op.mt_count = 1;
 845:             i = ioctl(fd, MTIOCTOP, &op);
 846:             if (i < 0) {
 847:                 perror(tapefile);
 848:                 exit(1);
 849:             }
 850:             i = 0;
 851:         }
 852:         else
 853:             i = read(fd, block, blocksize);
 854:         if(i == 0) {
 855:             rdtail();
 856:             eoffl=rdhead();
 857:         }
 858:         else if (i != blocksize) {
 859:             fprintf(stderr, "bad block read i = %d\n", i);
 860:             if (!iflag)
 861:                 exit(1);
 862:             else if (f != NULL) {
 863:                 printf("File '%s' truncated - bad blocks\n",
 864:                     filename);
 865:                 fclose(f);
 866:                 f = NULL;
 867:                 file_count = 0;
 868:                 reclen = 0;
 869:             }
 870:         }
 871:         else{
 872:             eoffl = 0;
 873:             process_block(block, blocksize);
 874:         }
 875:     }
 876:     if(vflag || tflag) printf("End of tape\n");
 877: 
 878:     /* close the tape */
 879:     close(fd);
 880: 
 881: #ifdef  NEWD
 882:     /* close debug file */
 883:     fclose(lf);
 884: #endif	NEWD
 885: 
 886:     /* exit cleanly */
 887:     exit(0);
 888: }

Defined functions

main defined in line 747; never used
openfile defined in line 250; used 1 times
process_block defined in line 571; used 1 times
process_file defined in line 345; never used
process_vbn defined in line 450; never used
rdhead defined in line 684; used 2 times
rdtail defined in line 723; used 1 times
swap defined in line 553; used 11 times
typecmp defined in line 314; used 1 times
usage defined in line 741; used 3 times

Defined variables

block defined in line 245; used 10 times
block_header defined in line 162; used 3 times
blocksize defined in line 246; used 9 times
cflag defined in line 237; used 3 times
data_item defined in line 187; never used
def_tapefile defined in line 192; used 1 times
dflag defined in line 237; used 4 times
eflag defined in line 237; used 3 times
fd defined in line 236; used 8 times
file_count defined in line 226; used 4 times
file_table defined in line 222; used 9 times
filename defined in line 196; used 8 times
filesize defined in line 197; used 4 times
fix defined in line 228; used 2 times
gargc defined in line 240; used 3 times
gargv defined in line 239; used 2 times
goptind defined in line 240; used 3 times
iflag defined in line 237; used 3 times
label defined in line 243; used 11 times
nflag defined in line 237; used 3 times
op defined in line 248; used 6 times
recatt defined in line 210; used 3 times
recfmt defined in line 199; used 5 times
reclen defined in line 227; used 21 times
record_header defined in line 170; used 5 times
recsize defined in line 229; used 4 times
setnr defined in line 238; used 3 times
sflag defined in line 237; used 3 times
tapefile defined in line 194; used 6 times
tflag defined in line 237; used 8 times
vfcsize defined in line 230; used 6 times
vflag defined in line 237; used 7 times
wflag defined in line 237; used 3 times
xflag defined in line 237; used 4 times

Defined struct's

bbh defined in line 137; used 6 times
brh defined in line 164; used 4 times
bsa defined in line 183; used 6 times

Defined macros

FAB_dol_C_FIX defined in line 202; never used
FAB_dol_C_MAXRFM defined in line 208; never used
FAB_dol_C_STM defined in line 205; never used
FAB_dol_C_STMCR defined in line 207; never used
FAB_dol_C_STMLF defined in line 206; never used
FAB_dol_C_UDF defined in line 201; never used
FAB_dol_C_VAR defined in line 203; never used
FAB_dol_C_VFC defined in line 204; used 1 times
FAB_dol_V_BLK defined in line 215; never used
FAB_dol_V_CR defined in line 213; never used
FAB_dol_V_FTN defined in line 212; used 1 times
FAB_dol_V_PRN defined in line 214; never used
FANO defined in line 217; used 3 times
LABEL_SIZE defined in line 242; used 5 times
SWAP defined in line 94; used 9 times
bbh_dol_b_bktsize defined in line 116; used 1 times
bbh_dol_b_rattrib defined in line 114; used 1 times
bbh_dol_b_rtype defined in line 113; used 1 times
bbh_dol_b_vfcsize defined in line 117; used 1 times
bbh_dol_l_blocksize defined in line 107; used 2 times
bbh_dol_l_crc defined in line 106; used 1 times
bbh_dol_l_filesize defined in line 119; used 1 times
bbh_dol_l_flags defined in line 108; used 1 times
bbh_dol_l_number defined in line 102; used 1 times
bbh_dol_t_filename defined in line 112; used 1 times
bbh_dol_t_spare_1 defined in line 103; used 1 times
bbh_dol_t_spare_2 defined in line 120; used 1 times
bbh_dol_t_ssname defined in line 109; used 1 times
bbh_dol_w_applic defined in line 101; used 1 times
bbh_dol_w_checksum defined in line 121; used 1 times
bbh_dol_w_did defined in line 111; used 1 times
bbh_dol_w_fid defined in line 110; used 1 times
bbh_dol_w_maxrec defined in line 118; used 1 times
bbh_dol_w_opsys defined in line 99; used 1 times
bbh_dol_w_rsize defined in line 115; used 1 times
bbh_dol_w_size defined in line 98; used 2 times
bbh_dol_w_struclev defined in line 104; used 1 times
bbh_dol_w_subsys defined in line 100; used 1 times
bbh_dol_w_volnum defined in line 105; used 1 times
brh_dol_k_fid defined in line 181; never used
brh_dol_k_file defined in line 177; never used
brh_dol_k_lbn defined in line 180; never used
brh_dol_k_null defined in line 174; never used
brh_dol_k_physvol defined in line 179; never used
brh_dol_k_summary defined in line 175; never used
brh_dol_k_vbn defined in line 178; never used
brh_dol_k_volume defined in line 176; never used
brh_dol_l_address defined in line 126; used 2 times
brh_dol_l_flags defined in line 125; used 2 times
brh_dol_l_spare defined in line 127; used 1 times
brh_dol_w_rsize defined in line 123; used 2 times
brh_dol_w_rtype defined in line 124; used 2 times
bsa_dol_t_text defined in line 131; used 3 times
bsa_dol_w_size defined in line 129; used 7 times
bsa_dol_w_type defined in line 130; used 1 times
process_file defined in line 133; used 1 times
process_vbn defined in line 134; used 1 times
Last modified: 1989-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6015
Valid CSS Valid XHTML 1.0 Strict