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*56106Sbostic static char sccsid[] = "@(#)tcopy.c 5.17 (Berkeley) 08/31/92"; 1632759Sbostic #endif /* not lint */ 1724973Sbloom 1837859Sbostic #include <sys/types.h> 19*56106Sbostic #include <sys/stat.h> 2024973Sbloom #include <sys/ioctl.h> 2124973Sbloom #include <sys/mtio.h> 22*56106Sbostic 23*56106Sbostic #include <errno.h> 24*56106Sbostic #include <fcntl.h> 2551629Sbostic #include <signal.h> 2637859Sbostic #include <stdio.h> 27*56106Sbostic #include <stdlib.h> 28*56106Sbostic #include <string.h> 29*56106Sbostic #include <unistd.h> 30*56106Sbostic 3137859Sbostic #include "pathnames.h" 3224973Sbloom 3334185Sbostic #define MAXREC (64 * 1024) 3434185Sbostic #define NOCOUNT (-2) 3534185Sbostic 3634185Sbostic int filen, guesslen, maxblk = MAXREC; 3734185Sbostic long lastrec, record, size, tsize; 3824973Sbloom 39*56106Sbostic void *getspace __P((int)); 40*56106Sbostic void intr __P((int)); 41*56106Sbostic void usage __P((void)); 42*56106Sbostic void verify __P((int, int, char *)); 43*56106Sbostic void writeop __P((int, int)); 44*56106Sbostic 45*56106Sbostic int 4624973Sbloom main(argc, argv) 4732759Sbostic int argc; 48*56106Sbostic char *argv[]; 4924973Sbloom { 5034185Sbostic register int lastnread, nread, nw, inp, outp; 5134185Sbostic enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; 5239834Sbostic sig_t oldsig; 5339834Sbostic int ch, needeof; 54*56106Sbostic char *buff, *inf; 5524973Sbloom 5634185Sbostic guesslen = 1; 5734185Sbostic while ((ch = getopt(argc, argv, "cs:v")) != EOF) 5834185Sbostic switch((char)ch) { 5934185Sbostic case 'c': 6034185Sbostic op = COPYVERIFY; 6134185Sbostic break; 6230870Skarels case 's': 6334185Sbostic maxblk = atoi(optarg); 6430870Skarels if (maxblk <= 0) { 6536197Sbostic fprintf(stderr, "tcopy: illegal block size\n"); 6634185Sbostic usage(); 6730870Skarels } 6830870Skarels guesslen = 0; 6930870Skarels break; 7034185Sbostic case 'v': 7134185Sbostic op = VERIFY; 7234185Sbostic break; 7334185Sbostic case '?': 7434185Sbostic default: 7534185Sbostic usage(); 7630870Skarels } 7734185Sbostic argc -= optind; 7834185Sbostic argv += optind; 7934185Sbostic 8034185Sbostic switch(argc) { 8134185Sbostic case 0: 8234185Sbostic if (op != READ) 8334185Sbostic usage(); 8437859Sbostic inf = _PATH_DEFTAPE; 8534185Sbostic break; 8634185Sbostic case 1: 8734185Sbostic if (op != READ) 8834185Sbostic usage(); 8934185Sbostic inf = argv[0]; 9034185Sbostic break; 9134185Sbostic case 2: 9234185Sbostic if (op == READ) 9334185Sbostic op = COPY; 9434185Sbostic inf = argv[0]; 9534954Sbostic if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR, 96*56106Sbostic DEFFILEMODE)) < 0) { 9734185Sbostic perror(argv[1]); 9834185Sbostic exit(3); 9934185Sbostic } 10034185Sbostic break; 10134185Sbostic default: 10234185Sbostic usage(); 10330870Skarels } 10434185Sbostic 10530870Skarels if ((inp = open(inf, O_RDONLY, 0)) < 0) { 10630870Skarels perror(inf); 10730870Skarels exit(1); 10830870Skarels } 10934185Sbostic 11034185Sbostic buff = getspace(maxblk); 11134185Sbostic 11234185Sbostic if (op == VERIFY) { 11334185Sbostic verify(inp, outp, buff); 11434185Sbostic exit(0); 11524973Sbloom } 11634185Sbostic 11734185Sbostic if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) 11830870Skarels (void) signal(SIGINT, intr); 11934185Sbostic 12034185Sbostic needeof = 0; 12134185Sbostic for (lastnread = NOCOUNT;;) { 12234185Sbostic if ((nread = read(inp, buff, maxblk)) == -1) { 12334185Sbostic while (errno == EINVAL && (maxblk -= 1024)) { 12434185Sbostic nread = read(inp, buff, maxblk); 12534185Sbostic if (nread >= 0) 12634185Sbostic goto r1; 12730870Skarels } 12832759Sbostic fprintf(stderr, "read error, file %d, record %ld: ", 12930870Skarels filen, record); 13030870Skarels perror(""); 13134185Sbostic exit(1); 13234185Sbostic } else if (nread != lastnread) { 13334185Sbostic if (lastnread != 0 && lastnread != NOCOUNT) { 13430870Skarels if (lastrec == 0 && nread == 0) 13532759Sbostic printf("%ld records\n", record); 13630870Skarels else if (record - lastrec > 1) 13730870Skarels printf("records %ld to %ld\n", 13830870Skarels lastrec, record); 13930870Skarels else 14030870Skarels printf("record %ld\n", lastrec); 14130870Skarels } 14230870Skarels if (nread != 0) 14330870Skarels printf("file %d: block size %d: ", 14430870Skarels filen, nread); 14532759Sbostic (void) fflush(stdout); 14630870Skarels lastrec = record; 14724973Sbloom } 14834185Sbostic r1: guesslen = 0; 14930870Skarels if (nread > 0) { 15045518Skarels if (op == COPY || op == COPYVERIFY) { 15130870Skarels if (needeof) { 15234185Sbostic writeop(outp, MTWEOF); 15334185Sbostic needeof = 0; 15430870Skarels } 15530870Skarels nw = write(outp, buff, nread); 15630870Skarels if (nw != nread) { 15730870Skarels fprintf(stderr, 15832759Sbostic "write error, file %d, record %ld: ", 15930870Skarels filen, record); 16030870Skarels if (nw == -1) 16130870Skarels perror(""); 16230870Skarels else 16330870Skarels fprintf(stderr, 16430870Skarels "write (%d) != read (%d)\n", 16530870Skarels nw, nread); 16630870Skarels fprintf(stderr, "copy aborted\n"); 16730870Skarels exit(5); 16830870Skarels } 16930870Skarels } 17030870Skarels size += nread; 17130870Skarels record++; 17230870Skarels } else { 17334185Sbostic if (lastnread <= 0 && lastnread != NOCOUNT) { 17424973Sbloom printf("eot\n"); 17524973Sbloom break; 17624973Sbloom } 17724973Sbloom printf("file %d: eof after %ld records: %ld bytes\n", 17830870Skarels filen, record, size); 17930870Skarels needeof = 1; 18024973Sbloom filen++; 18124973Sbloom tsize += size; 18234185Sbostic size = record = lastrec = 0; 18334185Sbostic lastnread = 0; 18424973Sbloom } 18534185Sbostic lastnread = nread; 18624973Sbloom } 18724973Sbloom printf("total length: %ld bytes\n", tsize); 18834185Sbostic (void)signal(SIGINT, oldsig); 18945518Skarels if (op == COPY || op == COPYVERIFY) { 19034185Sbostic writeop(outp, MTWEOF); 19134185Sbostic writeop(outp, MTWEOF); 19234185Sbostic if (op == COPYVERIFY) { 19334185Sbostic writeop(outp, MTREW); 19434185Sbostic writeop(inp, MTREW); 19534185Sbostic verify(inp, outp, buff); 19634185Sbostic } 19734185Sbostic } 19834185Sbostic exit(0); 19924973Sbloom } 20024973Sbloom 201*56106Sbostic void 20234185Sbostic verify(inp, outp, outb) 20334185Sbostic register int inp, outp; 20434185Sbostic register char *outb; 20534185Sbostic { 20634185Sbostic register int eot, inmaxblk, inn, outmaxblk, outn; 20734185Sbostic register char *inb; 20834185Sbostic 20934185Sbostic inb = getspace(maxblk); 21034185Sbostic inmaxblk = outmaxblk = maxblk; 21134185Sbostic for (eot = 0;; guesslen = 0) { 21234185Sbostic if ((inn = read(inp, inb, inmaxblk)) == -1) { 21334185Sbostic if (guesslen) 21434185Sbostic while (errno == EINVAL && (inmaxblk -= 1024)) { 21534185Sbostic inn = read(inp, inb, inmaxblk); 21634185Sbostic if (inn >= 0) 21734185Sbostic goto r1; 21834185Sbostic } 21934185Sbostic perror("tcopy: read error"); 22036197Sbostic break; 22134185Sbostic } 22234185Sbostic r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { 22334185Sbostic if (guesslen) 22434185Sbostic while (errno == EINVAL && (outmaxblk -= 1024)) { 22534185Sbostic outn = read(outp, outb, outmaxblk); 22634185Sbostic if (outn >= 0) 22734185Sbostic goto r2; 22834185Sbostic } 22934185Sbostic perror("tcopy: read error"); 23036197Sbostic break; 23134185Sbostic } 23236197Sbostic r2: if (inn != outn) { 23336197Sbostic printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn); 23434185Sbostic break; 23536197Sbostic } 23634185Sbostic if (!inn) { 23734185Sbostic if (eot++) { 23836197Sbostic printf("tcopy: tapes are identical.\n"); 23934185Sbostic return; 24034185Sbostic } 24134185Sbostic } else { 24236197Sbostic if (bcmp(inb, outb, inn)) { 24336197Sbostic printf("tcopy: tapes have different data.\n"); 24434185Sbostic break; 24536197Sbostic } 24634185Sbostic eot = 0; 24734185Sbostic } 24834185Sbostic } 24934185Sbostic exit(1); 25034185Sbostic } 25134185Sbostic 25239834Sbostic void 253*56106Sbostic intr(signo) 254*56106Sbostic int signo; 25524973Sbloom { 25630870Skarels if (record) 25730870Skarels if (record - lastrec > 1) 25830870Skarels printf("records %ld to %ld\n", lastrec, record); 25924973Sbloom else 26030870Skarels printf("record %ld\n", lastrec); 26130870Skarels printf("interrupt at file %d: record %ld\n", filen, record); 26234185Sbostic printf("total length: %ld bytes\n", tsize + size); 26324973Sbloom exit(1); 26424973Sbloom } 26534185Sbostic 266*56106Sbostic void * 26734185Sbostic getspace(blk) 26834185Sbostic int blk; 26934185Sbostic { 270*56106Sbostic void *bp; 27134185Sbostic 272*56106Sbostic if ((bp = malloc((size_t)blk)) == NULL) { 27336197Sbostic fprintf(stderr, "tcopy: no memory\n"); 27434185Sbostic exit(11); 27534185Sbostic } 276*56106Sbostic return (bp); 27734185Sbostic } 27834185Sbostic 279*56106Sbostic void 28034185Sbostic writeop(fd, type) 28134185Sbostic int fd, type; 28234185Sbostic { 28334185Sbostic struct mtop op; 28434185Sbostic 28534185Sbostic op.mt_op = type; 28634185Sbostic op.mt_count = (daddr_t)1; 28734185Sbostic if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { 28834185Sbostic perror("tcopy: tape op"); 28934185Sbostic exit(6); 29034185Sbostic } 29134185Sbostic } 29234185Sbostic 293*56106Sbostic void 29434185Sbostic usage() 29534185Sbostic { 29636197Sbostic fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n"); 29734185Sbostic exit(1); 29834185Sbostic } 299