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