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