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