home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
tapeutils.zip
/
tuucxx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-08-16
|
7KB
|
208 lines
char *vers = "copytape version 1.2, 15 May 87";
/* copytape -- tape-to-tape copy program */
/*
/* F. da Cruz, Columbia University Center for Computing Activities, May 1987 */
/*
/* Parts cribbed from Jim Guyton's readtape and writetape programs, and */
/* from ansitar. If run with debug printout, output tape is slightly /*
/* longer than input tape. */
/* Suggested minor improvements: check that input & output devices are */
/* really tapes. Really check that input & output tape not same device. */
/* Add some statistics. Use dynamic buffers & pointers, rather than fixed, */
/* to save space. Etc. */
/* Includes */
#include <stdio.h> /* standard i/o */
#include <sys/types.h> /* data types needed by below */
#include <sys/mtio.h> /* magtape i/o */
#include <sys/ioctl.h> /* i/o control */
/* I/O descriptors, flags, etc. */
int in, out; /* input, output tapes */
int teof; /* input tape eof flag */
int debug = 0, dv = 0; /* command line option flags */
long copyfile(); /* forward dcl of non-int function */
/* Tape stuff */
char *indef = "/dev/rmt12"; /* default input drive */
char *outdef = "/dev/rmt13"; /* default output drive */
char *intape = "";
char *outape = "";
struct mtop mtx; /* tape i/o structure for ioctl */
/* Buffer stuff */
#define BLKSIZE 30*1024 /* I/O buffer size */
#define BLOCKS 10 /* Number of buffers */
int maxblock = BLKSIZE;
char buf[BLOCKS][BLKSIZE]; /* Declare buffer array */
int buflen[BLOCKS]; /* & array of data lengths per buf */
char errbuf[100]; /* Buffer for making error strings */
/* Main program */
main(argc,argv) int argc; char *argv[]; {
long ct, files, bytes = 0L;
int filenum = 1;
char x, *xp;
while (--argc > 0) { /* Parse options */
argv++;
if (**argv == '-') {
x = *(*argv+1); /* Option letter */
xp = *argv+1; /* Point past dash */
while (x) { /* Loop thru bundled options */
switch(x) {
case 'd': /* Debugging display */
debug = 1;
break;
case 'f': /* From device */
if (*(xp+1)) fatal("Invalid argument bundling");
intape = *++argv;
argc--;
if (*intape == '-' || argc <= 0)
fatal("-f argument missing");
break;
case 't': /* To device */
if (*(xp+1)) fatal("Invalid argument bundling");
outape = *++argv;
argc--;
if (*outape == '-' || argc <= 0)
fatal("-t argument missing");
break;
case 'v': /* Version info */
dv = 1;
break;
default : usage();
}
x = *++xp; /* See if options are bundled */
}
} else usage();
}
if (debug || dv) { /* Display version info if asked */
fprintf(stderr,"%s\n",vers);
fprintf(stderr,"%d buffers, %d bytes each\n\n",BLOCKS,maxblock);
}
if (!*intape) intape = indef; /* Supply defaults */
if (!*outape) outape = outdef;
if (strcmp(intape,"0") == 0) intape = indef;
if (strcmp(intape,"1") == 0) intape = outdef;
if (strcmp(outape,"0") == 0) outape = indef;
if (strcmp(outape,"1") == 0) outape = outdef;
if (strcmp(outape,intape) == 0) {
fprintf(stderr,"You must specify two different tape drives\n");
exit(1);
}
if (debug) {
fprintf(stderr,"input drive: %s\n",intape);
fprintf(stderr,"output drive: %s\n",outape);
}
in = open(intape, 0); /* Open input tape */
if (in > 0)
printf("Reading from tape '%s'\n", intape);
else {
sprintf(errbuf,"Can't open tape %s for reading",intape);
fatal(errbuf);
}
if (rew(in) < 0) /* Rewind to load point */
fatal("Can't rewind input tape");
out = open(outape, 1); /* Open output tape */
if (out > 0)
printf("Writing to tape '%s'\n", outape);
else {
sprintf(errbuf,"Can't open tape %s for writing",outape);
fatal(errbuf);
}
if (rew(out) < 0) /* Rewind to load point */
fatal("Can't rewind output tape");
system("date"); /* Say when starting */
ct = files = 1; /* Initialize counters */
while (ct) { /* Copy each file on tape */
if (debug) fprintf(stderr,"\nfile %ld:", files);
ct = copyfile(); /* Copy the file */
files++; /* Count the file */
bytes += ct; /* Accumulate total byte count */
}
tapemark(out); /* Write final tapemark */
close(out); /* Close tape drives */
close(in);
system("date"); /* When done, print messages */
printf("\nDone, copied %ld bytes in %ld file(s)\n", bytes, (files - 1));
exit(0);
}
long /* Copy a file from in to out */
copyfile() { /* Returns number of bytes read */
int i, blks; /* Loop control, block count */
long ct = 0; /* Character count */
teof = 0; /* Copy tape blocks till tape eof */
/* Do several buffers at a time */
while (!teof) {
for (blks = i = 0; i < BLOCKS; i++) { /* Read some buffers */
if ((buflen[i] = read(in, buf[i], BLKSIZE)) < 0)
fatal("I/O error reading tape");
else if (buflen[i] > 0) {
blks++; /* Count this block */
if (debug) fprintf(stderr," %d:%d",i,buflen[i]);
} else { /* Count of 0 means end of tape file */
if (debug) fprintf(stderr," eof");
teof = 1; /* Flag tape file eof. */
break;
}
}
if (debug) fprintf(stderr," [%d]",blks); /* # of blocks read */
for (i = 0; i < blks; i++) { /* Write out the buffers. */
if (debug) fprintf(stderr," w%d:%d",i,buflen[i]);
if (write(out, buf[i], buflen[i]) != buflen[i])
fatal("Write error");
ct += buflen[i]; /* Keep track of # of bytes written */
buflen[i] = 0;
}
}
if (debug) fprintf(stderr," tm");
if (tapemark(out) < 0) /* Write file mark. */
fatal("Can't write tape mark");
return(ct); /* Return output byte count. */
}
tapemark(tf) int tf; { /* Write a tapemark (file mark) */
mtx.mt_count = 1;
mtx.mt_op = MTWEOF;
return(ioctl(tf, MTIOCTOP, (char *) &mtx));
}
rew(tf) int tf; { /* Rewind tape */
mtx.mt_op = MTREW;
return(ioctl(tf, MTIOCTOP, (char *) &mtx));
}
fatal(s) char *s; { /* Fatal error message and exit */
perror(s); /* Include last system error */
exit(1);
}
usage() {
fprintf(stderr,"usage: copytape [-d -v -f intape -t outtape]\n");
fprintf(stderr,"-d=debug, -v=version, -f=from, -t=to\n");
fprintf(stderr,"intape default %s, outtape default %s\n",indef,outdef);
fprintf(stderr,"maximum blocksize: %ld.\n",maxblock);
fprintf(stderr,"number of blocks buffered: %d.\n",BLOCKS);
exit(1);
}