124973Sbloom /* 230870Skarels * Copyright (c) 1985, 1987 Regents of the University of California. 332759Sbostic * All rights reserved. 432759Sbostic * 542770Sbostic * %sccs.include.redist.c% 624973Sbloom */ 724973Sbloom 824973Sbloom #ifndef lint 924973Sbloom char copyright[] = 1030870Skarels "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\ 1124973Sbloom All rights reserved.\n"; 1232759Sbostic #endif /* not lint */ 1324973Sbloom 1424973Sbloom #ifndef lint 15*45518Skarels static char sccsid[] = "@(#)tcopy.c 5.15 (Berkeley) 11/05/90"; 1632759Sbostic #endif /* not lint */ 1724973Sbloom 1837859Sbostic #include <sys/types.h> 1937859Sbostic #include <sys/signal.h> 2024973Sbloom #include <sys/file.h> 2124973Sbloom #include <sys/ioctl.h> 2224973Sbloom #include <sys/mtio.h> 2330873Skarels #include <sys/errno.h> 2437859Sbostic #include <stdio.h> 2537859Sbostic #include "pathnames.h" 2624973Sbloom 2734185Sbostic #define MAXREC (64 * 1024) 2834185Sbostic #define NOCOUNT (-2) 2934185Sbostic 3034185Sbostic int filen, guesslen, maxblk = MAXREC; 3134185Sbostic long lastrec, record, size, tsize; 3224973Sbloom 3324973Sbloom main(argc, argv) 3432759Sbostic int argc; 3532759Sbostic char **argv; 3624973Sbloom { 3734185Sbostic extern char *optarg; 3834185Sbostic extern int optind, errno; 3934185Sbostic register int lastnread, nread, nw, inp, outp; 4034185Sbostic enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; 4139834Sbostic sig_t oldsig; 4239834Sbostic int ch, needeof; 4334185Sbostic char *buff, *inf, *getspace(); 4439834Sbostic void intr(); 4524973Sbloom 4634185Sbostic guesslen = 1; 4734185Sbostic while ((ch = getopt(argc, argv, "cs:v")) != EOF) 4834185Sbostic switch((char)ch) { 4934185Sbostic case 'c': 5034185Sbostic op = COPYVERIFY; 5134185Sbostic break; 5230870Skarels case 's': 5334185Sbostic maxblk = atoi(optarg); 5430870Skarels if (maxblk <= 0) { 5536197Sbostic fprintf(stderr, "tcopy: illegal block size\n"); 5634185Sbostic usage(); 5730870Skarels } 5830870Skarels guesslen = 0; 5930870Skarels break; 6034185Sbostic case 'v': 6134185Sbostic op = VERIFY; 6234185Sbostic break; 6334185Sbostic case '?': 6434185Sbostic default: 6534185Sbostic usage(); 6630870Skarels } 6734185Sbostic argc -= optind; 6834185Sbostic argv += optind; 6934185Sbostic 7034185Sbostic switch(argc) { 7134185Sbostic case 0: 7234185Sbostic if (op != READ) 7334185Sbostic usage(); 7437859Sbostic inf = _PATH_DEFTAPE; 7534185Sbostic break; 7634185Sbostic case 1: 7734185Sbostic if (op != READ) 7834185Sbostic usage(); 7934185Sbostic inf = argv[0]; 8034185Sbostic break; 8134185Sbostic case 2: 8234185Sbostic if (op == READ) 8334185Sbostic op = COPY; 8434185Sbostic inf = argv[0]; 8534954Sbostic if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR, 8634954Sbostic 0666)) < 0) { 8734185Sbostic perror(argv[1]); 8834185Sbostic exit(3); 8934185Sbostic } 9034185Sbostic break; 9134185Sbostic default: 9234185Sbostic usage(); 9330870Skarels } 9434185Sbostic 9530870Skarels if ((inp = open(inf, O_RDONLY, 0)) < 0) { 9630870Skarels perror(inf); 9730870Skarels exit(1); 9830870Skarels } 9934185Sbostic 10034185Sbostic buff = getspace(maxblk); 10134185Sbostic 10234185Sbostic if (op == VERIFY) { 10334185Sbostic verify(inp, outp, buff); 10434185Sbostic exit(0); 10524973Sbloom } 10634185Sbostic 10734185Sbostic if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) 10830870Skarels (void) signal(SIGINT, intr); 10934185Sbostic 11034185Sbostic needeof = 0; 11134185Sbostic for (lastnread = NOCOUNT;;) { 11234185Sbostic if ((nread = read(inp, buff, maxblk)) == -1) { 11334185Sbostic while (errno == EINVAL && (maxblk -= 1024)) { 11434185Sbostic nread = read(inp, buff, maxblk); 11534185Sbostic if (nread >= 0) 11634185Sbostic goto r1; 11730870Skarels } 11832759Sbostic fprintf(stderr, "read error, file %d, record %ld: ", 11930870Skarels filen, record); 12030870Skarels perror(""); 12134185Sbostic exit(1); 12234185Sbostic } else if (nread != lastnread) { 12334185Sbostic if (lastnread != 0 && lastnread != NOCOUNT) { 12430870Skarels if (lastrec == 0 && nread == 0) 12532759Sbostic printf("%ld records\n", record); 12630870Skarels else if (record - lastrec > 1) 12730870Skarels printf("records %ld to %ld\n", 12830870Skarels lastrec, record); 12930870Skarels else 13030870Skarels printf("record %ld\n", lastrec); 13130870Skarels } 13230870Skarels if (nread != 0) 13330870Skarels printf("file %d: block size %d: ", 13430870Skarels filen, nread); 13532759Sbostic (void) fflush(stdout); 13630870Skarels lastrec = record; 13724973Sbloom } 13834185Sbostic r1: guesslen = 0; 13930870Skarels if (nread > 0) { 140*45518Skarels if (op == COPY || op == COPYVERIFY) { 14130870Skarels if (needeof) { 14234185Sbostic writeop(outp, MTWEOF); 14334185Sbostic needeof = 0; 14430870Skarels } 14530870Skarels nw = write(outp, buff, nread); 14630870Skarels if (nw != nread) { 14730870Skarels fprintf(stderr, 14832759Sbostic "write error, file %d, record %ld: ", 14930870Skarels filen, record); 15030870Skarels if (nw == -1) 15130870Skarels perror(""); 15230870Skarels else 15330870Skarels fprintf(stderr, 15430870Skarels "write (%d) != read (%d)\n", 15530870Skarels nw, nread); 15630870Skarels fprintf(stderr, "copy aborted\n"); 15730870Skarels exit(5); 15830870Skarels } 15930870Skarels } 16030870Skarels size += nread; 16130870Skarels record++; 16230870Skarels } else { 16334185Sbostic if (lastnread <= 0 && lastnread != NOCOUNT) { 16424973Sbloom printf("eot\n"); 16524973Sbloom break; 16624973Sbloom } 16724973Sbloom printf("file %d: eof after %ld records: %ld bytes\n", 16830870Skarels filen, record, size); 16930870Skarels needeof = 1; 17024973Sbloom filen++; 17124973Sbloom tsize += size; 17234185Sbostic size = record = lastrec = 0; 17334185Sbostic lastnread = 0; 17424973Sbloom } 17534185Sbostic lastnread = nread; 17624973Sbloom } 17724973Sbloom printf("total length: %ld bytes\n", tsize); 17834185Sbostic (void)signal(SIGINT, oldsig); 179*45518Skarels if (op == COPY || op == COPYVERIFY) { 18034185Sbostic writeop(outp, MTWEOF); 18134185Sbostic writeop(outp, MTWEOF); 18234185Sbostic if (op == COPYVERIFY) { 18334185Sbostic writeop(outp, MTREW); 18434185Sbostic writeop(inp, MTREW); 18534185Sbostic verify(inp, outp, buff); 18634185Sbostic } 18734185Sbostic } 18834185Sbostic exit(0); 18924973Sbloom } 19024973Sbloom 19134185Sbostic verify(inp, outp, outb) 19234185Sbostic register int inp, outp; 19334185Sbostic register char *outb; 19434185Sbostic { 19535696Sbostic extern int errno; 19634185Sbostic register int eot, inmaxblk, inn, outmaxblk, outn; 19734185Sbostic register char *inb; 19834185Sbostic char *getspace(); 19934185Sbostic 20034185Sbostic inb = getspace(maxblk); 20134185Sbostic inmaxblk = outmaxblk = maxblk; 20234185Sbostic for (eot = 0;; guesslen = 0) { 20334185Sbostic if ((inn = read(inp, inb, inmaxblk)) == -1) { 20434185Sbostic if (guesslen) 20534185Sbostic while (errno == EINVAL && (inmaxblk -= 1024)) { 20634185Sbostic inn = read(inp, inb, inmaxblk); 20734185Sbostic if (inn >= 0) 20834185Sbostic goto r1; 20934185Sbostic } 21034185Sbostic perror("tcopy: read error"); 21136197Sbostic break; 21234185Sbostic } 21334185Sbostic r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { 21434185Sbostic if (guesslen) 21534185Sbostic while (errno == EINVAL && (outmaxblk -= 1024)) { 21634185Sbostic outn = read(outp, outb, outmaxblk); 21734185Sbostic if (outn >= 0) 21834185Sbostic goto r2; 21934185Sbostic } 22034185Sbostic perror("tcopy: read error"); 22136197Sbostic break; 22234185Sbostic } 22336197Sbostic r2: if (inn != outn) { 22436197Sbostic printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn); 22534185Sbostic break; 22636197Sbostic } 22734185Sbostic if (!inn) { 22834185Sbostic if (eot++) { 22936197Sbostic printf("tcopy: tapes are identical.\n"); 23034185Sbostic return; 23134185Sbostic } 23234185Sbostic } else { 23336197Sbostic if (bcmp(inb, outb, inn)) { 23436197Sbostic printf("tcopy: tapes have different data.\n"); 23534185Sbostic break; 23636197Sbostic } 23734185Sbostic eot = 0; 23834185Sbostic } 23934185Sbostic } 24034185Sbostic exit(1); 24134185Sbostic } 24234185Sbostic 24339834Sbostic void 24430870Skarels intr() 24524973Sbloom { 24630870Skarels if (record) 24730870Skarels if (record - lastrec > 1) 24830870Skarels printf("records %ld to %ld\n", lastrec, record); 24924973Sbloom else 25030870Skarels printf("record %ld\n", lastrec); 25130870Skarels printf("interrupt at file %d: record %ld\n", filen, record); 25234185Sbostic printf("total length: %ld bytes\n", tsize + size); 25324973Sbloom exit(1); 25424973Sbloom } 25534185Sbostic 25635696Sbostic char * 25734185Sbostic getspace(blk) 25834185Sbostic int blk; 25934185Sbostic { 26034185Sbostic char *bp, *malloc(); 26134185Sbostic 26234185Sbostic if ((bp = malloc((u_int)blk)) == NULL) { 26336197Sbostic fprintf(stderr, "tcopy: no memory\n"); 26434185Sbostic exit(11); 26534185Sbostic } 26634185Sbostic return(bp); 26734185Sbostic } 26834185Sbostic 26934185Sbostic writeop(fd, type) 27034185Sbostic int fd, type; 27134185Sbostic { 27234185Sbostic struct mtop op; 27334185Sbostic 27434185Sbostic op.mt_op = type; 27534185Sbostic op.mt_count = (daddr_t)1; 27634185Sbostic if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { 27734185Sbostic perror("tcopy: tape op"); 27834185Sbostic exit(6); 27934185Sbostic } 28034185Sbostic } 28134185Sbostic 28234185Sbostic usage() 28334185Sbostic { 28436197Sbostic fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n"); 28534185Sbostic exit(1); 28634185Sbostic } 287