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