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

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