Commit | Line | Data |
---|---|---|
f7c68695 | 1 | /* |
2c00311e | 2 | * Copyright (c) 1985, 1987 Regents of the University of California. |
b210d410 KB |
3 | * All rights reserved. |
4 | * | |
cb956e54 | 5 | * %sccs.include.redist.c% |
f7c68695 JB |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
2c00311e | 10 | "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\ |
f7c68695 | 11 | All rights reserved.\n"; |
b210d410 | 12 | #endif /* not lint */ |
f7c68695 JB |
13 | |
14 | #ifndef lint | |
daf38612 | 15 | static char sccsid[] = "@(#)tcopy.c 5.16 (Berkeley) %G%"; |
b210d410 | 16 | #endif /* not lint */ |
f7c68695 | 17 | |
f7c68695 JB |
18 | #include <sys/types.h> |
19 | #include <sys/ioctl.h> | |
20 | #include <sys/mtio.h> | |
daf38612 KB |
21 | #include <signal.h> |
22 | #include <fcntl.h> | |
23 | #include <errno.h> | |
435e8dff KB |
24 | #include <stdio.h> |
25 | #include "pathnames.h" | |
f7c68695 | 26 | |
ceb3a81e KB |
27 | #define MAXREC (64 * 1024) |
28 | #define NOCOUNT (-2) | |
29 | ||
ceb3a81e KB |
30 | int filen, guesslen, maxblk = MAXREC; |
31 | long lastrec, record, size, tsize; | |
f7c68695 JB |
32 | |
33 | main(argc, argv) | |
b210d410 KB |
34 | int argc; |
35 | char **argv; | |
f7c68695 | 36 | { |
ceb3a81e KB |
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; | |
6894b138 KB |
41 | sig_t oldsig; |
42 | int ch, needeof; | |
ceb3a81e | 43 | char *buff, *inf, *getspace(); |
6894b138 | 44 | void intr(); |
f7c68695 | 45 | |
ceb3a81e KB |
46 | guesslen = 1; |
47 | while ((ch = getopt(argc, argv, "cs:v")) != EOF) | |
48 | switch((char)ch) { | |
49 | case 'c': | |
50 | op = COPYVERIFY; | |
51 | break; | |
2c00311e | 52 | case 's': |
ceb3a81e | 53 | maxblk = atoi(optarg); |
2c00311e | 54 | if (maxblk <= 0) { |
d8eaee96 | 55 | fprintf(stderr, "tcopy: illegal block size\n"); |
ceb3a81e | 56 | usage(); |
2c00311e | 57 | } |
2c00311e MK |
58 | guesslen = 0; |
59 | break; | |
ceb3a81e KB |
60 | case 'v': |
61 | op = VERIFY; | |
62 | break; | |
63 | case '?': | |
64 | default: | |
65 | usage(); | |
2c00311e | 66 | } |
ceb3a81e KB |
67 | argc -= optind; |
68 | argv += optind; | |
69 | ||
70 | switch(argc) { | |
71 | case 0: | |
72 | if (op != READ) | |
73 | usage(); | |
435e8dff | 74 | inf = _PATH_DEFTAPE; |
ceb3a81e KB |
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]; | |
2368c417 KB |
85 | if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR, |
86 | 0666)) < 0) { | |
ceb3a81e KB |
87 | perror(argv[1]); |
88 | exit(3); | |
89 | } | |
90 | break; | |
91 | default: | |
92 | usage(); | |
c11c323a | 93 | } |
ceb3a81e | 94 | |
2c00311e MK |
95 | if ((inp = open(inf, O_RDONLY, 0)) < 0) { |
96 | perror(inf); | |
f7c68695 JB |
97 | exit(1); |
98 | } | |
ceb3a81e KB |
99 | |
100 | buff = getspace(maxblk); | |
101 | ||
102 | if (op == VERIFY) { | |
103 | verify(inp, outp, buff); | |
104 | exit(0); | |
f7c68695 | 105 | } |
ceb3a81e KB |
106 | |
107 | if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) | |
2c00311e | 108 | (void) signal(SIGINT, intr); |
ceb3a81e KB |
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; | |
2c00311e | 117 | } |
b210d410 | 118 | fprintf(stderr, "read error, file %d, record %ld: ", |
2c00311e MK |
119 | filen, record); |
120 | perror(""); | |
ceb3a81e KB |
121 | exit(1); |
122 | } else if (nread != lastnread) { | |
123 | if (lastnread != 0 && lastnread != NOCOUNT) { | |
2c00311e | 124 | if (lastrec == 0 && nread == 0) |
b210d410 | 125 | printf("%ld records\n", record); |
2c00311e MK |
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); | |
b210d410 | 135 | (void) fflush(stdout); |
2c00311e | 136 | lastrec = record; |
f7c68695 | 137 | } |
ceb3a81e | 138 | r1: guesslen = 0; |
2c00311e | 139 | if (nread > 0) { |
1c63ce13 | 140 | if (op == COPY || op == COPYVERIFY) { |
2c00311e | 141 | if (needeof) { |
ceb3a81e KB |
142 | writeop(outp, MTWEOF); |
143 | needeof = 0; | |
2c00311e MK |
144 | } |
145 | nw = write(outp, buff, nread); | |
146 | if (nw != nread) { | |
147 | fprintf(stderr, | |
b210d410 | 148 | "write error, file %d, record %ld: ", |
2c00311e MK |
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 { | |
ceb3a81e | 163 | if (lastnread <= 0 && lastnread != NOCOUNT) { |
f7c68695 JB |
164 | printf("eot\n"); |
165 | break; | |
166 | } | |
f7c68695 | 167 | printf("file %d: eof after %ld records: %ld bytes\n", |
2c00311e MK |
168 | filen, record, size); |
169 | needeof = 1; | |
f7c68695 | 170 | filen++; |
f7c68695 | 171 | tsize += size; |
ceb3a81e KB |
172 | size = record = lastrec = 0; |
173 | lastnread = 0; | |
f7c68695 | 174 | } |
ceb3a81e | 175 | lastnread = nread; |
f7c68695 | 176 | } |
f7c68695 | 177 | printf("total length: %ld bytes\n", tsize); |
ceb3a81e | 178 | (void)signal(SIGINT, oldsig); |
1c63ce13 | 179 | if (op == COPY || op == COPYVERIFY) { |
ceb3a81e KB |
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 | ||
ceb3a81e KB |
191 | verify(inp, outp, outb) |
192 | register int inp, outp; | |
193 | register char *outb; | |
194 | { | |
17cd062a | 195 | extern int errno; |
ceb3a81e KB |
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"); | |
d8eaee96 | 211 | break; |
ceb3a81e KB |
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"); | |
d8eaee96 | 221 | break; |
ceb3a81e | 222 | } |
d8eaee96 KB |
223 | r2: if (inn != outn) { |
224 | printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn); | |
ceb3a81e | 225 | break; |
d8eaee96 | 226 | } |
ceb3a81e KB |
227 | if (!inn) { |
228 | if (eot++) { | |
d8eaee96 | 229 | printf("tcopy: tapes are identical.\n"); |
ceb3a81e KB |
230 | return; |
231 | } | |
232 | } else { | |
d8eaee96 KB |
233 | if (bcmp(inb, outb, inn)) { |
234 | printf("tcopy: tapes have different data.\n"); | |
ceb3a81e | 235 | break; |
d8eaee96 | 236 | } |
ceb3a81e KB |
237 | eot = 0; |
238 | } | |
239 | } | |
ceb3a81e | 240 | exit(1); |
f7c68695 JB |
241 | } |
242 | ||
6894b138 | 243 | void |
2c00311e | 244 | intr() |
f7c68695 | 245 | { |
2c00311e MK |
246 | if (record) |
247 | if (record - lastrec > 1) | |
248 | printf("records %ld to %ld\n", lastrec, record); | |
f7c68695 | 249 | else |
2c00311e MK |
250 | printf("record %ld\n", lastrec); |
251 | printf("interrupt at file %d: record %ld\n", filen, record); | |
ceb3a81e KB |
252 | printf("total length: %ld bytes\n", tsize + size); |
253 | exit(1); | |
254 | } | |
255 | ||
17cd062a | 256 | char * |
ceb3a81e KB |
257 | getspace(blk) |
258 | int blk; | |
259 | { | |
260 | char *bp, *malloc(); | |
261 | ||
262 | if ((bp = malloc((u_int)blk)) == NULL) { | |
d8eaee96 | 263 | fprintf(stderr, "tcopy: no memory\n"); |
ceb3a81e KB |
264 | exit(11); |
265 | } | |
266 | return(bp); | |
267 | } | |
268 | ||
ceb3a81e KB |
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 | ||
ceb3a81e KB |
282 | usage() |
283 | { | |
d8eaee96 | 284 | fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n"); |
f7c68695 JB |
285 | exit(1); |
286 | } |