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 } 718