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