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