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

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