home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / tapeutils.zip / tuucxx.c < prev    next >
C/C++ Source or Header  |  1988-08-16  |  7KB  |  208 lines

  1. char *vers = "copytape version 1.2, 15 May 87";
  2.  
  3. /* copytape -- tape-to-tape copy program */
  4. /*
  5. /* F. da Cruz, Columbia University Center for Computing Activities, May 1987 */
  6. /*
  7. /* Parts cribbed from Jim Guyton's readtape and writetape programs, and */
  8. /* from ansitar.  If run with debug printout, output tape is slightly /*
  9. /* longer than input tape. */
  10.  
  11. /* Suggested minor improvements: check that input & output devices are */ 
  12. /* really tapes.  Really check that input & output tape not same device. */ 
  13. /* Add some statistics.  Use dynamic buffers & pointers, rather than fixed, */
  14. /* to save space.  Etc. */
  15.  
  16. /* Includes */
  17.  
  18. #include <stdio.h>            /* standard i/o */
  19. #include <sys/types.h>            /* data types needed by below */
  20. #include <sys/mtio.h>            /* magtape i/o */
  21. #include <sys/ioctl.h>            /* i/o control */
  22.  
  23. /* I/O descriptors, flags, etc. */
  24.  
  25. int in, out;                /* input, output tapes */
  26. int teof;                /* input tape eof flag */
  27. int debug = 0, dv = 0;            /* command line option flags */
  28. long copyfile();            /* forward dcl of non-int function */
  29.  
  30. /* Tape stuff */
  31.  
  32. char *indef = "/dev/rmt12";        /* default input drive */
  33. char *outdef = "/dev/rmt13";        /* default output drive */
  34. char *intape = "";
  35. char *outape = "";
  36. struct mtop mtx;            /* tape i/o structure for ioctl */
  37.  
  38. /* Buffer stuff */
  39.  
  40. #define BLKSIZE 30*1024            /* I/O buffer size */
  41. #define BLOCKS 10            /* Number of buffers */
  42. int maxblock = BLKSIZE;
  43. char buf[BLOCKS][BLKSIZE];        /* Declare buffer array */
  44. int buflen[BLOCKS];            /* & array of data lengths per buf */
  45.  
  46. char errbuf[100];            /* Buffer for making error strings */
  47.  
  48. /* Main program */
  49.  
  50. main(argc,argv) int argc; char *argv[]; {
  51.  
  52.     long ct, files, bytes = 0L;
  53.     int filenum = 1;
  54.     char x, *xp;
  55.  
  56.     while (--argc > 0) {        /* Parse options */
  57.     argv++;
  58.     if (**argv == '-') {
  59.         x = *(*argv+1);        /* Option letter */
  60.         xp = *argv+1;        /* Point past dash */
  61.         while (x) {            /* Loop thru bundled options */
  62.         switch(x) {
  63.           case 'd':        /* Debugging display */
  64.             debug = 1;
  65.             break;
  66.           case 'f':        /* From device */
  67.             if (*(xp+1)) fatal("Invalid argument bundling");
  68.             intape = *++argv;
  69.             argc--;
  70.             if (*intape == '-' || argc <= 0)
  71.               fatal("-f argument missing");
  72.             break;
  73.           case 't':        /* To device */
  74.             if (*(xp+1)) fatal("Invalid argument bundling");
  75.             outape = *++argv;
  76.             argc--;
  77.             if (*outape == '-' || argc <= 0)
  78.               fatal("-t argument missing");
  79.             break;
  80.           case 'v':        /* Version info */
  81.             dv = 1;
  82.             break;
  83.           default  : usage();
  84.             }
  85.         x = *++xp;        /* See if options are bundled */
  86.         }
  87.     } else usage();
  88.     }
  89.     if (debug || dv) {            /* Display version info if asked */
  90.     fprintf(stderr,"%s\n",vers);
  91.     fprintf(stderr,"%d buffers, %d bytes each\n\n",BLOCKS,maxblock);
  92.     }
  93.   
  94.     if (!*intape) intape = indef;    /* Supply defaults */
  95.     if (!*outape) outape = outdef;
  96.     if (strcmp(intape,"0") == 0) intape = indef;
  97.     if (strcmp(intape,"1") == 0) intape = outdef;
  98.     if (strcmp(outape,"0") == 0) outape = indef;
  99.     if (strcmp(outape,"1") == 0) outape = outdef;
  100.     if (strcmp(outape,intape) == 0) {
  101.     fprintf(stderr,"You must specify two different tape drives\n");
  102.     exit(1);
  103.     }
  104.     if (debug) {
  105.     fprintf(stderr,"input drive: %s\n",intape);
  106.     fprintf(stderr,"output drive: %s\n",outape);
  107.     }
  108.     in = open(intape, 0);        /* Open input tape */
  109.     if (in > 0)
  110.       printf("Reading from tape '%s'\n", intape);
  111.     else {
  112.     sprintf(errbuf,"Can't open tape %s for reading",intape);
  113.     fatal(errbuf);
  114.     }
  115.     if (rew(in) < 0)             /* Rewind to load point */
  116.        fatal("Can't rewind input tape");
  117.  
  118.     out = open(outape, 1);        /* Open output tape */
  119.     if (out > 0)
  120.       printf("Writing to tape '%s'\n", outape);
  121.     else {
  122.     sprintf(errbuf,"Can't open tape %s for writing",outape);
  123.     fatal(errbuf);
  124.     }
  125.     if (rew(out) < 0)             /* Rewind to load point */
  126.        fatal("Can't rewind output tape");
  127.  
  128.     system("date");            /* Say when starting */
  129.     ct = files = 1;            /* Initialize counters */
  130.     while (ct) {            /* Copy each file on tape */
  131.       if (debug) fprintf(stderr,"\nfile %ld:", files);
  132.       ct = copyfile();            /* Copy the file */
  133.       files++;                /* Count the file */
  134.       bytes += ct;            /* Accumulate total byte count */
  135.     }
  136.     tapemark(out);            /* Write final tapemark */
  137.     close(out);                /* Close tape drives */
  138.     close(in);
  139.     system("date");            /* When done, print messages */
  140.     printf("\nDone, copied %ld bytes in %ld file(s)\n", bytes, (files - 1));
  141.     exit(0);
  142. }
  143.  
  144. long                    /* Copy a file from in to out */
  145. copyfile() {                /* Returns number of bytes read */
  146.  
  147.     int i, blks;            /* Loop control, block count */
  148.     long ct = 0;            /* Character count */
  149.  
  150.     teof = 0;                /* Copy tape blocks till tape eof */
  151.                     /* Do several buffers at a time */
  152.     while (!teof) {
  153.  
  154.     for (blks = i = 0; i < BLOCKS; i++) { /* Read some buffers */
  155.  
  156.         if ((buflen[i] = read(in, buf[i], BLKSIZE)) < 0)
  157.           fatal("I/O error reading tape");
  158.         else if (buflen[i] > 0) {
  159.         blks++;            /* Count this block */
  160.         if (debug) fprintf(stderr," %d:%d",i,buflen[i]);
  161.         } else {            /* Count of 0 means end of tape file */
  162.         if (debug) fprintf(stderr," eof"); 
  163.         teof = 1;        /* Flag tape file eof. */
  164.         break;
  165.         }
  166.     }
  167.     if (debug) fprintf(stderr," [%d]",blks); /* # of blocks read */
  168.  
  169.     for (i = 0; i < blks; i++) {    /* Write out the buffers. */
  170.  
  171.         if (debug) fprintf(stderr," w%d:%d",i,buflen[i]);
  172.         if (write(out, buf[i], buflen[i]) != buflen[i])
  173.           fatal("Write error");
  174.         ct += buflen[i];        /* Keep track of # of bytes written */
  175.         buflen[i] = 0;
  176.     }
  177.     }
  178.     if (debug) fprintf(stderr," tm");
  179.     if (tapemark(out) < 0)        /* Write file mark. */
  180.       fatal("Can't write tape mark");
  181.     return(ct);                /* Return output byte count. */
  182. }
  183.  
  184. tapemark(tf) int tf; {            /* Write a tapemark (file mark) */
  185.     mtx.mt_count = 1;
  186.     mtx.mt_op = MTWEOF;
  187.     return(ioctl(tf, MTIOCTOP, (char *) &mtx));
  188. }
  189.  
  190. rew(tf) int tf; {            /* Rewind tape */
  191.     mtx.mt_op = MTREW;
  192.     return(ioctl(tf, MTIOCTOP, (char *) &mtx));
  193. }
  194.  
  195. fatal(s) char *s; {            /* Fatal error message and exit */
  196.     perror(s);                /* Include last system error */
  197.     exit(1);
  198. }
  199.  
  200. usage() {
  201.     fprintf(stderr,"usage: copytape [-d -v -f intape -t outtape]\n");
  202.     fprintf(stderr,"-d=debug, -v=version, -f=from, -t=to\n");
  203.     fprintf(stderr,"intape default %s, outtape default %s\n",indef,outdef);
  204.     fprintf(stderr,"maximum blocksize: %ld.\n",maxblock);
  205.     fprintf(stderr,"number of blocks buffered: %d.\n",BLOCKS);
  206.     exit(1);
  207. }
  208.