home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / tcopy / tcopy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  7.2 KB  |  313 lines

  1. /*
  2.  * Copyright (c) 1985, 1987 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)tcopy.c    5.15 (Berkeley) 11/5/90";
  42. #endif /* not lint */
  43.  
  44. #include <sys/types.h>
  45. #include <sys/signal.h>
  46. #include <sys/file.h>
  47. #include <sys/ioctl.h>
  48. #include <sys/mtio.h>
  49. #include <sys/errno.h>
  50. #include <stdio.h>
  51. #include "pathnames.h"
  52.  
  53. #define    MAXREC    (64 * 1024)
  54. #define    NOCOUNT    (-2)
  55.  
  56. int    filen, guesslen, maxblk = MAXREC;
  57. long    lastrec, record, size, tsize;
  58.  
  59. main(argc, argv)
  60.     int argc;
  61.     char **argv;
  62. {
  63.     extern char *optarg;
  64.     extern int optind, errno;
  65.     register int lastnread, nread, nw, inp, outp;
  66.     enum {READ, VERIFY, COPY, COPYVERIFY} op = READ;
  67.     sig_t oldsig;
  68.     int ch, needeof;
  69.     char *buff, *inf, *getspace();
  70.     void intr();
  71.  
  72.     guesslen = 1;
  73.     while ((ch = getopt(argc, argv, "cs:v")) != EOF)
  74.         switch((char)ch) {
  75.         case 'c':
  76.             op = COPYVERIFY;
  77.             break;
  78.         case 's':
  79.             maxblk = atoi(optarg);
  80.             if (maxblk <= 0) {
  81.                 fprintf(stderr, "tcopy: illegal block size\n");
  82.                 usage();
  83.             }
  84.             guesslen = 0;
  85.             break;
  86.         case 'v':
  87.             op = VERIFY;
  88.             break;
  89.         case '?':
  90.         default:
  91.             usage();
  92.         }
  93.     argc -= optind;
  94.     argv += optind;
  95.  
  96.     switch(argc) {
  97.     case 0:
  98.         if (op != READ)
  99.             usage();
  100.         inf = _PATH_DEFTAPE;
  101.         break;
  102.     case 1:
  103.         if (op != READ)
  104.             usage();
  105.         inf = argv[0];
  106.         break;
  107.     case 2:
  108.         if (op == READ)
  109.             op = COPY;
  110.         inf = argv[0];
  111.         if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR,
  112.             0666)) < 0) {
  113.             perror(argv[1]);
  114.             exit(3);
  115.         }
  116.         break;
  117.     default:
  118.         usage();
  119.     }
  120.  
  121.     if ((inp = open(inf, O_RDONLY, 0)) < 0) {
  122.         perror(inf);
  123.         exit(1);
  124.     }
  125.  
  126.     buff = getspace(maxblk);
  127.  
  128.     if (op == VERIFY) {
  129.         verify(inp, outp, buff);
  130.         exit(0);
  131.     }
  132.  
  133.     if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
  134.         (void) signal(SIGINT, intr);
  135.  
  136.     needeof = 0;
  137.     for (lastnread = NOCOUNT;;) {
  138.         if ((nread = read(inp, buff, maxblk)) == -1) {
  139.             while (errno == EINVAL && (maxblk -= 1024)) {
  140.                 nread = read(inp, buff, maxblk);
  141.                 if (nread >= 0)
  142.                     goto r1;
  143.             }
  144.             fprintf(stderr, "read error, file %d, record %ld: ",
  145.                 filen, record);
  146.             perror("");
  147.             exit(1);
  148.         } else if (nread != lastnread) {
  149.             if (lastnread != 0 && lastnread != NOCOUNT) {
  150.                 if (lastrec == 0 && nread == 0)
  151.                     printf("%ld records\n", record);
  152.                 else if (record - lastrec > 1)
  153.                     printf("records %ld to %ld\n",
  154.                         lastrec, record);
  155.                 else
  156.                     printf("record %ld\n", lastrec);
  157.             }
  158.             if (nread != 0)
  159.                 printf("file %d: block size %d: ",
  160.                     filen, nread);
  161.             (void) fflush(stdout);
  162.             lastrec = record;
  163.         }
  164. r1:        guesslen = 0;
  165.         if (nread > 0) {
  166.             if (op == COPY || op == COPYVERIFY) {
  167.                 if (needeof) {
  168.                     writeop(outp, MTWEOF);
  169.                     needeof = 0;
  170.                 }
  171.                 nw = write(outp, buff, nread);
  172.                 if (nw != nread) {
  173.                     fprintf(stderr,
  174.                     "write error, file %d, record %ld: ",
  175.                     filen, record);
  176.                     if (nw == -1)
  177.                     perror("");
  178.                     else
  179.                     fprintf(stderr,
  180.                         "write (%d) != read (%d)\n",
  181.                         nw, nread);
  182.                     fprintf(stderr, "copy aborted\n");
  183.                     exit(5);
  184.                 }
  185.             }
  186.             size += nread;
  187.             record++;
  188.         } else {
  189.             if (lastnread <= 0 && lastnread != NOCOUNT) {
  190.                 printf("eot\n");
  191.                 break;
  192.             }
  193.             printf("file %d: eof after %ld records: %ld bytes\n",
  194.                 filen, record, size);
  195.             needeof = 1;
  196.             filen++;
  197.             tsize += size;
  198.             size = record = lastrec = 0;
  199.             lastnread = 0;
  200.         }
  201.         lastnread = nread;
  202.     }
  203.     printf("total length: %ld bytes\n", tsize);
  204.     (void)signal(SIGINT, oldsig);
  205.     if (op == COPY || op == COPYVERIFY) {
  206.         writeop(outp, MTWEOF);
  207.         writeop(outp, MTWEOF);
  208.         if (op == COPYVERIFY) {
  209.             writeop(outp, MTREW);
  210.             writeop(inp, MTREW);
  211.             verify(inp, outp, buff);
  212.         }
  213.     }
  214.     exit(0);
  215. }
  216.  
  217. verify(inp, outp, outb)
  218.     register int inp, outp;
  219.     register char *outb;
  220. {
  221.     extern int errno;
  222.     register int eot, inmaxblk, inn, outmaxblk, outn;
  223.     register char *inb;
  224.     char *getspace();
  225.  
  226.     inb = getspace(maxblk);
  227.     inmaxblk = outmaxblk = maxblk;
  228.     for (eot = 0;; guesslen = 0) {
  229.         if ((inn = read(inp, inb, inmaxblk)) == -1) {
  230.             if (guesslen)
  231.                 while (errno == EINVAL && (inmaxblk -= 1024)) {
  232.                     inn = read(inp, inb, inmaxblk);
  233.                     if (inn >= 0)
  234.                         goto r1;
  235.                 }
  236.             perror("tcopy: read error");
  237.             break;
  238.         }
  239. r1:        if ((outn = read(outp, outb, outmaxblk)) == -1) {
  240.             if (guesslen)
  241.                 while (errno == EINVAL && (outmaxblk -= 1024)) {
  242.                     outn = read(outp, outb, outmaxblk);
  243.                     if (outn >= 0)
  244.                         goto r2;
  245.                 }
  246.             perror("tcopy: read error");
  247.             break;
  248.         }
  249. r2:        if (inn != outn) {
  250.             printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn);
  251.             break;
  252.         }
  253.         if (!inn) {
  254.             if (eot++) {
  255.                 printf("tcopy: tapes are identical.\n");
  256.                 return;
  257.             }
  258.         } else {
  259.             if (bcmp(inb, outb, inn)) {
  260.                 printf("tcopy: tapes have different data.\n");
  261.                 break;
  262.             }
  263.             eot = 0;
  264.         }
  265.     }
  266.     exit(1);
  267. }
  268.  
  269. void
  270. intr()
  271. {
  272.     if (record)
  273.         if (record - lastrec > 1)
  274.             printf("records %ld to %ld\n", lastrec, record);
  275.         else
  276.             printf("record %ld\n", lastrec);
  277.     printf("interrupt at file %d: record %ld\n", filen, record);
  278.     printf("total length: %ld bytes\n", tsize + size);
  279.     exit(1);
  280. }
  281.  
  282. char *
  283. getspace(blk)
  284.     int blk;
  285. {
  286.     char *bp, *malloc();
  287.  
  288.     if ((bp = malloc((u_int)blk)) == NULL) {
  289.         fprintf(stderr, "tcopy: no memory\n");
  290.         exit(11);
  291.     }
  292.     return(bp);
  293. }
  294.  
  295. writeop(fd, type)
  296.     int fd, type;
  297. {
  298.     struct mtop op;
  299.  
  300.     op.mt_op = type;
  301.     op.mt_count = (daddr_t)1;
  302.     if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) {
  303.         perror("tcopy: tape op");
  304.         exit(6);
  305.     }
  306. }
  307.  
  308. usage()
  309. {
  310.     fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n");
  311.     exit(1);
  312. }
  313.