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