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%%C%10.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: #define getsize(a) ((a[0]-'0')*1000)+((a[1]-'0')*100)+((a[2]-'0')*10)+(a[3]-'0') 506: int 507: readfile(tape,argc,argv) 508: int tape; 509: int argc; 510: char *argv[]; 511: { 512: char buf[80]; 513: char mode; 514: char filename[18]; 515: FILE *file; 516: int extract; 517: char *ibuf; 518: char *ibufstart; 519: char *endibuf; 520: int i; 521: int size; 522: int numblock = 0 ; 523: int numchar = 0 ; 524: int numline = 0 ; 525: int argnum; 526: int ok; 527: int blocksize; 528: int recordsize; 529: int writeblock; 530: 531: if(!(read(tape,buf,80))) return(1); /* no hdr record, so second eof */ 532: sscanf(buf,"HDR1%17s",filename); 533: read(tape,buf,80); 534: sscanf(buf,"HDR2%c%5d%5d",&mode,&blocksize,&recordsize); 535: blocksize = blocksize>recordsize?blocksize:recordsize; 536: skipfile(tape); /* throw away rest of header(s) - not interesting */ 537: ibufstart=ibuf=malloc(blocksize+10); 538: endibuf=ibufstart+blocksize; 539: extract=0; 540: if(tflag || xflag) { 541: ok=0; 542: if(!argc) { 543: ok=1; 544: } else for(argnum=0;argnum<argc;argnum++) { 545: casefix(argv[argnum]); 546: if(!strcmp(filename,argv[argnum])) { 547: ok=1; 548: break; 549: } 550: } 551: if(mode == 'D') { 552: if(xflag && ok) { 553: file = fopen(filename,"w"); 554: if(file == NULL) { 555: perror(filename); 556: } else { 557: extract = 1; 558: } 559: } 560: while(read(tape,ibufstart,blocksize)) { 561: numblock++; 562: ibuf = ibufstart; 563: while(strncmp("^^^^",ibuf,4)) { 564: size = getsize(ibuf); 565: if(extract) { 566: fwrite(ibuf+4,sizeof(char),size-4,file); 567: fwrite("\n",1,1,file); 568: } 569: ibuf += (size); 570: numline++; 571: numchar += (size-4); 572: if(ibuf > endibuf+1) { 573: fprintf(stderr,"error: bad tape records(s) - file may be corrupted\n"); 574: break; 575: } 576: if(ibuf>endibuf-4) break; 577: } 578: } 579: if(extract) { 580: fclose(file); 581: } 582: } else if (mode == 'F') { 583: if(xflag && ok) { 584: file = fopen(filename,"w"); 585: if(file == NULL) { 586: perror(filename); 587: } else { 588: extract = 1; 589: } 590: } 591: while(read(tape,ibufstart,blocksize)) { 592: numblock++; 593: ibuf = ibufstart; 594: while(ibuf+recordsize <= endibuf) { 595: if(extract) { 596: fwrite(ibuf,sizeof(char),recordsize,file); 597: fwrite("\n",1,1,file); 598: } 599: ibuf += recordsize; 600: numline++; 601: numchar += recordsize; 602: } 603: } 604: if(extract) { 605: fclose(file); 606: } 607: } else { 608: fprintf(stderr,"unknown record mode (%c) - file %s skipped\n", 609: mode,filename); 610: skipfile(tape); /* throw away actual file */ 611: } 612: } else { 613: /* not interested in contents of file, so move fast */ 614: skipfile(tape); 615: } 616: skipfile(tape); /* throw away eof stuff - not interesting */ 617: totalreadchars += numchar; 618: totalreadlines += numline; 619: totalreadblocks += numblock; 620: totalreadfiles ++; 621: if(xflag && vflag && ok) { 622: fprintf(stdout,"x - %s: %d lines (%d chars) in %d tape blocks\n", 623: filename,numline,numchar,numblock); 624: } else if(tflag && ok) { 625: fprintf(stdout,"t - %s: %d lines (%d chars) in %d tape blocks\n", 626: filename,numline,numchar,numblock); 627: } 628: free(ibufstart); 629: return(0); 630: } 631: 632: filecheck(file,name) 633: int *file; 634: char *name; 635: 636: { 637: 638: struct stat buf; 639: struct exec sample; 640: 641: stat(name,&buf); 642: if ((buf.st_mode & S_IFDIR)==S_IFDIR) { 643: fprintf(stderr,"%s: directory - skipped\n",name); 644: return(1); 645: } 646: if ((buf.st_mode & S_IFCHR)==S_IFCHR) { 647: fprintf(stderr,"%s: character device - skipped\n",name); 648: return(1); 649: } 650: if ((buf.st_mode & S_IFBLK)==S_IFBLK) { 651: fprintf(stderr,"%s: block device - skipped\n",name); 652: return(1); 653: } 654: if ((buf.st_mode & S_IFLNK)==S_IFLNK) { 655: fprintf(stderr,"%s: symbolic link - skipped\n",name); 656: return(1); 657: } 658: if ((buf.st_mode & S_IFSOCK)==S_IFSOCK) { 659: fprintf(stderr,"%s: socket - skipped\n",name); 660: return(1); 661: } 662: *file = open(name,O_RDONLY,NULL); 663: if(*file <0) { 664: perror(name); 665: return(1); 666: } 667: if(read(*file,&sample,sizeof(struct exec))>= sizeof(struct exec)) { 668: if(!(N_BADMAG(sample))) { 669: /* executable */ 670: /* the format requires either fixed blocked records, 671: * or variable format records with each record remaining 672: * entirely within a tape block - this limits the 673: * distance between \n's to 2044 bytes, something 674: * which is VERY rarely true of executables, so 675: * we don't even try with them.... 676: */ 677: close(*file); 678: fprintf(stderr,"%s: executable - skipped\n",name); 679: return(1); 680: } 681: } 682: /* either couldn't read sizeof(struct exec) or wasn't executable */ 683: /* so we assume it is a reasonable file until proven otherwise */ 684: lseek(*file,0l,0); 685: return(0); 686: }