124973Sbloom /* 262301Sbostic * Copyright (c) 1985, 1987, 1993 362301Sbostic * The Regents of the University of California. All rights reserved. 432759Sbostic * 542770Sbostic * %sccs.include.redist.c% 624973Sbloom */ 724973Sbloom 824973Sbloom #ifndef lint 962301Sbostic static char copyright[] = 1062301Sbostic "@(#) Copyright (c) 1985, 1987, 1993\n\ 1162301Sbostic The Regents of the University of California. All rights reserved.\n"; 1232759Sbostic #endif /* not lint */ 1324973Sbloom 1424973Sbloom #ifndef lint 15*66855Smckusick static char sccsid[] = "@(#)tcopy.c 8.2 (Berkeley) 04/17/94"; 1632759Sbostic #endif /* not lint */ 1724973Sbloom 1837859Sbostic #include <sys/types.h> 1956106Sbostic #include <sys/stat.h> 2024973Sbloom #include <sys/ioctl.h> 2124973Sbloom #include <sys/mtio.h> 2256106Sbostic 2356106Sbostic #include <errno.h> 2456106Sbostic #include <fcntl.h> 2551629Sbostic #include <signal.h> 2637859Sbostic #include <stdio.h> 2756106Sbostic #include <stdlib.h> 2856106Sbostic #include <string.h> 2956106Sbostic #include <unistd.h> 3056106Sbostic 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; 38*66855Smckusick FILE *msg = stdout; 3924973Sbloom 4056106Sbostic void *getspace __P((int)); 4156106Sbostic void intr __P((int)); 4256106Sbostic void usage __P((void)); 4356106Sbostic void verify __P((int, int, char *)); 4456106Sbostic void writeop __P((int, int)); 4556106Sbostic 4656106Sbostic int 4724973Sbloom main(argc, argv) 4832759Sbostic int argc; 4956106Sbostic char *argv[]; 5024973Sbloom { 5134185Sbostic register int lastnread, nread, nw, inp, outp; 5234185Sbostic enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; 5339834Sbostic sig_t oldsig; 5439834Sbostic int ch, needeof; 5556106Sbostic char *buff, *inf; 5624973Sbloom 5734185Sbostic guesslen = 1; 58*66855Smckusick while ((ch = getopt(argc, argv, "cs:vx")) != EOF) 5934185Sbostic switch((char)ch) { 6034185Sbostic case 'c': 6134185Sbostic op = COPYVERIFY; 6234185Sbostic break; 6330870Skarels case 's': 6434185Sbostic maxblk = atoi(optarg); 6530870Skarels if (maxblk <= 0) { 6636197Sbostic fprintf(stderr, "tcopy: illegal block size\n"); 6734185Sbostic usage(); 6830870Skarels } 6930870Skarels guesslen = 0; 7030870Skarels break; 7134185Sbostic case 'v': 7234185Sbostic op = VERIFY; 7334185Sbostic break; 74*66855Smckusick case 'x': 75*66855Smckusick msg = stderr; 76*66855Smckusick break; 7734185Sbostic case '?': 7834185Sbostic default: 7934185Sbostic usage(); 8030870Skarels } 8134185Sbostic argc -= optind; 8234185Sbostic argv += optind; 8334185Sbostic 8434185Sbostic switch(argc) { 8534185Sbostic case 0: 8634185Sbostic if (op != READ) 8734185Sbostic usage(); 8837859Sbostic inf = _PATH_DEFTAPE; 8934185Sbostic break; 9034185Sbostic case 1: 9134185Sbostic if (op != READ) 9234185Sbostic usage(); 9334185Sbostic inf = argv[0]; 9434185Sbostic break; 9534185Sbostic case 2: 9634185Sbostic if (op == READ) 9734185Sbostic op = COPY; 9834185Sbostic inf = argv[0]; 99*66855Smckusick if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : 100*66855Smckusick op == COPY ? O_WRONLY : O_RDWR, DEFFILEMODE)) < 0) { 10134185Sbostic perror(argv[1]); 10234185Sbostic exit(3); 10334185Sbostic } 10434185Sbostic break; 10534185Sbostic default: 10634185Sbostic usage(); 10730870Skarels } 10834185Sbostic 10930870Skarels if ((inp = open(inf, O_RDONLY, 0)) < 0) { 11030870Skarels perror(inf); 11130870Skarels exit(1); 11230870Skarels } 11334185Sbostic 11434185Sbostic buff = getspace(maxblk); 11534185Sbostic 11634185Sbostic if (op == VERIFY) { 11734185Sbostic verify(inp, outp, buff); 11834185Sbostic exit(0); 11924973Sbloom } 12034185Sbostic 12134185Sbostic if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) 12230870Skarels (void) signal(SIGINT, intr); 12334185Sbostic 12434185Sbostic needeof = 0; 12534185Sbostic for (lastnread = NOCOUNT;;) { 12634185Sbostic if ((nread = read(inp, buff, maxblk)) == -1) { 12734185Sbostic while (errno == EINVAL && (maxblk -= 1024)) { 12834185Sbostic nread = read(inp, buff, maxblk); 12934185Sbostic if (nread >= 0) 13034185Sbostic goto r1; 13130870Skarels } 13232759Sbostic fprintf(stderr, "read error, file %d, record %ld: ", 13330870Skarels filen, record); 13430870Skarels perror(""); 13534185Sbostic exit(1); 13634185Sbostic } else if (nread != lastnread) { 13734185Sbostic if (lastnread != 0 && lastnread != NOCOUNT) { 13830870Skarels if (lastrec == 0 && nread == 0) 139*66855Smckusick fprintf(msg, "%ld records\n", record); 14030870Skarels else if (record - lastrec > 1) 141*66855Smckusick fprintf(msg, "records %ld to %ld\n", 14230870Skarels lastrec, record); 14330870Skarels else 144*66855Smckusick fprintf(msg, "record %ld\n", lastrec); 14530870Skarels } 14630870Skarels if (nread != 0) 147*66855Smckusick fprintf(msg, "file %d: block size %d: ", 14830870Skarels filen, nread); 14932759Sbostic (void) fflush(stdout); 15030870Skarels lastrec = record; 15124973Sbloom } 15234185Sbostic r1: guesslen = 0; 15330870Skarels if (nread > 0) { 15445518Skarels if (op == COPY || op == COPYVERIFY) { 15530870Skarels if (needeof) { 15634185Sbostic writeop(outp, MTWEOF); 15734185Sbostic needeof = 0; 15830870Skarels } 15930870Skarels nw = write(outp, buff, nread); 16030870Skarels if (nw != nread) { 16130870Skarels fprintf(stderr, 16232759Sbostic "write error, file %d, record %ld: ", 16330870Skarels filen, record); 16430870Skarels if (nw == -1) 16530870Skarels perror(""); 16630870Skarels else 16730870Skarels fprintf(stderr, 16830870Skarels "write (%d) != read (%d)\n", 16930870Skarels nw, nread); 17030870Skarels fprintf(stderr, "copy aborted\n"); 17130870Skarels exit(5); 17230870Skarels } 17330870Skarels } 17430870Skarels size += nread; 17530870Skarels record++; 17630870Skarels } else { 17734185Sbostic if (lastnread <= 0 && lastnread != NOCOUNT) { 178*66855Smckusick fprintf(msg, "eot\n"); 17924973Sbloom break; 18024973Sbloom } 181*66855Smckusick fprintf(msg, 182*66855Smckusick "file %d: eof after %ld records: %ld bytes\n", 183*66855Smckusick filen, record, size); 18430870Skarels needeof = 1; 18524973Sbloom filen++; 18624973Sbloom tsize += size; 18734185Sbostic size = record = lastrec = 0; 18834185Sbostic lastnread = 0; 18924973Sbloom } 19034185Sbostic lastnread = nread; 19124973Sbloom } 192*66855Smckusick fprintf(msg, "total length: %ld bytes\n", tsize); 19334185Sbostic (void)signal(SIGINT, oldsig); 19445518Skarels if (op == COPY || op == COPYVERIFY) { 19534185Sbostic writeop(outp, MTWEOF); 19634185Sbostic writeop(outp, MTWEOF); 19734185Sbostic if (op == COPYVERIFY) { 19834185Sbostic writeop(outp, MTREW); 19934185Sbostic writeop(inp, MTREW); 20034185Sbostic verify(inp, outp, buff); 20134185Sbostic } 20234185Sbostic } 20334185Sbostic exit(0); 20424973Sbloom } 20524973Sbloom 20656106Sbostic void 20734185Sbostic verify(inp, outp, outb) 20834185Sbostic register int inp, outp; 20934185Sbostic register char *outb; 21034185Sbostic { 21134185Sbostic register int eot, inmaxblk, inn, outmaxblk, outn; 21234185Sbostic register char *inb; 21334185Sbostic 21434185Sbostic inb = getspace(maxblk); 21534185Sbostic inmaxblk = outmaxblk = maxblk; 21634185Sbostic for (eot = 0;; guesslen = 0) { 21734185Sbostic if ((inn = read(inp, inb, inmaxblk)) == -1) { 21834185Sbostic if (guesslen) 21934185Sbostic while (errno == EINVAL && (inmaxblk -= 1024)) { 22034185Sbostic inn = read(inp, inb, inmaxblk); 22134185Sbostic if (inn >= 0) 22234185Sbostic goto r1; 22334185Sbostic } 22434185Sbostic perror("tcopy: read error"); 22536197Sbostic break; 22634185Sbostic } 22734185Sbostic r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { 22834185Sbostic if (guesslen) 22934185Sbostic while (errno == EINVAL && (outmaxblk -= 1024)) { 23034185Sbostic outn = read(outp, outb, outmaxblk); 23134185Sbostic if (outn >= 0) 23234185Sbostic goto r2; 23334185Sbostic } 23434185Sbostic perror("tcopy: read error"); 23536197Sbostic break; 23634185Sbostic } 23736197Sbostic r2: if (inn != outn) { 238*66855Smckusick fprintf(msg, 239*66855Smckusick "%s: tapes have different block sizes; %d != %d.\n", 240*66855Smckusick "tcopy", inn, outn); 24134185Sbostic break; 24236197Sbostic } 24334185Sbostic if (!inn) { 24434185Sbostic if (eot++) { 245*66855Smckusick fprintf(msg, "tcopy: tapes are identical.\n"); 24634185Sbostic return; 24734185Sbostic } 24834185Sbostic } else { 24936197Sbostic if (bcmp(inb, outb, inn)) { 250*66855Smckusick fprintf(msg, 251*66855Smckusick "tcopy: tapes have different data.\n"); 25234185Sbostic break; 25336197Sbostic } 25434185Sbostic eot = 0; 25534185Sbostic } 25634185Sbostic } 25734185Sbostic exit(1); 25834185Sbostic } 25934185Sbostic 26039834Sbostic void 26156106Sbostic intr(signo) 26256106Sbostic int signo; 26324973Sbloom { 26430870Skarels if (record) 26530870Skarels if (record - lastrec > 1) 266*66855Smckusick fprintf(msg, "records %ld to %ld\n", lastrec, record); 26724973Sbloom else 268*66855Smckusick fprintf(msg, "record %ld\n", lastrec); 269*66855Smckusick fprintf(msg, "interrupt at file %d: record %ld\n", filen, record); 270*66855Smckusick fprintf(msg, "total length: %ld bytes\n", tsize + size); 27124973Sbloom exit(1); 27224973Sbloom } 27334185Sbostic 27456106Sbostic void * 27534185Sbostic getspace(blk) 27634185Sbostic int blk; 27734185Sbostic { 27856106Sbostic void *bp; 27934185Sbostic 28056106Sbostic if ((bp = malloc((size_t)blk)) == NULL) { 28136197Sbostic fprintf(stderr, "tcopy: no memory\n"); 28234185Sbostic exit(11); 28334185Sbostic } 28456106Sbostic return (bp); 28534185Sbostic } 28634185Sbostic 28756106Sbostic void 28834185Sbostic writeop(fd, type) 28934185Sbostic int fd, type; 29034185Sbostic { 29134185Sbostic struct mtop op; 29234185Sbostic 29334185Sbostic op.mt_op = type; 29434185Sbostic op.mt_count = (daddr_t)1; 29534185Sbostic if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { 29634185Sbostic perror("tcopy: tape op"); 29734185Sbostic exit(6); 29834185Sbostic } 29934185Sbostic } 30034185Sbostic 30156106Sbostic void 30234185Sbostic usage() 30334185Sbostic { 304*66855Smckusick fprintf(stderr, "usage: tcopy [-cvx] [-s maxblk] src [dest]\n"); 30534185Sbostic exit(1); 30634185Sbostic } 307