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[] = "@(#)tcopy.c 5.15 (Berkeley) 11/5/90"; 42 #endif /* not lint */ 43 44 #include <sys/types.h> 45 #include <sys/signal.h> 46 #include <sys/file.h> 47 #include <sys/ioctl.h> 48 #include <sys/mtio.h> 49 #include <sys/errno.h> 50 #include <stdio.h> 51 #include "pathnames.h" 52 53 #define MAXREC (64 * 1024) 54 #define NOCOUNT (-2) 55 56 int filen, guesslen, maxblk = MAXREC; 57 long lastrec, record, size, tsize; 58 59 main(argc, argv) 60 int argc; 61 char **argv; 62 { 63 extern char *optarg; 64 extern int optind, errno; 65 register int lastnread, nread, nw, inp, outp; 66 enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; 67 sig_t oldsig; 68 int ch, needeof; 69 char *buff, *inf, *getspace(); 70 void intr(); 71 72 guesslen = 1; 73 while ((ch = getopt(argc, argv, "cs:v")) != EOF) 74 switch((char)ch) { 75 case 'c': 76 op = COPYVERIFY; 77 break; 78 case 's': 79 maxblk = atoi(optarg); 80 if (maxblk <= 0) { 81 fprintf(stderr, "tcopy: illegal block size\n"); 82 usage(); 83 } 84 guesslen = 0; 85 break; 86 case 'v': 87 op = VERIFY; 88 break; 89 case '?': 90 default: 91 usage(); 92 } 93 argc -= optind; 94 argv += optind; 95 96 switch(argc) { 97 case 0: 98 if (op != READ) 99 usage(); 100 inf = _PATH_DEFTAPE; 101 break; 102 case 1: 103 if (op != READ) 104 usage(); 105 inf = argv[0]; 106 break; 107 case 2: 108 if (op == READ) 109 op = COPY; 110 inf = argv[0]; 111 if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR, 112 0666)) < 0) { 113 perror(argv[1]); 114 exit(3); 115 } 116 break; 117 default: 118 usage(); 119 } 120 121 if ((inp = open(inf, O_RDONLY, 0)) < 0) { 122 perror(inf); 123 exit(1); 124 } 125 126 buff = getspace(maxblk); 127 128 if (op == VERIFY) { 129 verify(inp, outp, buff); 130 exit(0); 131 } 132 133 if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) 134 (void) signal(SIGINT, intr); 135 136 needeof = 0; 137 for (lastnread = NOCOUNT;;) { 138 if ((nread = read(inp, buff, maxblk)) == -1) { 139 while (errno == EINVAL && (maxblk -= 1024)) { 140 nread = read(inp, buff, maxblk); 141 if (nread >= 0) 142 goto r1; 143 } 144 fprintf(stderr, "read error, file %d, record %ld: ", 145 filen, record); 146 perror(""); 147 exit(1); 148 } else if (nread != lastnread) { 149 if (lastnread != 0 && lastnread != NOCOUNT) { 150 if (lastrec == 0 && nread == 0) 151 printf("%ld records\n", record); 152 else if (record - lastrec > 1) 153 printf("records %ld to %ld\n", 154 lastrec, record); 155 else 156 printf("record %ld\n", lastrec); 157 } 158 if (nread != 0) 159 printf("file %d: block size %d: ", 160 filen, nread); 161 (void) fflush(stdout); 162 lastrec = record; 163 } 164 r1: guesslen = 0; 165 if (nread > 0) { 166 if (op == COPY || op == COPYVERIFY) { 167 if (needeof) { 168 writeop(outp, MTWEOF); 169 needeof = 0; 170 } 171 nw = write(outp, buff, nread); 172 if (nw != nread) { 173 fprintf(stderr, 174 "write error, file %d, record %ld: ", 175 filen, record); 176 if (nw == -1) 177 perror(""); 178 else 179 fprintf(stderr, 180 "write (%d) != read (%d)\n", 181 nw, nread); 182 fprintf(stderr, "copy aborted\n"); 183 exit(5); 184 } 185 } 186 size += nread; 187 record++; 188 } else { 189 if (lastnread <= 0 && lastnread != NOCOUNT) { 190 printf("eot\n"); 191 break; 192 } 193 printf("file %d: eof after %ld records: %ld bytes\n", 194 filen, record, size); 195 needeof = 1; 196 filen++; 197 tsize += size; 198 size = record = lastrec = 0; 199 lastnread = 0; 200 } 201 lastnread = nread; 202 } 203 printf("total length: %ld bytes\n", tsize); 204 (void)signal(SIGINT, oldsig); 205 if (op == COPY || op == COPYVERIFY) { 206 writeop(outp, MTWEOF); 207 writeop(outp, MTWEOF); 208 if (op == COPYVERIFY) { 209 writeop(outp, MTREW); 210 writeop(inp, MTREW); 211 verify(inp, outp, buff); 212 } 213 } 214 exit(0); 215 } 216 217 verify(inp, outp, outb) 218 register int inp, outp; 219 register char *outb; 220 { 221 extern int errno; 222 register int eot, inmaxblk, inn, outmaxblk, outn; 223 register char *inb; 224 char *getspace(); 225 226 inb = getspace(maxblk); 227 inmaxblk = outmaxblk = maxblk; 228 for (eot = 0;; guesslen = 0) { 229 if ((inn = read(inp, inb, inmaxblk)) == -1) { 230 if (guesslen) 231 while (errno == EINVAL && (inmaxblk -= 1024)) { 232 inn = read(inp, inb, inmaxblk); 233 if (inn >= 0) 234 goto r1; 235 } 236 perror("tcopy: read error"); 237 break; 238 } 239 r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { 240 if (guesslen) 241 while (errno == EINVAL && (outmaxblk -= 1024)) { 242 outn = read(outp, outb, outmaxblk); 243 if (outn >= 0) 244 goto r2; 245 } 246 perror("tcopy: read error"); 247 break; 248 } 249 r2: if (inn != outn) { 250 printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn); 251 break; 252 } 253 if (!inn) { 254 if (eot++) { 255 printf("tcopy: tapes are identical.\n"); 256 return; 257 } 258 } else { 259 if (bcmp(inb, outb, inn)) { 260 printf("tcopy: tapes have different data.\n"); 261 break; 262 } 263 eot = 0; 264 } 265 } 266 exit(1); 267 } 268 269 void 270 intr() 271 { 272 if (record) 273 if (record - lastrec > 1) 274 printf("records %ld to %ld\n", lastrec, record); 275 else 276 printf("record %ld\n", lastrec); 277 printf("interrupt at file %d: record %ld\n", filen, record); 278 printf("total length: %ld bytes\n", tsize + size); 279 exit(1); 280 } 281 282 char * 283 getspace(blk) 284 int blk; 285 { 286 char *bp, *malloc(); 287 288 if ((bp = malloc((u_int)blk)) == NULL) { 289 fprintf(stderr, "tcopy: no memory\n"); 290 exit(11); 291 } 292 return(bp); 293 } 294 295 writeop(fd, type) 296 int fd, type; 297 { 298 struct mtop op; 299 300 op.mt_op = type; 301 op.mt_count = (daddr_t)1; 302 if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { 303 perror("tcopy: tape op"); 304 exit(6); 305 } 306 } 307 308 usage() 309 { 310 fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n"); 311 exit(1); 312 } 313