#include #include #include #include #include #include #include #include #include char *malloc(); int wflag; int xflag; int tflag; int cflag; int vflag; int dflag; int totalreadfiles = 0 ; int totalreadblocks = 0 ; int totalreadlines = 0 ; int totalreadchars = 0 ; int totalwritefiles = 0 ; int totalwriteblocks = 0 ; int totalwritelines = 0 ; int totalwritechars = 0 ; main(argc,argv) int argc; char *argv[]; { struct tm *tm; long timetemp; int year; int day; char *tapename; char *filename; char *namelist=NULL; char *device = "/dev/rmt12"; int tape; int file; int filenum; int argnum; char line[1001]; char vmsname[1000]; char unixname[1000]; FILE *names; int count; int tmp; char blockchar; int blocksize=2048; char *key; timetemp = time(0); tm = localtime(&timetemp); year = tm->tm_year; day = tm->tm_yday; tapename = malloc(10); gethostname(tapename,6); tapename[7]='\0'; /* parse command line */ if (argc < 2) usage(); argv++; argc--; /* loop through first argument (key) */ argc--; for (key = *argv++; *key; key++) switch(*key) { case 'f': if (*argv == NULL || argc <1) { fprintf(stderr, "ansitape: 'f' option requires tape name \n"); usage(); } device = *argv++; argc--; break; case 'n': if (*argv == NULL || argc <1) { fprintf(stderr, "ansitape: 'n' option requires file name\n"); usage(); } namelist = *argv++; argc--; break; case 'l': if (*argv == NULL || argc<1) { fprintf(stderr, "ansitape: 'l' option requires label\n"); usage(); } tapename = *argv++; argc--; break; case 'b': if (*argv == NULL) { fprintf(stderr, "ansitape: 'b' option requires blocksize specifier \n"); usage(); } tmp = sscanf(*argv++," %d%c ",&blocksize,&blockchar); argc--; if(tmp<1) { fprintf(stderr,"illegal blocksize: blocksize set to 2048\n"); blocksize=2048; } else if(tmp>1) { if(blockchar == 'b') blocksize *= 512; if(blockchar == 'k') blocksize *= 1024; } if(blocksize <18) blocksize=18; if(blocksize >62*1024) blocksize=62*1024; break; case 'c': cflag++; wflag++; break; case 'r': /*I know, this should be rflag, but I just don't like r for write*/ wflag++; break; case 'v': vflag++; break; case 'x': xflag++; break; case 't': tflag++; break; case '-': break; default: fprintf(stderr, "ansitape: %c: unknown option\n", *key); usage(); } if (!wflag && !xflag && !tflag) usage(); tape = open(device,wflag?O_RDWR:O_RDONLY,NULL); if(tape<0) { perror(device); printf(stderr,"tape not accessable - check if drive online and write ring present\n"); exit(1); } rewind(tape); filenum=1; casefix(tapename); if(cflag) { writevol(tapename,tape); } else { getvol(tapename,tape); while(1) { /* read files */ if( readfile(tape,argc,argv) ) break; filenum++; } backspace(tape); } if(wflag) { if(namelist) { if(*namelist == '-') { names = stdin; } else { names=fopen(namelist,"r"); if(names == NULL) { fprintf(stderr,"unable to open namelist file - no files added to tape\n"); } } while(1) { fgets(line,1000,names); if(feof(names)) break; count = sscanf(line,"%s %s",unixname,vmsname); if(count<1) continue; /* blank line */ if(count==1) strcpy(vmsname,unixname); casefix(vmsname); if(filecheck(&file,unixname)) continue; writefile(tape,file,vmsname,tapename,filenum,year,day,blocksize); filenum++; close(file); } } else { for(argnum=0;argnum=endibuf) { /* end of input buffer */ strncpy(ibufstart,ibuf,endibuf-ibuf); /* copy leftover to start */ ibuf = ibufstart+(endibuf-ibuf); /* point to end of valid data */ got = read(file,ibuf,blocksize<4096?4096:2*blocksize); /* read in a chunk */ endibuf = ibuf + got; ibuf = ibufstart; /* point to beginning of data */ if(got == 0) { /* end of input */ if(ibuf==ibufstart){ /* no leftovers */ break; /* done */ } else { ibuf[i]='\n'; /* fake extra newline */ } } } if(obuf+i+4 > endobuf) { /* end of output buffer */ if(i>blocksize-4) { printf("record exceeds blocksize - file truncated\n"); break; } /* filled up output record - have to fill,output,restart*/ for(j=obuf;jrecordsize?blocksize:recordsize; skipfile(tape); /* throw away rest of header(s) - not interesting */ ibufstart=ibuf=malloc(blocksize+10); endibuf=ibufstart+blocksize; extract=0; if(tflag || xflag) { ok=0; if(!argc) { ok=1; } else for(argnum=0;argnum endibuf+1) { fprintf(stderr,"error: bad tape records(s) - file may be corrupted\n"); break; } if(ibuf>endibuf-4) break; } } if(extract) { fclose(file); } } else if (mode == 'F') { if(xflag && ok) { file = fopen(filename,"w"); if(file == NULL) { perror(filename); } else { extract = 1; } } while(read(tape,ibufstart,blocksize)) { numblock++; ibuf = ibufstart; while(ibuf+recordsize <= endibuf) { if(extract) { fwrite(ibuf,sizeof(char),recordsize,file); fwrite("\n",1,1,file); } ibuf += recordsize; numline++; numchar += recordsize; } } if(extract) { fclose(file); } } else { fprintf(stderr,"unknown record mode (%c) - file %s skipped\n", mode,filename); skipfile(tape); /* throw away actual file */ } } else { /* not interested in contents of file, so move fast */ skipfile(tape); } skipfile(tape); /* throw away eof stuff - not interesting */ totalreadchars += numchar; totalreadlines += numline; totalreadblocks += numblock; totalreadfiles ++; if(xflag && vflag && ok) { fprintf(stdout,"x - %s: %d lines (%d chars) in %d tape blocks\n", filename,numline,numchar,numblock); } else if(tflag && ok) { fprintf(stdout,"t - %s: %d lines (%d chars) in %d tape blocks\n", filename,numline,numchar,numblock); } free(ibufstart); return(0); } filecheck(file,name) int *file; char *name; { struct stat buf; struct exec sample; stat(name,&buf); if ((buf.st_mode & S_IFDIR)==S_IFDIR) { fprintf(stderr,"%s: directory - skipped\n",name); return(1); } if ((buf.st_mode & S_IFCHR)==S_IFCHR) { fprintf(stderr,"%s: character device - skipped\n",name); return(1); } if ((buf.st_mode & S_IFBLK)==S_IFBLK) { fprintf(stderr,"%s: block device - skipped\n",name); return(1); } if ((buf.st_mode & S_IFLNK)==S_IFLNK) { fprintf(stderr,"%s: symbolic link - skipped\n",name); return(1); } if ((buf.st_mode & S_IFSOCK)==S_IFSOCK) { fprintf(stderr,"%s: socket - skipped\n",name); return(1); } *file = open(name,O_RDONLY,NULL); if(*file <0) { perror(name); return(1); } if(read(*file,&sample,sizeof(struct exec))>= sizeof(struct exec)) { if(!(N_BADMAG(sample))) { /* executable */ /* the format requires either fixed blocked records, * or variable format records with each record remaining * entirely within a tape block - this limits the * distance between \n's to 2044 bytes, something * which is VERY rarely true of executables, so * we don't even try with them.... */ close(*file); fprintf(stderr,"%s: executable - skipped\n",name); return(1); } } /* either couldn't read sizeof(struct exec) or wasn't executable */ /* so we assume it is a reasonable file until proven otherwise */ lseek(*file,0l,0); return(0); }