[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.10

1.10    ! deraadt     1: /*     $OpenBSD: tcopy.c,v 1.9 2003/06/10 22:20:53 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: #ifndef lint
                     34: static char copyright[] =
                     35: "@(#) Copyright (c) 1985, 1987, 1993\n\
                     36:        The Regents of the University of California.  All rights reserved.\n";
                     37: #endif /* not lint */
                     38:
                     39: #ifndef lint
                     40: #if 0
                     41: static char sccsid[] = "@(#)tcopy.c    8.3 (Berkeley) 1/23/95";
                     42: #endif
1.10    ! deraadt    43: static char rcsid[] = "$OpenBSD: tcopy.c,v 1.9 2003/06/10 22:20:53 deraadt Exp $";
1.1       deraadt    44: #endif /* not lint */
                     45:
                     46: #include <sys/types.h>
                     47: #include <sys/stat.h>
                     48: #include <sys/ioctl.h>
                     49: #include <sys/mtio.h>
                     50:
                     51: #include <err.h>
                     52: #include <errno.h>
                     53: #include <fcntl.h>
1.4       millert    54: #include <paths.h>
1.1       deraadt    55: #include <signal.h>
                     56: #include <stdio.h>
                     57: #include <stdlib.h>
                     58: #include <string.h>
                     59: #include <unistd.h>
                     60:
                     61: #define        MAXREC  (64 * 1024)
                     62: #define        NOCOUNT (-2)
                     63:
                     64: int    filen, guesslen, maxblk = MAXREC;
                     65: long   lastrec, record;
                     66: off_t  size, tsize;
                     67: FILE   *msg = stdout;
                     68:
1.7       millert    69: void   *getspace(int);
                     70: void    intr(int);
                     71: void    usage(void);
                     72: void    verify(int, int, char *);
                     73: void    writeop(int, int);
1.1       deraadt    74:
                     75: int
1.9       deraadt    76: main(int argc, char *argv[])
1.1       deraadt    77: {
                     78:        int ch, needeof, nw, inp, outp;
                     79:        ssize_t lastnread, nread;
                     80:        enum {READ, VERIFY, COPY, COPYVERIFY} op = READ;
                     81:        sig_t oldsig;
                     82:        char *buff, *inf;
                     83:
                     84:        guesslen = 1;
1.3       millert    85:        while ((ch = getopt(argc, argv, "cs:vx")) != -1)
1.1       deraadt    86:                switch((char)ch) {
                     87:                case 'c':
                     88:                        op = COPYVERIFY;
                     89:                        break;
                     90:                case 's':
                     91:                        maxblk = atoi(optarg);
                     92:                        if (maxblk <= 0) {
                     93:                                warnx("illegal block size");
                     94:                                usage();
                     95:                        }
                     96:                        guesslen = 0;
                     97:                        break;
                     98:                case 'v':
                     99:                        op = VERIFY;
                    100:                        break;
                    101:                case 'x':
                    102:                        msg = stderr;
                    103:                        break;
                    104:                case '?':
                    105:                default:
                    106:                        usage();
                    107:                }
                    108:        argc -= optind;
                    109:        argv += optind;
                    110:
                    111:        switch(argc) {
                    112:        case 0:
                    113:                if (op != READ)
                    114:                        usage();
                    115:                inf = _PATH_DEFTAPE;
                    116:                break;
                    117:        case 1:
                    118:                if (op != READ)
                    119:                        usage();
                    120:                inf = argv[0];
                    121:                break;
                    122:        case 2:
                    123:                if (op == READ)
                    124:                        op = COPY;
                    125:                inf = argv[0];
                    126:                if ((outp = open(argv[1], op == VERIFY ? O_RDONLY :
                    127:                    op == COPY ? O_WRONLY : O_RDWR, DEFFILEMODE)) < 0) {
1.5       millert   128:                        err(3, "%s", argv[1]);
1.1       deraadt   129:                }
                    130:                break;
                    131:        default:
                    132:                usage();
                    133:        }
                    134:
                    135:        if ((inp = open(inf, O_RDONLY, 0)) < 0)
1.5       millert   136:                err(1, "%s", inf);
1.1       deraadt   137:
                    138:        buff = getspace(maxblk);
                    139:
                    140:        if (op == VERIFY) {
                    141:                verify(inp, outp, buff);
                    142:                exit(0);
                    143:        }
                    144:
                    145:        if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
                    146:                (void) signal(SIGINT, intr);
                    147:
                    148:        needeof = 0;
                    149:        for (lastnread = NOCOUNT;;) {
                    150:                if ((nread = read(inp, buff, maxblk)) == -1) {
                    151:                        while (errno == EINVAL && (maxblk -= 1024)) {
                    152:                                nread = read(inp, buff, maxblk);
                    153:                                if (nread >= 0)
                    154:                                        goto r1;
                    155:                        }
                    156:                        err(1, "read error, file %d, record %ld",
                    157:                            filen, record);
                    158:                } else if (nread != lastnread) {
                    159:                        if (lastnread != 0 && lastnread != NOCOUNT) {
                    160:                                if (lastrec == 0 && nread == 0)
                    161:                                        fprintf(msg, "%ld records\n", record);
                    162:                                else if (record - lastrec > 1)
                    163:                                        fprintf(msg, "records %ld to %ld\n",
                    164:                                            lastrec, record);
                    165:                                else
                    166:                                        fprintf(msg, "record %ld\n", lastrec);
                    167:                        }
                    168:                        if (nread != 0)
1.6       deraadt   169:                                fprintf(msg, "file %d: block size %ld: ",
                    170:                                    filen, (long)nread);
1.1       deraadt   171:                        (void) fflush(stdout);
                    172:                        lastrec = record;
                    173:                }
                    174: r1:            guesslen = 0;
                    175:                if (nread > 0) {
                    176:                        if (op == COPY || op == COPYVERIFY) {
                    177:                                if (needeof) {
                    178:                                        writeop(outp, MTWEOF);
                    179:                                        needeof = 0;
                    180:                                }
                    181:                                nw = write(outp, buff, nread);
                    182:                                if (nw != nread) {
                    183:                                    int error = errno;
                    184:                                    fprintf(stderr,
                    185:                                        "write error, file %d, record %ld: ",
                    186:                                        filen, record);
                    187:                                    if (nw == -1)
                    188:                                        fprintf(stderr,
                    189:                                                ": %s", strerror(error));
                    190:                                    else
                    191:                                        fprintf(stderr,
1.6       deraadt   192:                                            "write (%d) != read (%ld)\n",
                    193:                                            nw, (long)nread);
1.1       deraadt   194:                                    fprintf(stderr, "copy aborted\n");
                    195:                                    exit(5);
                    196:                                }
                    197:                        }
                    198:                        size += nread;
                    199:                        record++;
                    200:                } else {
                    201:                        if (lastnread <= 0 && lastnread != NOCOUNT) {
                    202:                                fprintf(msg, "eot\n");
                    203:                                break;
                    204:                        }
                    205:                        fprintf(msg,
1.6       deraadt   206:                            "file %d: eof after %ld records: %lld bytes\n",
                    207:                            filen, record, (long long)size);
1.1       deraadt   208:                        needeof = 1;
                    209:                        filen++;
                    210:                        tsize += size;
                    211:                        size = record = lastrec = 0;
                    212:                        lastnread = 0;
                    213:                }
                    214:                lastnread = nread;
                    215:        }
1.6       deraadt   216:        fprintf(msg, "total length: %lld bytes\n", (long long)tsize);
1.1       deraadt   217:        (void)signal(SIGINT, oldsig);
                    218:        if (op == COPY || op == COPYVERIFY) {
                    219:                writeop(outp, MTWEOF);
                    220:                writeop(outp, MTWEOF);
                    221:                if (op == COPYVERIFY) {
                    222:                        writeop(outp, MTREW);
                    223:                        writeop(inp, MTREW);
                    224:                        verify(inp, outp, buff);
                    225:                }
                    226:        }
                    227:        exit(0);
                    228: }
                    229:
                    230: void
1.9       deraadt   231: verify(int inp, int outp, char *outb)
1.1       deraadt   232: {
                    233:        int eot, inmaxblk, inn, outmaxblk, outn;
                    234:        char *inb;
                    235:
                    236:        inb = getspace(maxblk);
                    237:        inmaxblk = outmaxblk = maxblk;
                    238:        for (eot = 0;; guesslen = 0) {
                    239:                if ((inn = read(inp, inb, inmaxblk)) == -1) {
                    240:                        if (guesslen)
                    241:                                while (errno == EINVAL && (inmaxblk -= 1024)) {
                    242:                                        inn = read(inp, inb, inmaxblk);
                    243:                                        if (inn >= 0)
                    244:                                                goto r1;
                    245:                                }
                    246:                        warn("read error");
                    247:                        break;
                    248:                }
                    249: r1:            if ((outn = read(outp, outb, outmaxblk)) == -1) {
                    250:                        if (guesslen)
                    251:                                while (errno == EINVAL && (outmaxblk -= 1024)) {
                    252:                                        outn = read(outp, outb, outmaxblk);
                    253:                                        if (outn >= 0)
                    254:                                                goto r2;
                    255:                                }
                    256:                        warn("read error");
                    257:                        break;
                    258:                }
                    259: r2:            if (inn != outn) {
                    260:                        fprintf(msg,
                    261:                            "%s: tapes have different block sizes; %d != %d.\n",
                    262:                            "tcopy", inn, outn);
                    263:                        break;
                    264:                }
                    265:                if (!inn) {
                    266:                        if (eot++) {
                    267:                                fprintf(msg, "%s: tapes are identical.\n",
                    268:                                        "tcopy");
                    269:                                return;
                    270:                        }
                    271:                } else {
                    272:                        if (bcmp(inb, outb, inn)) {
                    273:                                fprintf(msg,
                    274:                                    "%s: tapes have different data.\n",
                    275:                                        "tcopy");
                    276:                                break;
                    277:                        }
                    278:                        eot = 0;
                    279:                }
                    280:        }
                    281:        exit(1);
                    282: }
                    283:
                    284: void
1.9       deraadt   285: intr(int signo)
1.1       deraadt   286: {
1.6       deraadt   287:        if (record) {
1.1       deraadt   288:                if (record - lastrec > 1)
                    289:                        fprintf(msg, "records %ld to %ld\n", lastrec, record);
                    290:                else
                    291:                        fprintf(msg, "record %ld\n", lastrec);
1.6       deraadt   292:        }
1.1       deraadt   293:        fprintf(msg, "interrupt at file %d: record %ld\n", filen, record);
1.6       deraadt   294:        fprintf(msg, "total length: %lld bytes\n", (long long)(tsize + size));
1.1       deraadt   295:        exit(1);
                    296: }
                    297:
                    298: void *
1.9       deraadt   299: getspace(int blk)
1.1       deraadt   300: {
                    301:        void *bp;
                    302:
                    303:        if ((bp = malloc((size_t)blk)) == NULL)
                    304:                errx(11, "no memory");
                    305:
                    306:        return (bp);
                    307: }
                    308:
                    309: void
1.9       deraadt   310: writeop(int fd, int type)
1.1       deraadt   311: {
                    312:        struct mtop op;
                    313:
                    314:        op.mt_op = type;
1.10    ! deraadt   315:        op.mt_count = 1;
1.1       deraadt   316:        if (ioctl(fd, MTIOCTOP, (char *)&op) < 0)
                    317:                err(6, "tape op");
                    318: }
                    319:
                    320: void
1.9       deraadt   321: usage(void)
1.1       deraadt   322: {
                    323:
                    324:        fprintf(stderr, "usage: tcopy [-cvx] [-s maxblk] src [dest]\n");
                    325:        exit(1);
                    326: }