1: #include <sys/types.h> 2: #include <sys/time.h> 3: #include <sys/mtio.h> 4: #include <sys/ioctl.h> 5: #include <sys/file.h> 6: #include <sys/stat.h> 7: #include <a.out.h> 8: #include <stdio.h> 9: #include <ctype.h> 10: 11: char *malloc(); 12: int wflag; 13: int xflag; 14: int tflag; 15: int cflag; 16: int vflag; 17: int dflag; 18: int totalreadfiles = 0 ; 19: int totalreadblocks = 0 ; 20: int totalreadlines = 0 ; 21: int totalreadchars = 0 ; 22: int totalwritefiles = 0 ; 23: int totalwriteblocks = 0 ; 24: int totalwritelines = 0 ; 25: int totalwritechars = 0 ; 26: 27: main(argc,argv) 28: int argc; 29: char *argv[]; 30: { 31: struct tm *tm; 32: long timetemp; 33: int year; 34: int day; 35: char *tapename; 36: char *filename; 37: char *namelist=NULL; 38: char *device = "/dev/rmt12"; 39: int tape; 40: int file; 41: int filenum; 42: int argnum; 43: char line[1001]; 44: char vmsname[1000]; 45: char unixname[1000]; 46: FILE *names; 47: int count; 48: int tmp; 49: char blockchar; 50: int blocksize=2048; 51: 52: char *key; 53: 54: timetemp = time(0); 55: tm = localtime(&timetemp); 56: year = tm->tm_year; 57: day = tm->tm_yday; 58: tapename = malloc(10); 59: gethostname(tapename,6); 60: tapename[7]='\0'; 61: 62: /* parse command line */ 63: if (argc < 2) 64: usage(); 65: 66: argv++; 67: argc--; 68: /* loop through first argument (key) */ 69: argc--; 70: for (key = *argv++; *key; key++) 71: switch(*key) { 72: 73: case 'f': 74: if (*argv == NULL || argc <1) { 75: fprintf(stderr, 76: "ansitape: 'f' option requires tape name \n"); 77: usage(); 78: } 79: device = *argv++; 80: argc--; 81: break; 82: 83: case 'n': 84: if (*argv == NULL || argc <1) { 85: fprintf(stderr, 86: "ansitape: 'n' option requires file name\n"); 87: usage(); 88: } 89: namelist = *argv++; 90: argc--; 91: break; 92: 93: case 'l': 94: if (*argv == NULL || argc<1) { 95: fprintf(stderr, 96: "ansitape: 'l' option requires label\n"); 97: usage(); 98: } 99: tapename = *argv++; 100: argc--; 101: break; 102: 103: case 'b': 104: if (*argv == NULL) { 105: fprintf(stderr, 106: "ansitape: 'b' option requires blocksize specifier \n"); 107: usage(); 108: } 109: tmp = sscanf(*argv++," %d%c ",&blocksize,&blockchar); 110: argc--; 111: if(tmp<1) { 112: fprintf(stderr,"illegal blocksize: blocksize set to 2048\n"); 113: blocksize=2048; 114: } else if(tmp>1) { 115: if(blockchar == 'b') blocksize *= 512; 116: if(blockchar == 'k') blocksize *= 1024; 117: } 118: if(blocksize <18) blocksize=18; 119: if(blocksize >62*1024) blocksize=62*1024; 120: break; 121: 122: case 'c': 123: cflag++; 124: wflag++; 125: break; 126: 127: case 'r': 128: /*I know, this should be rflag, but I just don't like r for write*/ 129: wflag++; 130: break; 131: 132: case 'v': 133: vflag++; 134: break; 135: 136: case 'x': 137: xflag++; 138: break; 139: 140: case 't': 141: tflag++; 142: break; 143: 144: case '-': 145: break; 146: 147: default: 148: fprintf(stderr, "ansitape: %c: unknown option\n", *key); 149: usage(); 150: } 151: 152: if (!wflag && !xflag && !tflag) 153: usage(); 154: 155: tape = open(device,wflag?O_RDWR:O_RDONLY,NULL); 156: if(tape<0) { 157: perror(device); 158: printf(stderr,"tape not accessable - check if drive online and write ring present\n"); 159: exit(1); 160: } 161: rewind(tape); 162: filenum=1; 163: casefix(tapename); 164: 165: if(cflag) { 166: writevol(tapename,tape); 167: } else { 168: getvol(tapename,tape); 169: while(1) { 170: /* read files */ 171: if( readfile(tape,argc,argv) ) break; 172: filenum++; 173: } 174: backspace(tape); 175: } 176: 177: if(wflag) { 178: if(namelist) { 179: if(*namelist == '-') { 180: names = stdin; 181: } else { 182: names=fopen(namelist,"r"); 183: if(names == NULL) { 184: fprintf(stderr,"unable to open namelist file - no files added to tape\n"); 185: } 186: } 187: while(1) { 188: fgets(line,1000,names); 189: if(feof(names)) break; 190: count = sscanf(line,"%s %s",unixname,vmsname); 191: if(count<1) continue; /* blank line */ 192: if(count==1) strcpy(vmsname,unixname); 193: casefix(vmsname); 194: if(filecheck(&file,unixname)) continue; 195: writefile(tape,file,vmsname,tapename,filenum,year,day,blocksize); 196: filenum++; 197: close(file); 198: } 199: } else { 200: for(argnum=0;argnum<argc;argnum++) { 201: filename = argv[argnum]; 202: if(filecheck(&file,filename)) continue; 203: casefix(filename); 204: writefile(tape,file,filename,tapename,filenum,year,day,blocksize); 205: filenum++; 206: close(file); 207: } 208: } 209: writetm(tape); 210: writetm(tape); 211: writetm(tape); 212: writetm(tape); 213: } 214: rewind(tape); 215: close(tape); 216: if(vflag && (tflag || xflag)) { 217: fprintf(stdout," read %d files in %d blocks (%d lines, %d chars)\n", 218: totalreadfiles,totalreadblocks,totalreadlines,totalreadchars); 219: } 220: if(vflag && wflag) { 221: fprintf(stdout," wrote %d files in %d blocks (%d lines, %d chars)\n", 222: totalwritefiles,totalwriteblocks,totalwritelines,totalwritechars); 223: } 224: } 225: usage() { 226: fprintf(stderr, 227: "ansitape: usage: ansitape -{rxtc}[flnvb] [filename] [label] [filename] [blocksize] [files]\n"); 228: exit(); 229: } 230: 231: writefile(tape,file,filename,tapename,filenum,year,day,blocksize) 232: int tape; 233: int file; 234: char *filename; 235: char *tapename; 236: int filenum; 237: int year; 238: int day; 239: int blocksize; 240: 241: { 242: int blocks; 243: writehdr1(tape,filename,tapename,filenum,year,day); 244: writehdr2(tape,blocksize); 245: writehdr3(tape); 246: writetm(tape); 247: writedata(tape,file,filename,&blocks,blocksize); 248: writetm(tape); 249: writeeof1(tape,filename,tapename,filenum,year,day,blocks); 250: writeeof2(tape); 251: writeeof3(tape); 252: writetm(tape); 253: totalwritefiles++; 254: } 255: 256: writedata(tape,file,filename,blocks,blocksize) 257: int tape; 258: int file; 259: char *filename; 260: int *blocks; 261: int blocksize; 262: { 263: char *ibuf; 264: char *ibufstart; 265: char *obuf; 266: char *obufstart; 267: char sizebuf[5]; 268: char *endibuf; 269: char *endobuf; 270: int got; 271: int i; 272: char *j; 273: int numchar = 0 ; 274: int numline = 0 ; 275: int numblock = 0; 276: int success; 277: 278: ibufstart = ibuf = malloc(blocksize<4096?8200:(2*blocksize+10)); 279: obufstart = obuf = malloc(blocksize+10); 280: endobuf = obuf + blocksize; 281: endibuf = ibuf; 282: 283: 284: i=0; 285: while(1) { 286: if(ibuf+i>=endibuf) { /* end of input buffer */ 287: strncpy(ibufstart,ibuf,endibuf-ibuf); /* copy leftover to start */ 288: ibuf = ibufstart+(endibuf-ibuf); /* point to end of valid data */ 289: got = read(file,ibuf,blocksize<4096?4096:2*blocksize); /* read in a chunk */ 290: endibuf = ibuf + got; 291: ibuf = ibufstart; /* point to beginning of data */ 292: if(got == 0) { /* end of input */ 293: if(ibuf==ibufstart){ /* no leftovers */ 294: break; /* done */ 295: } else { 296: ibuf[i]='\n'; /* fake extra newline */ 297: } 298: } 299: } 300: 301: if(obuf+i+4 > endobuf) { /* end of output buffer */ 302: if(i>blocksize-4) { 303: printf("record exceeds blocksize - file truncated\n"); 304: break; 305: } 306: /* filled up output record - have to fill,output,restart*/ 307: for(j=obuf;j<endobuf;j++) { 308: *j = '^'; 309: } 310: success = write(tape,obufstart,blocksize); 311: if(success != blocksize) { 312: perror("tape"); 313: fprintf(stderr," hard write error: write aborted\n"); 314: rewind(tape); 315: exit(1); 316: } 317: obuf=obufstart; 318: numchar -= i; 319: i=0; 320: numblock++; 321: continue; 322: } 323: 324: if(ibuf[i] == '\n') { /* end of line */ 325: /*sprintf(sizebuf,"%4.4d",i+4); /* make length string */ 326: /*strncpy(obuf,sizebuf,4); /* put in length field */ 327: obuf[0] = ((i+4)/1000) + '0'; 328: obuf[1] = (((i+4)/100)%10) + '0'; 329: obuf[2] = (((i+4)/10)%10) + '0'; 330: obuf[3] = (((i+4)/1)%10) + '0'; 331: obuf += (4+i); /* size + strlen */ 332: ibuf += (1+i); /* newline + strlen */ 333: i=0; 334: numline++; 335: continue; /* back to the top */ 336: } 337: 338: obuf[i+4]=ibuf[i]; 339: numchar++; 340: i++; 341: 342: } 343: /* exited - write last record and go for lunch */ 344: if(obuf != obufstart) { 345: for(j=obuf;j<endobuf;j++) { 346: *j = '^'; 347: } 348: success = write(tape,obufstart,blocksize); 349: if(success != blocksize) { 350: perror("tape"); 351: fprintf(stderr," hard write error: write aborted\n"); 352: rewind(tape); 353: exit(1); 354: } 355: numblock++; 356: } 357: free(ibufstart); 358: free(obufstart); 359: if(vflag) { 360: fprintf(stdout,"r - %s: %d lines (%d chars) in %d tape blocks\n", 361: filename,numline,numchar,numblock); 362: } 363: totalwritechars += numchar; 364: totalwritelines += numline; 365: totalwriteblocks += numblock; 366: *blocks = numblock; 367: } 368: 369: writetm(tape) 370: int tape; 371: { 372: struct mtop mtop; 373: mtop.mt_op = MTWEOF; 374: mtop.mt_count = 1; 375: ioctl(tape,MTIOCTOP,&mtop); 376: } 377: 378: rewind(tape) 379: int tape; 380: { 381: struct mtop mtop; 382: mtop.mt_op = MTREW; 383: mtop.mt_count = 1; 384: ioctl(tape,MTIOCTOP,&mtop); 385: } 386: 387: skipfile(tape) 388: int tape; 389: { 390: struct mtop mtop; 391: mtop.mt_op = MTFSF; 392: mtop.mt_count = 1; 393: ioctl(tape,MTIOCTOP,&mtop); 394: } 395: 396: backspace(tape) 397: int tape; 398: { 399: struct mtop mtop; 400: mtop.mt_op = MTBSF; 401: mtop.mt_count = 1; 402: ioctl(tape,MTIOCTOP,&mtop); 403: } 404: 405: writehdr1(tape,filename,tapename,filenum,year,day) 406: int tape; 407: char *filename; 408: char *tapename; 409: int filenum; 410: int year; 411: int day; 412: { 413: char buf[81]; 414: sprintf(buf, 415: "HDR1%-17.17s%-6.6s0001%4.4d000101 %2.2d%3.3d %2.2d%3.3d 000000DECFILE11A " 416: ,filename,tapename,filenum,year,day,year,day); 417: write(tape,buf,80); 418: } 419: 420: writeeof1(tape,filename,tapename,filenum,year,day,blocks) 421: int tape; 422: char *filename; 423: char *tapename; 424: int filenum; 425: int year; 426: int day; 427: int blocks; 428: { 429: char buf[81]; 430: sprintf(buf, 431: "EOF1%-17.17s%-6.6s0001%4.4d000101 %2.2d%3.3d %2.2d%3.3d %6.6dDECFILE11A " 432: ,filename,tapename,filenum,year,day,year,day,blocks); 433: write(tape,buf,80); 434: } 435: 436: writehdr2(tape,blocksize) 437: int tape; 438: int blocksize; 439: { 440: char buf[81]; 441: sprintf(buf, "HDR2D%5.5d%5.5d%35.35s00%28.28s",blocksize,blocksize," "," "); 442: write(tape,buf,80); 443: } 444: 445: writeeof2(tape,blocksize) 446: int tape; 447: int blocksize; 448: { 449: char buf[81]; 450: sprintf(buf, "EOF2D%5.5d%5.5d%35.35s00%28.28s",blocksize,blocksize," "," "); 451: write(tape,buf,80); 452: } 453: 454: writehdr3(tape) 455: int tape; 456: { 457: char buf[81]; 458: sprintf(buf, "HDR3%76.76s"," "); 459: write(tape,buf,80); 460: } 461: 462: writeeof3(tape) 463: int tape; 464: { 465: char buf[81]; 466: sprintf(buf, "EOF3%76.76s"," "); 467: write(tape,buf,80); 468: } 469: 470: writevol(tapename,tape) 471: int tape; 472: char *tapename; 473: { 474: char buf[81]; 475: sprintf(buf,"VOL1%-6.6s %26.26sD%47510.10s1%28.28s3",tapename," "," "," "); 476: write(tape,buf,80); 477: if(vflag) { 478: fprintf(stdout," tape labeled %-6.6s\n",tapename); 479: } 480: } 481: 482: getvol(tapename,tape) 483: int tape; 484: char *tapename; 485: { 486: char buf[81]; 487: read(tape,buf,80); 488: sscanf(buf,"VOL1%6s",tapename); 489: if(vflag) { 490: fprintf(stdout," tape was labeled %-6.6s\n",tapename); 491: } 492: } 493: 494: casefix(string) 495: register char *string; 496: { 497: while(*string) { 498: if(islower(*string)) { 499: *string = toupper(*string); 500: } 501: string++; 502: } 503: } 504: 505: static 506: getsize(a) 507: register char *a; 508: { 509: register int i; 510: int answer; 511: 512: answer = 0; 513: for (i = 0; i < 4; ++i) { 514: answer *= 10; 515: switch (a[i]) { 516: default: return -1; 517: case '0': break; 518: case '1': answer += 1; break; 519: case '2': answer += 2; break; 520: case '3': answer += 3; break; 521: case '4': answer += 4; break; 522: case '5': answer += 5; break; 523: case '6': answer += 6; break; 524: case '7': answer += 7; break; 525: case '8': answer += 8; break; 526: case '9': answer += 9; break; 527: } 528: } 529: return(answer); 530: } 531: 532: int 533: readfile(tape,argc,argv) 534: int tape; 535: int argc; 536: char *argv[]; 537: { 538: char buf[80]; 539: char mode; 540: char filename[18]; 541: FILE *file; 542: int extract; 543: char *ibuf; 544: char *ibufstart; 545: char *endibuf; 546: int i; 547: int size; 548: int numblock = 0 ; 549: int numchar = 0 ; 550: int numline = 0 ; 551: int argnum; 552: int ok; 553: int blocksize; 554: int recordsize; 555: int writeblock; 556: 557: if(!(read(tape,buf,80))) return(1); /* no hdr record, so second eof */ 558: sscanf(buf,"HDR1%17s",filename); 559: read(tape,buf,80); 560: sscanf(buf,"HDR2%c%5d%5d",&mode,&blocksize,&recordsize); 561: blocksize = blocksize>recordsize?blocksize:recordsize; 562: skipfile(tape); /* throw away rest of header(s) - not interesting */ 563: ibufstart=ibuf=malloc(blocksize+10); 564: endibuf=ibufstart+blocksize; 565: extract=0; 566: if(tflag || xflag) { 567: ok=0; 568: if(!argc) { 569: ok=1; 570: } else for(argnum=0;argnum<argc;argnum++) { 571: casefix(argv[argnum]); 572: if(!strcmp(filename,argv[argnum])) { 573: ok=1; 574: break; 575: } 576: } 577: if(mode == 'D') { 578: if(xflag && ok) { 579: file = fopen(filename,"w"); 580: if(file == NULL) { 581: perror(filename); 582: } else { 583: extract = 1; 584: } 585: } 586: while(read(tape,ibufstart,blocksize)) { 587: numblock++; 588: ibuf = ibufstart; 589: while(strncmp("^^^^",ibuf,4)) { 590: size = getsize(ibuf); 591: if(size <= 0) { 592: (void)fflush(stdout); 593: (void)fprintf(stderr,"error: bad tape record(s) in file %s - file may be truncated/corrupted.\n", filename); 594: break; 595: } 596: if(extract) { 597: fwrite(ibuf+4,sizeof(char),size-4,file); 598: fwrite("\n",1,1,file); 599: } 600: ibuf += (size); 601: numline++; 602: numchar += (size-4); 603: if(ibuf > endibuf+1) { 604: fprintf(stderr,"error: bad tape records(s) - file may be corrupted\n"); 605: break; 606: } 607: if(ibuf>endibuf-4) break; 608: } 609: } 610: if(extract) { 611: fclose(file); 612: } 613: } else if (mode == 'F') { 614: if(xflag && ok) { 615: file = fopen(filename,"w"); 616: if(file == NULL) { 617: perror(filename); 618: } else { 619: extract = 1; 620: } 621: } 622: while(read(tape,ibufstart,blocksize)) { 623: numblock++; 624: ibuf = ibufstart; 625: while(ibuf+recordsize <= endibuf) { 626: if(extract) { 627: fwrite(ibuf,sizeof(char),recordsize,file); 628: fwrite("\n",1,1,file); 629: } 630: ibuf += recordsize; 631: numline++; 632: numchar += recordsize; 633: } 634: } 635: if(extract) { 636: fclose(file); 637: } 638: } else { 639: fprintf(stderr,"unknown record mode (%c) - file %s skipped\n", 640: mode,filename); 641: skipfile(tape); /* throw away actual file */ 642: } 643: } else { 644: /* not interested in contents of file, so move fast */ 645: skipfile(tape); 646: } 647: skipfile(tape); /* throw away eof stuff - not interesting */ 648: totalreadchars += numchar; 649: totalreadlines += numline; 650: totalreadblocks += numblock; 651: totalreadfiles ++; 652: if(xflag && vflag && ok) { 653: fprintf(stdout,"x - %s: %d lines (%d chars) in %d tape blocks\n", 654: filename,numline,numchar,numblock); 655: } else if(tflag && ok) { 656: fprintf(stdout,"t - %s: %d lines (%d chars) in %d tape blocks\n", 657: filename,numline,numchar,numblock); 658: } 659: free(ibufstart); 660: return(0); 661: } 662: 663: filecheck(file,name) 664: int *file; 665: char *name; 666: 667: { 668: 669: struct stat buf; 670: struct exec sample; 671: 672: stat(name,&buf); 673: if ((buf.st_mode & S_IFDIR)==S_IFDIR) { 674: fprintf(stderr,"%s: directory - skipped\n",name); 675: return(1); 676: } 677: if ((buf.st_mode & S_IFCHR)==S_IFCHR) { 678: fprintf(stderr,"%s: character device - skipped\n",name); 679: return(1); 680: } 681: if ((buf.st_mode & S_IFBLK)==S_IFBLK) { 682: fprintf(stderr,"%s: block device - skipped\n",name); 683: return(1); 684: } 685: if ((buf.st_mode & S_IFLNK)==S_IFLNK) { 686: fprintf(stderr,"%s: symbolic link - skipped\n",name); 687: return(1); 688: } 689: if ((buf.st_mode & S_IFSOCK)==S_IFSOCK) { 690: fprintf(stderr,"%s: socket - skipped\n",name); 691: return(1); 692: } 693: *file = open(name,O_RDONLY,NULL); 694: if(*file <0) { 695: perror(name); 696: return(1); 697: } 698: if(read(*file,&sample,sizeof(struct exec))>= sizeof(struct exec)) { 699: if(!(N_BADMAG(sample))) { 700: /* executable */ 701: /* the format requires either fixed blocked records, 702: * or variable format records with each record remaining 703: * entirely within a tape block - this limits the 704: * distance between \n's to 2044 bytes, something 705: * which is VERY rarely true of executables, so 706: * we don't even try with them.... 707: */ 708: close(*file); 709: fprintf(stderr,"%s: executable - skipped\n",name); 710: return(1); 711: } 712: } 713: /* either couldn't read sizeof(struct exec) or wasn't executable */ 714: /* so we assume it is a reasonable file until proven otherwise */ 715: lseek(*file,0l,0); 716: return(0); 717: }