Change <sys/queue.h> to <queue.h> (thanks Nate! I'm falling asleep
[unix-history] / usr.bin / tcopy / tcopy.c
CommitLineData
15637ed4
RG
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
35char 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
41static char sccsid[] = "@(#)tcopy.c 5.15 (Berkeley) 11/5/90";
42#endif /* not lint */
43
44#include <sys/types.h>
45#include <sys/signal.h>
46#include <sys/file.h>
47#include <sys/ioctl.h>
48#include <sys/mtio.h>
49#include <sys/errno.h>
50#include <stdio.h>
51#include "pathnames.h"
52
53#define MAXREC (64 * 1024)
54#define NOCOUNT (-2)
55
56int filen, guesslen, maxblk = MAXREC;
57long lastrec, record, size, tsize;
58
59main(argc, argv)
60 int argc;
61 char **argv;
62{
63 extern char *optarg;
64 extern int optind, errno;
65 register int lastnread, nread, nw, inp, outp;
66 enum {READ, VERIFY, COPY, COPYVERIFY} op = READ;
67 sig_t oldsig;
68 int ch, needeof;
69 char *buff, *inf, *getspace();
70 void intr();
71
72 guesslen = 1;
73 while ((ch = getopt(argc, argv, "cs:v")) != EOF)
74 switch((char)ch) {
75 case 'c':
76 op = COPYVERIFY;
77 break;
78 case 's':
79 maxblk = atoi(optarg);
80 if (maxblk <= 0) {
81 fprintf(stderr, "tcopy: illegal block size\n");
82 usage();
83 }
84 guesslen = 0;
85 break;
86 case 'v':
87 op = VERIFY;
88 break;
89 case '?':
90 default:
91 usage();
92 }
93 argc -= optind;
94 argv += optind;
95
96 switch(argc) {
97 case 0:
98 if (op != READ)
99 usage();
100 inf = _PATH_DEFTAPE;
101 break;
102 case 1:
103 if (op != READ)
104 usage();
105 inf = argv[0];
106 break;
107 case 2:
108 if (op == READ)
109 op = COPY;
110 inf = argv[0];
111 if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR,
112 0666)) < 0) {
113 perror(argv[1]);
114 exit(3);
115 }
116 break;
117 default:
118 usage();
119 }
120
121 if ((inp = open(inf, O_RDONLY, 0)) < 0) {
122 perror(inf);
123 exit(1);
124 }
125
126 buff = getspace(maxblk);
127
128 if (op == VERIFY) {
129 verify(inp, outp, buff);
130 exit(0);
131 }
132
133 if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
134 (void) signal(SIGINT, intr);
135
136 needeof = 0;
137 for (lastnread = NOCOUNT;;) {
138 if ((nread = read(inp, buff, maxblk)) == -1) {
139 while (errno == EINVAL && (maxblk -= 1024)) {
140 nread = read(inp, buff, maxblk);
141 if (nread >= 0)
142 goto r1;
143 }
144 fprintf(stderr, "read error, file %d, record %ld: ",
145 filen, record);
146 perror("");
147 exit(1);
148 } else if (nread != lastnread) {
149 if (lastnread != 0 && lastnread != NOCOUNT) {
150 if (lastrec == 0 && nread == 0)
151 printf("%ld records\n", record);
152 else if (record - lastrec > 1)
153 printf("records %ld to %ld\n",
154 lastrec, record);
155 else
156 printf("record %ld\n", lastrec);
157 }
158 if (nread != 0)
159 printf("file %d: block size %d: ",
160 filen, nread);
161 (void) fflush(stdout);
162 lastrec = record;
163 }
164r1: guesslen = 0;
165 if (nread > 0) {
166 if (op == COPY || op == COPYVERIFY) {
167 if (needeof) {
168 writeop(outp, MTWEOF);
169 needeof = 0;
170 }
171 nw = write(outp, buff, nread);
172 if (nw != nread) {
173 fprintf(stderr,
174 "write error, file %d, record %ld: ",
175 filen, record);
176 if (nw == -1)
177 perror("");
178 else
179 fprintf(stderr,
180 "write (%d) != read (%d)\n",
181 nw, nread);
182 fprintf(stderr, "copy aborted\n");
183 exit(5);
184 }
185 }
186 size += nread;
187 record++;
188 } else {
189 if (lastnread <= 0 && lastnread != NOCOUNT) {
190 printf("eot\n");
191 break;
192 }
193 printf("file %d: eof after %ld records: %ld bytes\n",
194 filen, record, size);
195 needeof = 1;
196 filen++;
197 tsize += size;
198 size = record = lastrec = 0;
199 lastnread = 0;
200 }
201 lastnread = nread;
202 }
203 printf("total length: %ld bytes\n", tsize);
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
217verify(inp, outp, outb)
218 register int inp, outp;
219 register char *outb;
220{
221 extern int errno;
222 register int eot, inmaxblk, inn, outmaxblk, outn;
223 register char *inb;
224 char *getspace();
225
226 inb = getspace(maxblk);
227 inmaxblk = outmaxblk = maxblk;
228 for (eot = 0;; guesslen = 0) {
229 if ((inn = read(inp, inb, inmaxblk)) == -1) {
230 if (guesslen)
231 while (errno == EINVAL && (inmaxblk -= 1024)) {
232 inn = read(inp, inb, inmaxblk);
233 if (inn >= 0)
234 goto r1;
235 }
236 perror("tcopy: read error");
237 break;
238 }
239r1: if ((outn = read(outp, outb, outmaxblk)) == -1) {
240 if (guesslen)
241 while (errno == EINVAL && (outmaxblk -= 1024)) {
242 outn = read(outp, outb, outmaxblk);
243 if (outn >= 0)
244 goto r2;
245 }
246 perror("tcopy: read error");
247 break;
248 }
249r2: if (inn != outn) {
250 printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn);
251 break;
252 }
253 if (!inn) {
254 if (eot++) {
255 printf("tcopy: tapes are identical.\n");
256 return;
257 }
258 } else {
259 if (bcmp(inb, outb, inn)) {
260 printf("tcopy: tapes have different data.\n");
261 break;
262 }
263 eot = 0;
264 }
265 }
266 exit(1);
267}
268
269void
270intr()
271{
272 if (record)
273 if (record - lastrec > 1)
274 printf("records %ld to %ld\n", lastrec, record);
275 else
276 printf("record %ld\n", lastrec);
277 printf("interrupt at file %d: record %ld\n", filen, record);
278 printf("total length: %ld bytes\n", tsize + size);
279 exit(1);
280}
281
282char *
283getspace(blk)
284 int blk;
285{
286 char *bp, *malloc();
287
288 if ((bp = malloc((u_int)blk)) == NULL) {
289 fprintf(stderr, "tcopy: no memory\n");
290 exit(11);
291 }
292 return(bp);
293}
294
295writeop(fd, type)
296 int fd, type;
297{
298 struct mtop op;
299
300 op.mt_op = type;
301 op.mt_count = (daddr_t)1;
302 if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) {
303 perror("tcopy: tape op");
304 exit(6);
305 }
306}
307
308usage()
309{
310 fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n");
311 exit(1);
312}