xref: /csrg-svn/usr.bin/tcopy/tcopy.c (revision 34185)
124973Sbloom /*
230870Skarels  * Copyright (c) 1985, 1987 Regents of the University of California.
332759Sbostic  * All rights reserved.
432759Sbostic  *
532759Sbostic  * Redistribution and use in source and binary forms are permitted
632759Sbostic  * provided that this notice is preserved and that due credit is given
732759Sbostic  * to the University of California at Berkeley. The name of the University
832759Sbostic  * may not be used to endorse or promote products derived from this
932759Sbostic  * software without specific written prior permission. This software
1032759Sbostic  * is provided ``as is'' without express or implied warranty.
1124973Sbloom  */
1224973Sbloom 
1324973Sbloom #ifndef lint
1424973Sbloom char copyright[] =
1530870Skarels "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\
1624973Sbloom  All rights reserved.\n";
1732759Sbostic #endif /* not lint */
1824973Sbloom 
1924973Sbloom #ifndef lint
20*34185Sbostic static char sccsid[] = "@(#)tcopy.c	5.7 (Berkeley) 05/04/88";
2132759Sbostic #endif /* not lint */
2224973Sbloom 
2324973Sbloom #include <stdio.h>
2425590Sbloom #include <signal.h>
2524973Sbloom #include <sys/file.h>
2624973Sbloom #include <sys/types.h>
2724973Sbloom #include <sys/ioctl.h>
2824973Sbloom #include <sys/mtio.h>
2930873Skarels #include <sys/errno.h>
3024973Sbloom 
31*34185Sbostic #define	MAXREC	(64 * 1024)
32*34185Sbostic #define	NOCOUNT	(-2)
33*34185Sbostic 
3430870Skarels #undef DEFTAPE
3530870Skarels #define	DEFTAPE	"/dev/rmt0"
3624973Sbloom 
37*34185Sbostic int	filen, guesslen, maxblk = MAXREC;
38*34185Sbostic long	lastrec, record, size, tsize;
3924973Sbloom 
4024973Sbloom main(argc, argv)
4132759Sbostic 	int argc;
4232759Sbostic 	char **argv;
4324973Sbloom {
44*34185Sbostic 	extern char *optarg;
45*34185Sbostic 	extern int optind, errno;
46*34185Sbostic 	register int lastnread, nread, nw, inp, outp;
47*34185Sbostic 	enum {READ, VERIFY, COPY, COPYVERIFY} op = READ;
48*34185Sbostic 	int ch, needeof, intr(), (*oldsig)();
49*34185Sbostic 	char *buff, *inf, *getspace();
5024973Sbloom 
51*34185Sbostic 	guesslen = 1;
52*34185Sbostic 	while ((ch = getopt(argc, argv, "cs:v")) != EOF)
53*34185Sbostic 		switch((char)ch) {
54*34185Sbostic 		case 'c':
55*34185Sbostic 			op = COPYVERIFY;
56*34185Sbostic 			break;
5730870Skarels 		case 's':
58*34185Sbostic 			maxblk = atoi(optarg);
5930870Skarels 			if (maxblk <= 0) {
60*34185Sbostic 				fputs("tcopy: illegal block size\n", stderr);
61*34185Sbostic 				usage();
6230870Skarels 			}
6330870Skarels 			guesslen = 0;
6430870Skarels 			break;
65*34185Sbostic 		case 'v':
66*34185Sbostic 			op = VERIFY;
67*34185Sbostic 			break;
68*34185Sbostic 		case '?':
69*34185Sbostic 		default:
70*34185Sbostic 			usage();
7130870Skarels 		}
72*34185Sbostic 	argc -= optind;
73*34185Sbostic 	argv += optind;
74*34185Sbostic 
75*34185Sbostic 	switch(argc) {
76*34185Sbostic 	case 0:
77*34185Sbostic 		if (op != READ)
78*34185Sbostic 			usage();
79*34185Sbostic 		inf = DEFTAPE;
80*34185Sbostic 		break;
81*34185Sbostic 	case 1:
82*34185Sbostic 		if (op != READ)
83*34185Sbostic 			usage();
84*34185Sbostic 		inf = argv[0];
85*34185Sbostic 		break;
86*34185Sbostic 	case 2:
87*34185Sbostic 		if (op == READ)
88*34185Sbostic 			op = COPY;
89*34185Sbostic 		inf = argv[0];
90*34185Sbostic 		if ((outp = open(argv[1], O_RDWR, 0666)) < 0) {
91*34185Sbostic 			perror(argv[1]);
92*34185Sbostic 			exit(3);
93*34185Sbostic 		}
94*34185Sbostic 		break;
95*34185Sbostic 	default:
96*34185Sbostic 		usage();
9730870Skarels 	}
98*34185Sbostic 
9930870Skarels 	if ((inp = open(inf, O_RDONLY, 0)) < 0) {
10030870Skarels 		perror(inf);
10130870Skarels 		exit(1);
10230870Skarels 	}
103*34185Sbostic 
104*34185Sbostic 	buff = getspace(maxblk);
105*34185Sbostic 
106*34185Sbostic 	if (op == VERIFY) {
107*34185Sbostic 		verify(inp, outp, buff);
108*34185Sbostic 		exit(0);
10924973Sbloom 	}
110*34185Sbostic 
111*34185Sbostic 	if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
11230870Skarels 		(void) signal(SIGINT, intr);
113*34185Sbostic 
114*34185Sbostic 	needeof = 0;
115*34185Sbostic 	for (lastnread = NOCOUNT;;) {
116*34185Sbostic 		if ((nread = read(inp, buff, maxblk)) == -1) {
117*34185Sbostic 			while (errno == EINVAL && (maxblk -= 1024)) {
118*34185Sbostic 				nread = read(inp, buff, maxblk);
119*34185Sbostic 				if (nread >= 0)
120*34185Sbostic 					goto r1;
12130870Skarels 			}
12232759Sbostic 			fprintf(stderr, "read error, file %d, record %ld: ",
12330870Skarels 			    filen, record);
12430870Skarels 			perror("");
125*34185Sbostic 			exit(1);
126*34185Sbostic 		} else if (nread != lastnread) {
127*34185Sbostic 			if (lastnread != 0 && lastnread != NOCOUNT) {
12830870Skarels 				if (lastrec == 0 && nread == 0)
12932759Sbostic 					printf("%ld records\n", record);
13030870Skarels 				else if (record - lastrec > 1)
13130870Skarels 					printf("records %ld to %ld\n",
13230870Skarels 					    lastrec, record);
13330870Skarels 				else
13430870Skarels 					printf("record %ld\n", lastrec);
13530870Skarels 			}
13630870Skarels 			if (nread != 0)
13730870Skarels 				printf("file %d: block size %d: ",
13830870Skarels 				    filen, nread);
13932759Sbostic 			(void) fflush(stdout);
14030870Skarels 			lastrec = record;
14124973Sbloom 		}
142*34185Sbostic r1:		guesslen = 0;
14330870Skarels 		if (nread > 0) {
144*34185Sbostic 			if (op >= COPY) {
14530870Skarels 				if (needeof) {
146*34185Sbostic 					writeop(outp, MTWEOF);
147*34185Sbostic 					needeof = 0;
14830870Skarels 				}
14930870Skarels 				nw = write(outp, buff, nread);
15030870Skarels 				if (nw != nread) {
15130870Skarels 				    fprintf(stderr,
15232759Sbostic 					"write error, file %d, record %ld: ",
15330870Skarels 					filen, record);
15430870Skarels 				    if (nw == -1)
15530870Skarels 					perror("");
15630870Skarels 				    else
15730870Skarels 					fprintf(stderr,
15830870Skarels 					    "write (%d) != read (%d)\n",
15930870Skarels 					    nw, nread);
16030870Skarels 				    fprintf(stderr, "copy aborted\n");
16130870Skarels 				    exit(5);
16230870Skarels 				}
16330870Skarels 			}
16430870Skarels 			size += nread;
16530870Skarels 			record++;
16630870Skarels 		} else {
167*34185Sbostic 			if (lastnread <= 0 && lastnread != NOCOUNT) {
16824973Sbloom 				printf("eot\n");
16924973Sbloom 				break;
17024973Sbloom 			}
17124973Sbloom 			printf("file %d: eof after %ld records: %ld bytes\n",
17230870Skarels 				filen, record, size);
17330870Skarels 			needeof = 1;
17424973Sbloom 			filen++;
17524973Sbloom 			tsize += size;
176*34185Sbostic 			size = record = lastrec = 0;
177*34185Sbostic 			lastnread = 0;
17824973Sbloom 		}
179*34185Sbostic 		lastnread = nread;
18024973Sbloom 	}
18124973Sbloom 	printf("total length: %ld bytes\n", tsize);
182*34185Sbostic 	(void)signal(SIGINT, oldsig);
183*34185Sbostic 	if (op >= COPY) {
184*34185Sbostic 		writeop(outp, MTWEOF);
185*34185Sbostic 		writeop(outp, MTWEOF);
186*34185Sbostic 		if (op == COPYVERIFY) {
187*34185Sbostic 			writeop(outp, MTREW);
188*34185Sbostic 			writeop(inp, MTREW);
189*34185Sbostic 			verify(inp, outp, buff);
190*34185Sbostic 		}
191*34185Sbostic 	}
192*34185Sbostic 	exit(0);
19324973Sbloom }
19424973Sbloom 
195*34185Sbostic static
196*34185Sbostic verify(inp, outp, outb)
197*34185Sbostic 	register int inp, outp;
198*34185Sbostic 	register char *outb;
199*34185Sbostic {
200*34185Sbostic 	register int eot, inmaxblk, inn, outmaxblk, outn;
201*34185Sbostic 	register char *inb;
202*34185Sbostic 	char *getspace();
203*34185Sbostic 
204*34185Sbostic 	inb = getspace(maxblk);
205*34185Sbostic 	inmaxblk = outmaxblk = maxblk;
206*34185Sbostic 	for (eot = 0;; guesslen = 0) {
207*34185Sbostic 		if ((inn = read(inp, inb, inmaxblk)) == -1) {
208*34185Sbostic 			if (guesslen)
209*34185Sbostic 				while (errno == EINVAL && (inmaxblk -= 1024)) {
210*34185Sbostic 					inn = read(inp, inb, inmaxblk);
211*34185Sbostic 					if (inn >= 0)
212*34185Sbostic 						goto r1;
213*34185Sbostic 				}
214*34185Sbostic 			perror("tcopy: read error");
215*34185Sbostic 			exit(1);
216*34185Sbostic 		}
217*34185Sbostic r1:		if ((outn = read(outp, outb, outmaxblk)) == -1) {
218*34185Sbostic 			if (guesslen)
219*34185Sbostic 				while (errno == EINVAL && (outmaxblk -= 1024)) {
220*34185Sbostic 					outn = read(outp, outb, outmaxblk);
221*34185Sbostic 					if (outn >= 0)
222*34185Sbostic 						goto r2;
223*34185Sbostic 				}
224*34185Sbostic 			perror("tcopy: read error");
225*34185Sbostic 			exit(1);
226*34185Sbostic 		}
227*34185Sbostic r2:		if (inn != outn)
228*34185Sbostic 			break;
229*34185Sbostic 		if (!inn) {
230*34185Sbostic 			if (eot++) {
231*34185Sbostic 				puts("tcopy: tapes are identical.");
232*34185Sbostic 				return;
233*34185Sbostic 			}
234*34185Sbostic 		} else {
235*34185Sbostic 			if (bcmp(inb, outb, inn))
236*34185Sbostic 				break;
237*34185Sbostic 			eot = 0;
238*34185Sbostic 		}
239*34185Sbostic 	}
240*34185Sbostic 	puts("tcopy: tapes are different.");
241*34185Sbostic 	exit(1);
242*34185Sbostic }
243*34185Sbostic 
244*34185Sbostic static
24530870Skarels intr()
24624973Sbloom {
24730870Skarels 	if (record)
24830870Skarels 		if (record - lastrec > 1)
24930870Skarels 			printf("records %ld to %ld\n", lastrec, record);
25024973Sbloom 		else
25130870Skarels 			printf("record %ld\n", lastrec);
25230870Skarels 	printf("interrupt at file %d: record %ld\n", filen, record);
253*34185Sbostic 	printf("total length: %ld bytes\n", tsize + size);
25424973Sbloom 	exit(1);
25524973Sbloom }
256*34185Sbostic 
257*34185Sbostic static char *
258*34185Sbostic getspace(blk)
259*34185Sbostic 	int blk;
260*34185Sbostic {
261*34185Sbostic 	char *bp, *malloc();
262*34185Sbostic 
263*34185Sbostic 	if ((bp = malloc((u_int)blk)) == NULL) {
264*34185Sbostic 		fputs("tcopy: no memory\n", stderr);
265*34185Sbostic 		exit(11);
266*34185Sbostic 	}
267*34185Sbostic 	return(bp);
268*34185Sbostic }
269*34185Sbostic 
270*34185Sbostic static
271*34185Sbostic writeop(fd, type)
272*34185Sbostic 	int fd, type;
273*34185Sbostic {
274*34185Sbostic 	struct mtop op;
275*34185Sbostic 
276*34185Sbostic 	op.mt_op = type;
277*34185Sbostic 	op.mt_count = (daddr_t)1;
278*34185Sbostic 	if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) {
279*34185Sbostic 		perror("tcopy: tape op");
280*34185Sbostic 		exit(6);
281*34185Sbostic 	}
282*34185Sbostic }
283*34185Sbostic 
284*34185Sbostic static
285*34185Sbostic usage()
286*34185Sbostic {
287*34185Sbostic 	fputs("usage: tcopy [-cv] [-s maxblk] src [dest]\n", stderr);
288*34185Sbostic 	exit(1);
289*34185Sbostic }
290