124973Sbloom /* 230870Skarels * Copyright (c) 1985, 1987 Regents of the University of California. 332759Sbostic * All rights reserved. 432759Sbostic * 532759Sbostic * Redistribution and use in source and binary forms are permitted 634911Sbostic * provided that the above copyright notice and this paragraph are 734911Sbostic * duplicated in all such forms and that any documentation, 834911Sbostic * advertising materials, and other materials related to such 934911Sbostic * distribution and use acknowledge that the software was developed 1034911Sbostic * by the University of California, Berkeley. The name of the 1134911Sbostic * University may not be used to endorse or promote products derived 1234911Sbostic * from this software without specific prior written permission. 1334911Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434911Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534911Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1624973Sbloom */ 1724973Sbloom 1824973Sbloom #ifndef lint 1924973Sbloom char copyright[] = 2030870Skarels "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\ 2124973Sbloom All rights reserved.\n"; 2232759Sbostic #endif /* not lint */ 2324973Sbloom 2424973Sbloom #ifndef lint 25*37859Sbostic static char sccsid[] = "@(#)tcopy.c 5.12 (Berkeley) 05/11/89"; 2632759Sbostic #endif /* not lint */ 2724973Sbloom 28*37859Sbostic #include <sys/types.h> 29*37859Sbostic #include <sys/signal.h> 3024973Sbloom #include <sys/file.h> 3124973Sbloom #include <sys/ioctl.h> 3224973Sbloom #include <sys/mtio.h> 3330873Skarels #include <sys/errno.h> 34*37859Sbostic #include <stdio.h> 35*37859Sbostic #include "pathnames.h" 3624973Sbloom 3734185Sbostic #define MAXREC (64 * 1024) 3834185Sbostic #define NOCOUNT (-2) 3934185Sbostic 4034185Sbostic int filen, guesslen, maxblk = MAXREC; 4134185Sbostic long lastrec, record, size, tsize; 4224973Sbloom 4324973Sbloom main(argc, argv) 4432759Sbostic int argc; 4532759Sbostic char **argv; 4624973Sbloom { 4734185Sbostic extern char *optarg; 4834185Sbostic extern int optind, errno; 4934185Sbostic register int lastnread, nread, nw, inp, outp; 5034185Sbostic enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; 5134185Sbostic int ch, needeof, intr(), (*oldsig)(); 5234185Sbostic char *buff, *inf, *getspace(); 5324973Sbloom 5434185Sbostic guesslen = 1; 5534185Sbostic while ((ch = getopt(argc, argv, "cs:v")) != EOF) 5634185Sbostic switch((char)ch) { 5734185Sbostic case 'c': 5834185Sbostic op = COPYVERIFY; 5934185Sbostic break; 6030870Skarels case 's': 6134185Sbostic maxblk = atoi(optarg); 6230870Skarels if (maxblk <= 0) { 6336197Sbostic fprintf(stderr, "tcopy: illegal block size\n"); 6434185Sbostic usage(); 6530870Skarels } 6630870Skarels guesslen = 0; 6730870Skarels break; 6834185Sbostic case 'v': 6934185Sbostic op = VERIFY; 7034185Sbostic break; 7134185Sbostic case '?': 7234185Sbostic default: 7334185Sbostic usage(); 7430870Skarels } 7534185Sbostic argc -= optind; 7634185Sbostic argv += optind; 7734185Sbostic 7834185Sbostic switch(argc) { 7934185Sbostic case 0: 8034185Sbostic if (op != READ) 8134185Sbostic usage(); 82*37859Sbostic inf = _PATH_DEFTAPE; 8334185Sbostic break; 8434185Sbostic case 1: 8534185Sbostic if (op != READ) 8634185Sbostic usage(); 8734185Sbostic inf = argv[0]; 8834185Sbostic break; 8934185Sbostic case 2: 9034185Sbostic if (op == READ) 9134185Sbostic op = COPY; 9234185Sbostic inf = argv[0]; 9334954Sbostic if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR, 9434954Sbostic 0666)) < 0) { 9534185Sbostic perror(argv[1]); 9634185Sbostic exit(3); 9734185Sbostic } 9834185Sbostic break; 9934185Sbostic default: 10034185Sbostic usage(); 10130870Skarels } 10234185Sbostic 10330870Skarels if ((inp = open(inf, O_RDONLY, 0)) < 0) { 10430870Skarels perror(inf); 10530870Skarels exit(1); 10630870Skarels } 10734185Sbostic 10834185Sbostic buff = getspace(maxblk); 10934185Sbostic 11034185Sbostic if (op == VERIFY) { 11134185Sbostic verify(inp, outp, buff); 11234185Sbostic exit(0); 11324973Sbloom } 11434185Sbostic 11534185Sbostic if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) 11630870Skarels (void) signal(SIGINT, intr); 11734185Sbostic 11834185Sbostic needeof = 0; 11934185Sbostic for (lastnread = NOCOUNT;;) { 12034185Sbostic if ((nread = read(inp, buff, maxblk)) == -1) { 12134185Sbostic while (errno == EINVAL && (maxblk -= 1024)) { 12234185Sbostic nread = read(inp, buff, maxblk); 12334185Sbostic if (nread >= 0) 12434185Sbostic goto r1; 12530870Skarels } 12632759Sbostic fprintf(stderr, "read error, file %d, record %ld: ", 12730870Skarels filen, record); 12830870Skarels perror(""); 12934185Sbostic exit(1); 13034185Sbostic } else if (nread != lastnread) { 13134185Sbostic if (lastnread != 0 && lastnread != NOCOUNT) { 13230870Skarels if (lastrec == 0 && nread == 0) 13332759Sbostic printf("%ld records\n", record); 13430870Skarels else if (record - lastrec > 1) 13530870Skarels printf("records %ld to %ld\n", 13630870Skarels lastrec, record); 13730870Skarels else 13830870Skarels printf("record %ld\n", lastrec); 13930870Skarels } 14030870Skarels if (nread != 0) 14130870Skarels printf("file %d: block size %d: ", 14230870Skarels filen, nread); 14332759Sbostic (void) fflush(stdout); 14430870Skarels lastrec = record; 14524973Sbloom } 14634185Sbostic r1: guesslen = 0; 14730870Skarels if (nread > 0) { 14834911Sbostic if (op >= COPY) { 14930870Skarels if (needeof) { 15034185Sbostic writeop(outp, MTWEOF); 15134185Sbostic needeof = 0; 15230870Skarels } 15330870Skarels nw = write(outp, buff, nread); 15430870Skarels if (nw != nread) { 15530870Skarels fprintf(stderr, 15632759Sbostic "write error, file %d, record %ld: ", 15730870Skarels filen, record); 15830870Skarels if (nw == -1) 15930870Skarels perror(""); 16030870Skarels else 16130870Skarels fprintf(stderr, 16230870Skarels "write (%d) != read (%d)\n", 16330870Skarels nw, nread); 16430870Skarels fprintf(stderr, "copy aborted\n"); 16530870Skarels exit(5); 16630870Skarels } 16730870Skarels } 16830870Skarels size += nread; 16930870Skarels record++; 17030870Skarels } else { 17134185Sbostic if (lastnread <= 0 && lastnread != NOCOUNT) { 17224973Sbloom printf("eot\n"); 17324973Sbloom break; 17424973Sbloom } 17524973Sbloom printf("file %d: eof after %ld records: %ld bytes\n", 17630870Skarels filen, record, size); 17730870Skarels needeof = 1; 17824973Sbloom filen++; 17924973Sbloom tsize += size; 18034185Sbostic size = record = lastrec = 0; 18134185Sbostic lastnread = 0; 18224973Sbloom } 18334185Sbostic lastnread = nread; 18424973Sbloom } 18524973Sbloom printf("total length: %ld bytes\n", tsize); 18634185Sbostic (void)signal(SIGINT, oldsig); 18734911Sbostic if (op >= COPY) { 18834185Sbostic writeop(outp, MTWEOF); 18934185Sbostic writeop(outp, MTWEOF); 19034185Sbostic if (op == COPYVERIFY) { 19134185Sbostic writeop(outp, MTREW); 19234185Sbostic writeop(inp, MTREW); 19334185Sbostic verify(inp, outp, buff); 19434185Sbostic } 19534185Sbostic } 19634185Sbostic exit(0); 19724973Sbloom } 19824973Sbloom 19934185Sbostic verify(inp, outp, outb) 20034185Sbostic register int inp, outp; 20134185Sbostic register char *outb; 20234185Sbostic { 20335696Sbostic extern int errno; 20434185Sbostic register int eot, inmaxblk, inn, outmaxblk, outn; 20534185Sbostic register char *inb; 20634185Sbostic char *getspace(); 20734185Sbostic 20834185Sbostic inb = getspace(maxblk); 20934185Sbostic inmaxblk = outmaxblk = maxblk; 21034185Sbostic for (eot = 0;; guesslen = 0) { 21134185Sbostic if ((inn = read(inp, inb, inmaxblk)) == -1) { 21234185Sbostic if (guesslen) 21334185Sbostic while (errno == EINVAL && (inmaxblk -= 1024)) { 21434185Sbostic inn = read(inp, inb, inmaxblk); 21534185Sbostic if (inn >= 0) 21634185Sbostic goto r1; 21734185Sbostic } 21834185Sbostic perror("tcopy: read error"); 21936197Sbostic break; 22034185Sbostic } 22134185Sbostic r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { 22234185Sbostic if (guesslen) 22334185Sbostic while (errno == EINVAL && (outmaxblk -= 1024)) { 22434185Sbostic outn = read(outp, outb, outmaxblk); 22534185Sbostic if (outn >= 0) 22634185Sbostic goto r2; 22734185Sbostic } 22834185Sbostic perror("tcopy: read error"); 22936197Sbostic break; 23034185Sbostic } 23136197Sbostic r2: if (inn != outn) { 23236197Sbostic printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn); 23334185Sbostic break; 23436197Sbostic } 23534185Sbostic if (!inn) { 23634185Sbostic if (eot++) { 23736197Sbostic printf("tcopy: tapes are identical.\n"); 23834185Sbostic return; 23934185Sbostic } 24034185Sbostic } else { 24136197Sbostic if (bcmp(inb, outb, inn)) { 24236197Sbostic printf("tcopy: tapes have different data.\n"); 24334185Sbostic break; 24436197Sbostic } 24534185Sbostic eot = 0; 24634185Sbostic } 24734185Sbostic } 24834185Sbostic exit(1); 24934185Sbostic } 25034185Sbostic 25130870Skarels intr() 25224973Sbloom { 25330870Skarels if (record) 25430870Skarels if (record - lastrec > 1) 25530870Skarels printf("records %ld to %ld\n", lastrec, record); 25624973Sbloom else 25730870Skarels printf("record %ld\n", lastrec); 25830870Skarels printf("interrupt at file %d: record %ld\n", filen, record); 25934185Sbostic printf("total length: %ld bytes\n", tsize + size); 26024973Sbloom exit(1); 26124973Sbloom } 26234185Sbostic 26335696Sbostic char * 26434185Sbostic getspace(blk) 26534185Sbostic int blk; 26634185Sbostic { 26734185Sbostic char *bp, *malloc(); 26834185Sbostic 26934185Sbostic if ((bp = malloc((u_int)blk)) == NULL) { 27036197Sbostic fprintf(stderr, "tcopy: no memory\n"); 27134185Sbostic exit(11); 27234185Sbostic } 27334185Sbostic return(bp); 27434185Sbostic } 27534185Sbostic 27634185Sbostic writeop(fd, type) 27734185Sbostic int fd, type; 27834185Sbostic { 27934185Sbostic struct mtop op; 28034185Sbostic 28134185Sbostic op.mt_op = type; 28234185Sbostic op.mt_count = (daddr_t)1; 28334185Sbostic if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { 28434185Sbostic perror("tcopy: tape op"); 28534185Sbostic exit(6); 28634185Sbostic } 28734185Sbostic } 28834185Sbostic 28934185Sbostic usage() 29034185Sbostic { 29136197Sbostic fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n"); 29234185Sbostic exit(1); 29334185Sbostic } 294