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: }