xref: /csrg-svn/usr.bin/tcopy/tcopy.c (revision 45518)
124973Sbloom /*
230870Skarels  * Copyright (c) 1985, 1987 Regents of the University of California.
332759Sbostic  * All rights reserved.
432759Sbostic  *
542770Sbostic  * %sccs.include.redist.c%
624973Sbloom  */
724973Sbloom 
824973Sbloom #ifndef lint
924973Sbloom char copyright[] =
1030870Skarels "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\
1124973Sbloom  All rights reserved.\n";
1232759Sbostic #endif /* not lint */
1324973Sbloom 
1424973Sbloom #ifndef lint
15*45518Skarels static char sccsid[] = "@(#)tcopy.c	5.15 (Berkeley) 11/05/90";
1632759Sbostic #endif /* not lint */
1724973Sbloom 
1837859Sbostic #include <sys/types.h>
1937859Sbostic #include <sys/signal.h>
2024973Sbloom #include <sys/file.h>
2124973Sbloom #include <sys/ioctl.h>
2224973Sbloom #include <sys/mtio.h>
2330873Skarels #include <sys/errno.h>
2437859Sbostic #include <stdio.h>
2537859Sbostic #include "pathnames.h"
2624973Sbloom 
2734185Sbostic #define	MAXREC	(64 * 1024)
2834185Sbostic #define	NOCOUNT	(-2)
2934185Sbostic 
3034185Sbostic int	filen, guesslen, maxblk = MAXREC;
3134185Sbostic long	lastrec, record, size, tsize;
3224973Sbloom 
3324973Sbloom main(argc, argv)
3432759Sbostic 	int argc;
3532759Sbostic 	char **argv;
3624973Sbloom {
3734185Sbostic 	extern char *optarg;
3834185Sbostic 	extern int optind, errno;
3934185Sbostic 	register int lastnread, nread, nw, inp, outp;
4034185Sbostic 	enum {READ, VERIFY, COPY, COPYVERIFY} op = READ;
4139834Sbostic 	sig_t oldsig;
4239834Sbostic 	int ch, needeof;
4334185Sbostic 	char *buff, *inf, *getspace();
4439834Sbostic 	void intr();
4524973Sbloom 
4634185Sbostic 	guesslen = 1;
4734185Sbostic 	while ((ch = getopt(argc, argv, "cs:v")) != EOF)
4834185Sbostic 		switch((char)ch) {
4934185Sbostic 		case 'c':
5034185Sbostic 			op = COPYVERIFY;
5134185Sbostic 			break;
5230870Skarels 		case 's':
5334185Sbostic 			maxblk = atoi(optarg);
5430870Skarels 			if (maxblk <= 0) {
5536197Sbostic 				fprintf(stderr, "tcopy: illegal block size\n");
5634185Sbostic 				usage();
5730870Skarels 			}
5830870Skarels 			guesslen = 0;
5930870Skarels 			break;
6034185Sbostic 		case 'v':
6134185Sbostic 			op = VERIFY;
6234185Sbostic 			break;
6334185Sbostic 		case '?':
6434185Sbostic 		default:
6534185Sbostic 			usage();
6630870Skarels 		}
6734185Sbostic 	argc -= optind;
6834185Sbostic 	argv += optind;
6934185Sbostic 
7034185Sbostic 	switch(argc) {
7134185Sbostic 	case 0:
7234185Sbostic 		if (op != READ)
7334185Sbostic 			usage();
7437859Sbostic 		inf = _PATH_DEFTAPE;
7534185Sbostic 		break;
7634185Sbostic 	case 1:
7734185Sbostic 		if (op != READ)
7834185Sbostic 			usage();
7934185Sbostic 		inf = argv[0];
8034185Sbostic 		break;
8134185Sbostic 	case 2:
8234185Sbostic 		if (op == READ)
8334185Sbostic 			op = COPY;
8434185Sbostic 		inf = argv[0];
8534954Sbostic 		if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR,
8634954Sbostic 		    0666)) < 0) {
8734185Sbostic 			perror(argv[1]);
8834185Sbostic 			exit(3);
8934185Sbostic 		}
9034185Sbostic 		break;
9134185Sbostic 	default:
9234185Sbostic 		usage();
9330870Skarels 	}
9434185Sbostic 
9530870Skarels 	if ((inp = open(inf, O_RDONLY, 0)) < 0) {
9630870Skarels 		perror(inf);
9730870Skarels 		exit(1);
9830870Skarels 	}
9934185Sbostic 
10034185Sbostic 	buff = getspace(maxblk);
10134185Sbostic 
10234185Sbostic 	if (op == VERIFY) {
10334185Sbostic 		verify(inp, outp, buff);
10434185Sbostic 		exit(0);
10524973Sbloom 	}
10634185Sbostic 
10734185Sbostic 	if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
10830870Skarels 		(void) signal(SIGINT, intr);
10934185Sbostic 
11034185Sbostic 	needeof = 0;
11134185Sbostic 	for (lastnread = NOCOUNT;;) {
11234185Sbostic 		if ((nread = read(inp, buff, maxblk)) == -1) {
11334185Sbostic 			while (errno == EINVAL && (maxblk -= 1024)) {
11434185Sbostic 				nread = read(inp, buff, maxblk);
11534185Sbostic 				if (nread >= 0)
11634185Sbostic 					goto r1;
11730870Skarels 			}
11832759Sbostic 			fprintf(stderr, "read error, file %d, record %ld: ",
11930870Skarels 			    filen, record);
12030870Skarels 			perror("");
12134185Sbostic 			exit(1);
12234185Sbostic 		} else if (nread != lastnread) {
12334185Sbostic 			if (lastnread != 0 && lastnread != NOCOUNT) {
12430870Skarels 				if (lastrec == 0 && nread == 0)
12532759Sbostic 					printf("%ld records\n", record);
12630870Skarels 				else if (record - lastrec > 1)
12730870Skarels 					printf("records %ld to %ld\n",
12830870Skarels 					    lastrec, record);
12930870Skarels 				else
13030870Skarels 					printf("record %ld\n", lastrec);
13130870Skarels 			}
13230870Skarels 			if (nread != 0)
13330870Skarels 				printf("file %d: block size %d: ",
13430870Skarels 				    filen, nread);
13532759Sbostic 			(void) fflush(stdout);
13630870Skarels 			lastrec = record;
13724973Sbloom 		}
13834185Sbostic r1:		guesslen = 0;
13930870Skarels 		if (nread > 0) {
140*45518Skarels 			if (op == COPY || op == COPYVERIFY) {
14130870Skarels 				if (needeof) {
14234185Sbostic 					writeop(outp, MTWEOF);
14334185Sbostic 					needeof = 0;
14430870Skarels 				}
14530870Skarels 				nw = write(outp, buff, nread);
14630870Skarels 				if (nw != nread) {
14730870Skarels 				    fprintf(stderr,
14832759Sbostic 					"write error, file %d, record %ld: ",
14930870Skarels 					filen, record);
15030870Skarels 				    if (nw == -1)
15130870Skarels 					perror("");
15230870Skarels 				    else
15330870Skarels 					fprintf(stderr,
15430870Skarels 					    "write (%d) != read (%d)\n",
15530870Skarels 					    nw, nread);
15630870Skarels 				    fprintf(stderr, "copy aborted\n");
15730870Skarels 				    exit(5);
15830870Skarels 				}
15930870Skarels 			}
16030870Skarels 			size += nread;
16130870Skarels 			record++;
16230870Skarels 		} else {
16334185Sbostic 			if (lastnread <= 0 && lastnread != NOCOUNT) {
16424973Sbloom 				printf("eot\n");
16524973Sbloom 				break;
16624973Sbloom 			}
16724973Sbloom 			printf("file %d: eof after %ld records: %ld bytes\n",
16830870Skarels 				filen, record, size);
16930870Skarels 			needeof = 1;
17024973Sbloom 			filen++;
17124973Sbloom 			tsize += size;
17234185Sbostic 			size = record = lastrec = 0;
17334185Sbostic 			lastnread = 0;
17424973Sbloom 		}
17534185Sbostic 		lastnread = nread;
17624973Sbloom 	}
17724973Sbloom 	printf("total length: %ld bytes\n", tsize);
17834185Sbostic 	(void)signal(SIGINT, oldsig);
179*45518Skarels 	if (op == COPY || op == COPYVERIFY) {
18034185Sbostic 		writeop(outp, MTWEOF);
18134185Sbostic 		writeop(outp, MTWEOF);
18234185Sbostic 		if (op == COPYVERIFY) {
18334185Sbostic 			writeop(outp, MTREW);
18434185Sbostic 			writeop(inp, MTREW);
18534185Sbostic 			verify(inp, outp, buff);
18634185Sbostic 		}
18734185Sbostic 	}
18834185Sbostic 	exit(0);
18924973Sbloom }
19024973Sbloom 
19134185Sbostic verify(inp, outp, outb)
19234185Sbostic 	register int inp, outp;
19334185Sbostic 	register char *outb;
19434185Sbostic {
19535696Sbostic 	extern int errno;
19634185Sbostic 	register int eot, inmaxblk, inn, outmaxblk, outn;
19734185Sbostic 	register char *inb;
19834185Sbostic 	char *getspace();
19934185Sbostic 
20034185Sbostic 	inb = getspace(maxblk);
20134185Sbostic 	inmaxblk = outmaxblk = maxblk;
20234185Sbostic 	for (eot = 0;; guesslen = 0) {
20334185Sbostic 		if ((inn = read(inp, inb, inmaxblk)) == -1) {
20434185Sbostic 			if (guesslen)
20534185Sbostic 				while (errno == EINVAL && (inmaxblk -= 1024)) {
20634185Sbostic 					inn = read(inp, inb, inmaxblk);
20734185Sbostic 					if (inn >= 0)
20834185Sbostic 						goto r1;
20934185Sbostic 				}
21034185Sbostic 			perror("tcopy: read error");
21136197Sbostic 			break;
21234185Sbostic 		}
21334185Sbostic r1:		if ((outn = read(outp, outb, outmaxblk)) == -1) {
21434185Sbostic 			if (guesslen)
21534185Sbostic 				while (errno == EINVAL && (outmaxblk -= 1024)) {
21634185Sbostic 					outn = read(outp, outb, outmaxblk);
21734185Sbostic 					if (outn >= 0)
21834185Sbostic 						goto r2;
21934185Sbostic 				}
22034185Sbostic 			perror("tcopy: read error");
22136197Sbostic 			break;
22234185Sbostic 		}
22336197Sbostic r2:		if (inn != outn) {
22436197Sbostic 			printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn);
22534185Sbostic 			break;
22636197Sbostic 		}
22734185Sbostic 		if (!inn) {
22834185Sbostic 			if (eot++) {
22936197Sbostic 				printf("tcopy: tapes are identical.\n");
23034185Sbostic 				return;
23134185Sbostic 			}
23234185Sbostic 		} else {
23336197Sbostic 			if (bcmp(inb, outb, inn)) {
23436197Sbostic 				printf("tcopy: tapes have different data.\n");
23534185Sbostic 				break;
23636197Sbostic 			}
23734185Sbostic 			eot = 0;
23834185Sbostic 		}
23934185Sbostic 	}
24034185Sbostic 	exit(1);
24134185Sbostic }
24234185Sbostic 
24339834Sbostic void
24430870Skarels intr()
24524973Sbloom {
24630870Skarels 	if (record)
24730870Skarels 		if (record - lastrec > 1)
24830870Skarels 			printf("records %ld to %ld\n", lastrec, record);
24924973Sbloom 		else
25030870Skarels 			printf("record %ld\n", lastrec);
25130870Skarels 	printf("interrupt at file %d: record %ld\n", filen, record);
25234185Sbostic 	printf("total length: %ld bytes\n", tsize + size);
25324973Sbloom 	exit(1);
25424973Sbloom }
25534185Sbostic 
25635696Sbostic char *
25734185Sbostic getspace(blk)
25834185Sbostic 	int blk;
25934185Sbostic {
26034185Sbostic 	char *bp, *malloc();
26134185Sbostic 
26234185Sbostic 	if ((bp = malloc((u_int)blk)) == NULL) {
26336197Sbostic 		fprintf(stderr, "tcopy: no memory\n");
26434185Sbostic 		exit(11);
26534185Sbostic 	}
26634185Sbostic 	return(bp);
26734185Sbostic }
26834185Sbostic 
26934185Sbostic writeop(fd, type)
27034185Sbostic 	int fd, type;
27134185Sbostic {
27234185Sbostic 	struct mtop op;
27334185Sbostic 
27434185Sbostic 	op.mt_op = type;
27534185Sbostic 	op.mt_count = (daddr_t)1;
27634185Sbostic 	if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) {
27734185Sbostic 		perror("tcopy: tape op");
27834185Sbostic 		exit(6);
27934185Sbostic 	}
28034185Sbostic }
28134185Sbostic 
28234185Sbostic usage()
28334185Sbostic {
28436197Sbostic 	fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n");
28534185Sbostic 	exit(1);
28634185Sbostic }
287