tcopy.c revision 24360
161981Sbrian/* 261981Sbrian * Copyright (c) 1985, 1987, 1993 361981Sbrian * The Regents of the University of California. All rights reserved. 461981Sbrian * 561981Sbrian * Redistribution and use in source and binary forms, with or without 661981Sbrian * modification, are permitted provided that the following conditions 761981Sbrian * are met: 861981Sbrian * 1. Redistributions of source code must retain the above copyright 961981Sbrian * notice, this list of conditions and the following disclaimer. 1061981Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1161981Sbrian * notice, this list of conditions and the following disclaimer in the 1261981Sbrian * documentation and/or other materials provided with the distribution. 13140771Skeramida * 3. All advertising materials mentioning features or use of this software 14140771Skeramida * must display the following acknowledgement: 15140771Skeramida * This product includes software developed by the University of 1661981Sbrian * California, Berkeley and its contributors. 1761981Sbrian * 4. Neither the name of the University nor the names of its contributors 1861981Sbrian * may be used to endorse or promote products derived from this software 1961981Sbrian * without specific prior written permission. 2061981Sbrian * 2161981Sbrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2261981Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23170085Sdougb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2461981Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2561981Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2661981Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2761981Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2865843Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2965843Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3065843Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3165843Sbrian * SUCH DAMAGE. 3265843Sbrian */ 3365843Sbrian 3465843Sbrian#ifndef lint 3565843Sbrianstatic char copyright[] = 3665843Sbrian"@(#) Copyright (c) 1985, 1987, 1993\n\ 3765843Sbrian The Regents of the University of California. All rights reserved.\n"; 3861981Sbrian#endif /* not lint */ 3961981Sbrian 4061981Sbrian#ifndef lint 4161981Sbrianstatic char sccsid[] = "@(#)tcopy.c 8.2 (Berkeley) 4/17/94"; 4261981Sbrian#endif /* not lint */ 4361981Sbrian 4461981Sbrian#include <sys/types.h> 4561981Sbrian#include <sys/stat.h> 4661981Sbrian#include <sys/ioctl.h> 4761981Sbrian#include <sys/mtio.h> 48174028Sjhb 49205509Sjoerg#include <errno.h> 50236284Seadler#include <fcntl.h> 51174028Sjhb#include <signal.h> 5261981Sbrian#include <stdio.h> 5361981Sbrian#include <stdlib.h> 5461981Sbrian#include <string.h> 5561981Sbrian#include <unistd.h> 5661981Sbrian 5761981Sbrian#include "pathnames.h" 5861981Sbrian 5961981Sbrian#define MAXREC (64 * 1024) 6061981Sbrian#define NOCOUNT (-2) 6161981Sbrian 6261981Sbrianint filen, guesslen, maxblk = MAXREC; 6361981Sbrianu_long lastrec, record, size, tsize; 6461981SbrianFILE *msg = stdout; 6561981Sbrian 6661981Sbrianvoid *getspace __P((int)); 6761981Sbrianvoid intr __P((int)); 6861981Sbrianvoid usage __P((void)); 69108959Swollmanvoid verify __P((int, int, char *)); 70108959Swollmanvoid writeop __P((int, int)); 7161981Sbrian 7261981Sbrianint 7361981Sbrianmain(argc, argv) 7461981Sbrian int argc; 7561981Sbrian char *argv[]; 7661981Sbrian{ 7761981Sbrian register int lastnread, nread, nw, inp, outp; 78220020Sdougb enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; 79220020Sdougb sig_t oldsig; 80220020Sdougb int ch, needeof; 81220020Sdougb char *buff, *inf; 8261981Sbrian 8361981Sbrian guesslen = 1; 8461981Sbrian while ((ch = getopt(argc, argv, "cs:vx")) != -1) 8561981Sbrian switch((char)ch) { 8661981Sbrian case 'c': 8762054Sbrian op = COPYVERIFY; 8877496Sbrian break; 8977492Sbrian case 's': 9061981Sbrian maxblk = atoi(optarg); 9161981Sbrian if (maxblk <= 0) { 9261981Sbrian fprintf(stderr, "tcopy: illegal block size\n"); 9361981Sbrian usage(); 9461981Sbrian } 9561981Sbrian guesslen = 0; 96281318Sjhb break; 9761981Sbrian case 'v': 98249095Smav op = VERIFY; 99249095Smav break; 100249095Smav case 'x': 101168412Spjd msg = stderr; 102168412Spjd break; 103231171Sgjb case '?': 104168412Spjd default: 105154304Swollman usage(); 106154304Swollman } 107154304Swollman argc -= optind; 108156216Sbrueffer argv += optind; 109156216Sbrueffer 110156216Sbrueffer switch(argc) { 111156216Sbrueffer case 0: 112156216Sbrueffer if (op != READ) 113156216Sbrueffer usage(); 114156216Sbrueffer inf = _PATH_DEFTAPE; 115156216Sbrueffer break; 116156216Sbrueffer case 1: 11761981Sbrian if (op != READ) 11861981Sbrian usage(); 11961981Sbrian inf = argv[0]; 120282243Sjhb break; 12161981Sbrian case 2: 12261981Sbrian if (op == READ) 12361981Sbrian op = COPY; 12461981Sbrian inf = argv[0]; 12561981Sbrian if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : 12661981Sbrian op == COPY ? O_WRONLY : O_RDWR, DEFFILEMODE)) < 0) { 12761981Sbrian perror(argv[1]); 12894342Sgshapiro exit(3); 12961981Sbrian } 13061981Sbrian break; 13161981Sbrian default: 132254974Sjlh usage(); 133254974Sjlh } 134254974Sjlh 13561981Sbrian if ((inp = open(inf, O_RDONLY, 0)) < 0) { 13661981Sbrian perror(inf); 13761981Sbrian exit(1); 13862274Sbrian } 139175153Sdds 14061981Sbrian buff = getspace(maxblk); 141295461Scy 142295461Scy if (op == VERIFY) { 143295461Scy verify(inp, outp, buff); 144295461Scy exit(0); 145295461Scy } 146169517Smaxim 147169517Smaxim if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) 148169517Smaxim (void) signal(SIGINT, intr); 14972677Speter 15072677Speter needeof = 0; 15194342Sgshapiro for (lastnread = NOCOUNT;;) { 15272677Speter if ((nread = read(inp, buff, maxblk)) == -1) { 153277520Sgjb while (errno == EINVAL && (maxblk -= 1024)) { 154277520Sgjb nread = read(inp, buff, maxblk); 155277520Sgjb if (nread >= 0) 156277520Sgjb goto r1; 157226471Sse } 158226471Sse fprintf(stderr, "read error, file %d, record %ld: ", 159226471Sse filen, record); 160226865Sdelphij perror(""); 161226865Sdelphij exit(1); 162226471Sse } else if (nread != lastnread) { 16361981Sbrian if (lastnread != 0 && lastnread != NOCOUNT) { 16461981Sbrian if (lastrec == 0 && nread == 0) 16561981Sbrian fprintf(msg, "%ld records\n", record); 16661981Sbrian else if (record - lastrec > 1) 167255169Sjlh fprintf(msg, "records %ld to %ld\n", 168255169Sjlh lastrec, record); 169255169Sjlh else 170255169Sjlh fprintf(msg, "record %ld\n", lastrec); 171255169Sjlh } 172255169Sjlh if (nread != 0) 173255169Sjlh fprintf(msg, "file %d: block size %d: ", 174255169Sjlh filen, nread); 175255169Sjlh (void) fflush(stdout); 176255169Sjlh lastrec = record; 177255169Sjlh } 178255169Sjlhr1: guesslen = 0; 179255169Sjlh if (nread > 0) { 180255169Sjlh if (op == COPY || op == COPYVERIFY) { 181255169Sjlh if (needeof) { 182255169Sjlh writeop(outp, MTWEOF); 183255169Sjlh needeof = 0; 184255169Sjlh } 185255169Sjlh nw = write(outp, buff, nread); 186255169Sjlh if (nw != nread) { 187255169Sjlh fprintf(stderr, 188255169Sjlh "write error, file %d, record %ld: ", 189255169Sjlh filen, record); 190255169Sjlh if (nw == -1) 191255169Sjlh perror(""); 192255169Sjlh else 193255169Sjlh fprintf(stderr, 194255169Sjlh "write (%d) != read (%d)\n", 195255169Sjlh nw, nread); 196255169Sjlh fprintf(stderr, "copy aborted\n"); 197255169Sjlh exit(5); 198255169Sjlh } 199255169Sjlh } 200255169Sjlh size += nread; 201255169Sjlh record++; 202255169Sjlh } else { 203255169Sjlh if (lastnread <= 0 && lastnread != NOCOUNT) { 204255169Sjlh fprintf(msg, "eot\n"); 205255169Sjlh break; 206255169Sjlh } 207255169Sjlh fprintf(msg, 208255169Sjlh "file %d: eof after %lu records: %lu bytes\n", 209255169Sjlh filen, record, size); 210255169Sjlh needeof = 1; 211255169Sjlh filen++; 212255169Sjlh tsize += size; 213255169Sjlh size = record = lastrec = 0; 214255169Sjlh lastnread = 0; 215255169Sjlh } 216255169Sjlh lastnread = nread; 217255169Sjlh } 218255169Sjlh fprintf(msg, "total length: %lu bytes\n", tsize); 219255169Sjlh (void)signal(SIGINT, oldsig); 220255169Sjlh if (op == COPY || op == COPYVERIFY) { 221255169Sjlh writeop(outp, MTWEOF); 222255169Sjlh writeop(outp, MTWEOF); 223255169Sjlh if (op == COPYVERIFY) { 224255169Sjlh writeop(outp, MTREW); 225255169Sjlh writeop(inp, MTREW); 226255169Sjlh verify(inp, outp, buff); 22787514Scjc } 22887514Scjc } 229101607Sfanf exit(0); 230254974Sjlh} 231254974Sjlh 232254974Sjlhvoid 23387514Scjcverify(inp, outp, outb) 234255169Sjlh register int inp, outp; 235254974Sjlh register char *outb; 236255169Sjlh{ 237254974Sjlh register int eot, inmaxblk, inn, outmaxblk, outn; 238254974Sjlh register char *inb; 239255169Sjlh 240255169Sjlh inb = getspace(maxblk); 241255169Sjlh inmaxblk = outmaxblk = maxblk; 242254974Sjlh for (eot = 0;; guesslen = 0) { 24387514Scjc if ((inn = read(inp, inb, inmaxblk)) == -1) { 244254974Sjlh if (guesslen) 245254974Sjlh while (errno == EINVAL && (inmaxblk -= 1024)) { 24687514Scjc inn = read(inp, inb, inmaxblk); 247215213Sbrooks if (inn >= 0) 248254974Sjlh goto r1; 249254974Sjlh } 250215213Sbrooks perror("tcopy: read error"); 25187514Scjc break; 252254974Sjlh } 253254974Sjlhr1: if ((outn = read(outp, outb, outmaxblk)) == -1) { 254254974Sjlh if (guesslen) 25587514Scjc while (errno == EINVAL && (outmaxblk -= 1024)) { 256254974Sjlh outn = read(outp, outb, outmaxblk); 25787514Scjc if (outn >= 0) 25887514Scjc goto r2; 259254974Sjlh } 260254974Sjlh perror("tcopy: read error"); 26187514Scjc break; 26287514Scjc } 263254974Sjlhr2: if (inn != outn) { 264254974Sjlh fprintf(msg, 26587514Scjc "%s: tapes have different block sizes; %d != %d.\n", 266161602Strhodes "tcopy", inn, outn); 267254974Sjlh break; 268254974Sjlh } 269161602Strhodes if (!inn) { 270210254Sgabor if (eot++) { 271254974Sjlh fprintf(msg, "tcopy: tapes are identical.\n"); 272254974Sjlh return; 273210254Sgabor } 27487514Scjc } else { 275254974Sjlh if (bcmp(inb, outb, inn)) { 276254974Sjlh fprintf(msg, 27787514Scjc "tcopy: tapes have different data.\n"); 278105937Sthomas break; 279254974Sjlh } 280254974Sjlh eot = 0; 281105937Sthomas } 282138061Smlaier } 283254974Sjlh exit(1); 284254974Sjlh} 285138061Smlaier 28687514Scjcvoid 287254974Sjlhintr(signo) 288254974Sjlh int signo; 28987514Scjc{ 290128473Sdarrenr if (record) 291254974Sjlh if (record - lastrec > 1) 292254974Sjlh fprintf(msg, "records %ld to %ld\n", lastrec, record); 293128473Sdarrenr else 29487514Scjc fprintf(msg, "record %ld\n", lastrec); 295254974Sjlh fprintf(msg, "interrupt at file %d: record %ld\n", filen, record); 296254974Sjlh fprintf(msg, "total length: %ld bytes\n", tsize + size); 29787514Scjc exit(1); 29887514Scjc} 299254974Sjlh 300254974Sjlhvoid * 30187514Scjcgetspace(blk) 30287514Scjc int blk; 303254974Sjlh{ 304254974Sjlh void *bp; 30587514Scjc 30687514Scjc if ((bp = malloc((size_t)blk)) == NULL) { 30761981Sbrian fprintf(stderr, "tcopy: no memory\n"); 30861981Sbrian exit(11); 30961981Sbrian } 31061981Sbrian return (bp); 31161981Sbrian} 31261981Sbrian 313254974Sjlhvoid 314254974Sjlhwriteop(fd, type) 315254974Sjlh int fd, type; 316254974Sjlh{ 317254974Sjlh struct mtop op; 318254974Sjlh 319257508Sjlh op.mt_op = type; 320254974Sjlh op.mt_count = (daddr_t)1; 321254974Sjlh if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { 322254974Sjlh perror("tcopy: tape op"); 323254974Sjlh exit(6); 324254974Sjlh } 325254974Sjlh} 326254974Sjlh 327292841Sjillesvoid 328292841Sjillesusage() 329254974Sjlh{ 330254974Sjlh fprintf(stderr, "usage: tcopy [-cvx] [-s maxblk] src [dest]\n"); 331257508Sjlh exit(1); 332254974Sjlh} 333254974Sjlh