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

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