[BACK]Return to tcopy.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tcopy

Annotation of src/usr.bin/tcopy/tcopy.c, Revision 1.11

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