1 /* 2 * Copyright (c) 1985, 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 char copyright[] = 36 "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\ 37 All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 /*static char sccsid[] = "from: @(#)tcopy.c 5.15 (Berkeley) 11/5/90";*/ 42 static char rcsid[] = "$Id: tcopy.c,v 1.2 1993/08/01 18:07:38 mycroft Exp $"; 43 #endif /* not lint */ 44 45 #include <sys/types.h> 46 #include <sys/signal.h> 47 #include <sys/file.h> 48 #include <sys/ioctl.h> 49 #include <sys/mtio.h> 50 #include <sys/errno.h> 51 #include <stdio.h> 52 #include "pathnames.h" 53 54 #define MAXREC (64 * 1024) 55 #define NOCOUNT (-2) 56 57 int filen, guesslen, maxblk = MAXREC; 58 long lastrec, record, size, tsize; 59 60 main(argc, argv) 61 int argc; 62 char **argv; 63 { 64 extern char *optarg; 65 extern int optind, errno; 66 register int lastnread, nread, nw, inp, outp; 67 enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; 68 sig_t oldsig; 69 int ch, needeof; 70 char *buff, *inf, *getspace(); 71 void intr(); 72 73 guesslen = 1; 74 while ((ch = getopt(argc, argv, "cs:v")) != EOF) 75 switch((char)ch) { 76 case 'c': 77 op = COPYVERIFY; 78 break; 79 case 's': 80 maxblk = atoi(optarg); 81 if (maxblk <= 0) { 82 fprintf(stderr, "tcopy: illegal block size\n"); 83 usage(); 84 } 85 guesslen = 0; 86 break; 87 case 'v': 88 op = VERIFY; 89 break; 90 case '?': 91 default: 92 usage(); 93 } 94 argc -= optind; 95 argv += optind; 96 97 switch(argc) { 98 case 0: 99 if (op != READ) 100 usage(); 101 inf = _PATH_DEFTAPE; 102 break; 103 case 1: 104 if (op != READ) 105 usage(); 106 inf = argv[0]; 107 break; 108 case 2: 109 if (op == READ) 110 op = COPY; 111 inf = argv[0]; 112 if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR, 113 0666)) < 0) { 114 perror(argv[1]); 115 exit(3); 116 } 117 break; 118 default: 119 usage(); 120 } 121 122 if ((inp = open(inf, O_RDONLY, 0)) < 0) { 123 perror(inf); 124 exit(1); 125 } 126 127 buff = getspace(maxblk); 128 129 if (op == VERIFY) { 130 verify(inp, outp, buff); 131 exit(0); 132 } 133 134 if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) 135 (void) signal(SIGINT, intr); 136 137 needeof = 0; 138 for (lastnread = NOCOUNT;;) { 139 if ((nread = read(inp, buff, maxblk)) == -1) { 140 while (errno == EINVAL && (maxblk -= 1024)) { 141 nread = read(inp, buff, maxblk); 142 if (nread >= 0) 143 goto r1; 144 } 145 fprintf(stderr, "read error, file %d, record %ld: ", 146 filen, record); 147 perror(""); 148 exit(1); 149 } else if (nread != lastnread) { 150 if (lastnread != 0 && lastnread != NOCOUNT) { 151 if (lastrec == 0 && nread == 0) 152 printf("%ld records\n", record); 153 else if (record - lastrec > 1) 154 printf("records %ld to %ld\n", 155 lastrec, record); 156 else 157 printf("record %ld\n", lastrec); 158 } 159 if (nread != 0) 160 printf("file %d: block size %d: ", 161 filen, nread); 162 (void) fflush(stdout); 163 lastrec = record; 164 } 165 r1: guesslen = 0; 166 if (nread > 0) { 167 if (op == COPY || op == COPYVERIFY) { 168 if (needeof) { 169 writeop(outp, MTWEOF); 170 needeof = 0; 171 } 172 nw = write(outp, buff, nread); 173 if (nw != nread) { 174 fprintf(stderr, 175 "write error, file %d, record %ld: ", 176 filen, record); 177 if (nw == -1) 178 perror(""); 179 else 180 fprintf(stderr, 181 "write (%d) != read (%d)\n", 182 nw, nread); 183 fprintf(stderr, "copy aborted\n"); 184 exit(5); 185 } 186 } 187 size += nread; 188 record++; 189 } else { 190 if (lastnread <= 0 && lastnread != NOCOUNT) { 191 printf("eot\n"); 192 break; 193 } 194 printf("file %d: eof after %ld records: %ld bytes\n", 195 filen, record, size); 196 needeof = 1; 197 filen++; 198 tsize += size; 199 size = record = lastrec = 0; 200 lastnread = 0; 201 } 202 lastnread = nread; 203 } 204 printf("total length: %ld bytes\n", tsize); 205 (void)signal(SIGINT, oldsig); 206 if (op == COPY || op == COPYVERIFY) { 207 writeop(outp, MTWEOF); 208 writeop(outp, MTWEOF); 209 if (op == COPYVERIFY) { 210 writeop(outp, MTREW); 211 writeop(inp, MTREW); 212 verify(inp, outp, buff); 213 } 214 } 215 exit(0); 216 } 217 218 verify(inp, outp, outb) 219 register int inp, outp; 220 register char *outb; 221 { 222 extern int errno; 223 register int eot, inmaxblk, inn, outmaxblk, outn; 224 register char *inb; 225 char *getspace(); 226 227 inb = getspace(maxblk); 228 inmaxblk = outmaxblk = maxblk; 229 for (eot = 0;; guesslen = 0) { 230 if ((inn = read(inp, inb, inmaxblk)) == -1) { 231 if (guesslen) 232 while (errno == EINVAL && (inmaxblk -= 1024)) { 233 inn = read(inp, inb, inmaxblk); 234 if (inn >= 0) 235 goto r1; 236 } 237 perror("tcopy: read error"); 238 break; 239 } 240 r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { 241 if (guesslen) 242 while (errno == EINVAL && (outmaxblk -= 1024)) { 243 outn = read(outp, outb, outmaxblk); 244 if (outn >= 0) 245 goto r2; 246 } 247 perror("tcopy: read error"); 248 break; 249 } 250 r2: if (inn != outn) { 251 printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn); 252 break; 253 } 254 if (!inn) { 255 if (eot++) { 256 printf("tcopy: tapes are identical.\n"); 257 return; 258 } 259 } else { 260 if (bcmp(inb, outb, inn)) { 261 printf("tcopy: tapes have different data.\n"); 262 break; 263 } 264 eot = 0; 265 } 266 } 267 exit(1); 268 } 269 270 void 271 intr() 272 { 273 if (record) 274 if (record - lastrec > 1) 275 printf("records %ld to %ld\n", lastrec, record); 276 else 277 printf("record %ld\n", lastrec); 278 printf("interrupt at file %d: record %ld\n", filen, record); 279 printf("total length: %ld bytes\n", tsize + size); 280 exit(1); 281 } 282 283 char * 284 getspace(blk) 285 int blk; 286 { 287 char *bp, *malloc(); 288 289 if ((bp = malloc((u_int)blk)) == NULL) { 290 fprintf(stderr, "tcopy: no memory\n"); 291 exit(11); 292 } 293 return(bp); 294 } 295 296 writeop(fd, type) 297 int fd, type; 298 { 299 struct mtop op; 300 301 op.mt_op = type; 302 op.mt_count = (daddr_t)1; 303 if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { 304 perror("tcopy: tape op"); 305 exit(6); 306 } 307 } 308 309 usage() 310 { 311 fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n"); 312 exit(1); 313 } 314