1 /* 2 * Copyright (c) 1985, 1987, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1985, 1987, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)tcopy.c 8.1 (Berkeley) 06/06/93"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <sys/ioctl.h> 21 #include <sys/mtio.h> 22 23 #include <errno.h> 24 #include <fcntl.h> 25 #include <signal.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include "pathnames.h" 32 33 #define MAXREC (64 * 1024) 34 #define NOCOUNT (-2) 35 36 int filen, guesslen, maxblk = MAXREC; 37 long lastrec, record, size, tsize; 38 39 void *getspace __P((int)); 40 void intr __P((int)); 41 void usage __P((void)); 42 void verify __P((int, int, char *)); 43 void writeop __P((int, int)); 44 45 int 46 main(argc, argv) 47 int argc; 48 char *argv[]; 49 { 50 register int lastnread, nread, nw, inp, outp; 51 enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; 52 sig_t oldsig; 53 int ch, needeof; 54 char *buff, *inf; 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 fprintf(stderr, "tcopy: illegal block size\n"); 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 = _PATH_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 DEFFILEMODE)) < 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 || op == COPYVERIFY) { 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 || op == COPYVERIFY) { 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 void 202 verify(inp, outp, outb) 203 register int inp, outp; 204 register char *outb; 205 { 206 register int eot, inmaxblk, inn, outmaxblk, outn; 207 register char *inb; 208 209 inb = getspace(maxblk); 210 inmaxblk = outmaxblk = maxblk; 211 for (eot = 0;; guesslen = 0) { 212 if ((inn = read(inp, inb, inmaxblk)) == -1) { 213 if (guesslen) 214 while (errno == EINVAL && (inmaxblk -= 1024)) { 215 inn = read(inp, inb, inmaxblk); 216 if (inn >= 0) 217 goto r1; 218 } 219 perror("tcopy: read error"); 220 break; 221 } 222 r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { 223 if (guesslen) 224 while (errno == EINVAL && (outmaxblk -= 1024)) { 225 outn = read(outp, outb, outmaxblk); 226 if (outn >= 0) 227 goto r2; 228 } 229 perror("tcopy: read error"); 230 break; 231 } 232 r2: if (inn != outn) { 233 printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn); 234 break; 235 } 236 if (!inn) { 237 if (eot++) { 238 printf("tcopy: tapes are identical.\n"); 239 return; 240 } 241 } else { 242 if (bcmp(inb, outb, inn)) { 243 printf("tcopy: tapes have different data.\n"); 244 break; 245 } 246 eot = 0; 247 } 248 } 249 exit(1); 250 } 251 252 void 253 intr(signo) 254 int signo; 255 { 256 if (record) 257 if (record - lastrec > 1) 258 printf("records %ld to %ld\n", lastrec, record); 259 else 260 printf("record %ld\n", lastrec); 261 printf("interrupt at file %d: record %ld\n", filen, record); 262 printf("total length: %ld bytes\n", tsize + size); 263 exit(1); 264 } 265 266 void * 267 getspace(blk) 268 int blk; 269 { 270 void *bp; 271 272 if ((bp = malloc((size_t)blk)) == NULL) { 273 fprintf(stderr, "tcopy: no memory\n"); 274 exit(11); 275 } 276 return (bp); 277 } 278 279 void 280 writeop(fd, type) 281 int fd, type; 282 { 283 struct mtop op; 284 285 op.mt_op = type; 286 op.mt_count = (daddr_t)1; 287 if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { 288 perror("tcopy: tape op"); 289 exit(6); 290 } 291 } 292 293 void 294 usage() 295 { 296 fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n"); 297 exit(1); 298 } 299