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