xref: /csrg-svn/usr.bin/tcopy/tcopy.c (revision 34911)
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
6*34911Sbostic  * provided that the above copyright notice and this paragraph are
7*34911Sbostic  * duplicated in all such forms and that any documentation,
8*34911Sbostic  * advertising materials, and other materials related to such
9*34911Sbostic  * distribution and use acknowledge that the software was developed
10*34911Sbostic  * by the University of California, Berkeley.  The name of the
11*34911Sbostic  * University may not be used to endorse or promote products derived
12*34911Sbostic  * from this software without specific prior written permission.
13*34911Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*34911Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*34911Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1624973Sbloom  */
1724973Sbloom 
1824973Sbloom #ifndef lint
1924973Sbloom char copyright[] =
2030870Skarels "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\
2124973Sbloom  All rights reserved.\n";
2232759Sbostic #endif /* not lint */
2324973Sbloom 
2424973Sbloom #ifndef lint
25*34911Sbostic static char sccsid[] = "@(#)tcopy.c	5.8 (Berkeley) 06/29/88";
2632759Sbostic #endif /* not lint */
2724973Sbloom 
2824973Sbloom #include <stdio.h>
2925590Sbloom #include <signal.h>
3024973Sbloom #include <sys/file.h>
3124973Sbloom #include <sys/types.h>
3224973Sbloom #include <sys/ioctl.h>
3324973Sbloom #include <sys/mtio.h>
3430873Skarels #include <sys/errno.h>
3524973Sbloom 
3634185Sbostic #define	MAXREC	(64 * 1024)
3734185Sbostic #define	NOCOUNT	(-2)
3834185Sbostic 
3930870Skarels #undef DEFTAPE
4030870Skarels #define	DEFTAPE	"/dev/rmt0"
4124973Sbloom 
4234185Sbostic int	filen, guesslen, maxblk = MAXREC;
4334185Sbostic long	lastrec, record, size, tsize;
4424973Sbloom 
4524973Sbloom main(argc, argv)
4632759Sbostic 	int argc;
4732759Sbostic 	char **argv;
4824973Sbloom {
4934185Sbostic 	extern char *optarg;
5034185Sbostic 	extern int optind, errno;
5134185Sbostic 	register int lastnread, nread, nw, inp, outp;
5234185Sbostic 	enum {READ, VERIFY, COPY, COPYVERIFY} op = READ;
5334185Sbostic 	int ch, needeof, intr(), (*oldsig)();
5434185Sbostic 	char *buff, *inf, *getspace();
5524973Sbloom 
5634185Sbostic 	guesslen = 1;
5734185Sbostic 	while ((ch = getopt(argc, argv, "cs:v")) != EOF)
5834185Sbostic 		switch((char)ch) {
5934185Sbostic 		case 'c':
6034185Sbostic 			op = COPYVERIFY;
6134185Sbostic 			break;
6230870Skarels 		case 's':
6334185Sbostic 			maxblk = atoi(optarg);
6430870Skarels 			if (maxblk <= 0) {
6534185Sbostic 				fputs("tcopy: illegal block size\n", stderr);
6634185Sbostic 				usage();
6730870Skarels 			}
6830870Skarels 			guesslen = 0;
6930870Skarels 			break;
7034185Sbostic 		case 'v':
7134185Sbostic 			op = VERIFY;
7234185Sbostic 			break;
7334185Sbostic 		case '?':
7434185Sbostic 		default:
7534185Sbostic 			usage();
7630870Skarels 		}
7734185Sbostic 	argc -= optind;
7834185Sbostic 	argv += optind;
7934185Sbostic 
8034185Sbostic 	switch(argc) {
8134185Sbostic 	case 0:
8234185Sbostic 		if (op != READ)
8334185Sbostic 			usage();
8434185Sbostic 		inf = DEFTAPE;
8534185Sbostic 		break;
8634185Sbostic 	case 1:
8734185Sbostic 		if (op != READ)
8834185Sbostic 			usage();
8934185Sbostic 		inf = argv[0];
9034185Sbostic 		break;
9134185Sbostic 	case 2:
9234185Sbostic 		if (op == READ)
9334185Sbostic 			op = COPY;
9434185Sbostic 		inf = argv[0];
9534185Sbostic 		if ((outp = open(argv[1], O_RDWR, 0666)) < 0) {
9634185Sbostic 			perror(argv[1]);
9734185Sbostic 			exit(3);
9834185Sbostic 		}
9934185Sbostic 		break;
10034185Sbostic 	default:
10134185Sbostic 		usage();
10230870Skarels 	}
10334185Sbostic 
10430870Skarels 	if ((inp = open(inf, O_RDONLY, 0)) < 0) {
10530870Skarels 		perror(inf);
10630870Skarels 		exit(1);
10730870Skarels 	}
10834185Sbostic 
10934185Sbostic 	buff = getspace(maxblk);
11034185Sbostic 
11134185Sbostic 	if (op == VERIFY) {
11234185Sbostic 		verify(inp, outp, buff);
11334185Sbostic 		exit(0);
11424973Sbloom 	}
11534185Sbostic 
11634185Sbostic 	if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
11730870Skarels 		(void) signal(SIGINT, intr);
11834185Sbostic 
11934185Sbostic 	needeof = 0;
12034185Sbostic 	for (lastnread = NOCOUNT;;) {
12134185Sbostic 		if ((nread = read(inp, buff, maxblk)) == -1) {
12234185Sbostic 			while (errno == EINVAL && (maxblk -= 1024)) {
12334185Sbostic 				nread = read(inp, buff, maxblk);
12434185Sbostic 				if (nread >= 0)
12534185Sbostic 					goto r1;
12630870Skarels 			}
12732759Sbostic 			fprintf(stderr, "read error, file %d, record %ld: ",
12830870Skarels 			    filen, record);
12930870Skarels 			perror("");
13034185Sbostic 			exit(1);
13134185Sbostic 		} else if (nread != lastnread) {
13234185Sbostic 			if (lastnread != 0 && lastnread != NOCOUNT) {
13330870Skarels 				if (lastrec == 0 && nread == 0)
13432759Sbostic 					printf("%ld records\n", record);
13530870Skarels 				else if (record - lastrec > 1)
13630870Skarels 					printf("records %ld to %ld\n",
13730870Skarels 					    lastrec, record);
13830870Skarels 				else
13930870Skarels 					printf("record %ld\n", lastrec);
14030870Skarels 			}
14130870Skarels 			if (nread != 0)
14230870Skarels 				printf("file %d: block size %d: ",
14330870Skarels 				    filen, nread);
14432759Sbostic 			(void) fflush(stdout);
14530870Skarels 			lastrec = record;
14624973Sbloom 		}
14734185Sbostic r1:		guesslen = 0;
14830870Skarels 		if (nread > 0) {
149*34911Sbostic 			if (op >= COPY) {
15030870Skarels 				if (needeof) {
15134185Sbostic 					writeop(outp, MTWEOF);
15234185Sbostic 					needeof = 0;
15330870Skarels 				}
15430870Skarels 				nw = write(outp, buff, nread);
15530870Skarels 				if (nw != nread) {
15630870Skarels 				    fprintf(stderr,
15732759Sbostic 					"write error, file %d, record %ld: ",
15830870Skarels 					filen, record);
15930870Skarels 				    if (nw == -1)
16030870Skarels 					perror("");
16130870Skarels 				    else
16230870Skarels 					fprintf(stderr,
16330870Skarels 					    "write (%d) != read (%d)\n",
16430870Skarels 					    nw, nread);
16530870Skarels 				    fprintf(stderr, "copy aborted\n");
16630870Skarels 				    exit(5);
16730870Skarels 				}
16830870Skarels 			}
16930870Skarels 			size += nread;
17030870Skarels 			record++;
17130870Skarels 		} else {
17234185Sbostic 			if (lastnread <= 0 && lastnread != NOCOUNT) {
17324973Sbloom 				printf("eot\n");
17424973Sbloom 				break;
17524973Sbloom 			}
17624973Sbloom 			printf("file %d: eof after %ld records: %ld bytes\n",
17730870Skarels 				filen, record, size);
17830870Skarels 			needeof = 1;
17924973Sbloom 			filen++;
18024973Sbloom 			tsize += size;
18134185Sbostic 			size = record = lastrec = 0;
18234185Sbostic 			lastnread = 0;
18324973Sbloom 		}
18434185Sbostic 		lastnread = nread;
18524973Sbloom 	}
18624973Sbloom 	printf("total length: %ld bytes\n", tsize);
18734185Sbostic 	(void)signal(SIGINT, oldsig);
188*34911Sbostic 	if (op >= COPY) {
18934185Sbostic 		writeop(outp, MTWEOF);
19034185Sbostic 		writeop(outp, MTWEOF);
19134185Sbostic 		if (op == COPYVERIFY) {
19234185Sbostic 			writeop(outp, MTREW);
19334185Sbostic 			writeop(inp, MTREW);
19434185Sbostic 			verify(inp, outp, buff);
19534185Sbostic 		}
19634185Sbostic 	}
19734185Sbostic 	exit(0);
19824973Sbloom }
19924973Sbloom 
20034185Sbostic static
20134185Sbostic verify(inp, outp, outb)
20234185Sbostic 	register int inp, outp;
20334185Sbostic 	register char *outb;
20434185Sbostic {
20534185Sbostic 	register int eot, inmaxblk, inn, outmaxblk, outn;
20634185Sbostic 	register char *inb;
20734185Sbostic 	char *getspace();
20834185Sbostic 
20934185Sbostic 	inb = getspace(maxblk);
21034185Sbostic 	inmaxblk = outmaxblk = maxblk;
21134185Sbostic 	for (eot = 0;; guesslen = 0) {
21234185Sbostic 		if ((inn = read(inp, inb, inmaxblk)) == -1) {
21334185Sbostic 			if (guesslen)
21434185Sbostic 				while (errno == EINVAL && (inmaxblk -= 1024)) {
21534185Sbostic 					inn = read(inp, inb, inmaxblk);
21634185Sbostic 					if (inn >= 0)
21734185Sbostic 						goto r1;
21834185Sbostic 				}
21934185Sbostic 			perror("tcopy: read error");
22034185Sbostic 			exit(1);
22134185Sbostic 		}
22234185Sbostic r1:		if ((outn = read(outp, outb, outmaxblk)) == -1) {
22334185Sbostic 			if (guesslen)
22434185Sbostic 				while (errno == EINVAL && (outmaxblk -= 1024)) {
22534185Sbostic 					outn = read(outp, outb, outmaxblk);
22634185Sbostic 					if (outn >= 0)
22734185Sbostic 						goto r2;
22834185Sbostic 				}
22934185Sbostic 			perror("tcopy: read error");
23034185Sbostic 			exit(1);
23134185Sbostic 		}
23234185Sbostic r2:		if (inn != outn)
23334185Sbostic 			break;
23434185Sbostic 		if (!inn) {
23534185Sbostic 			if (eot++) {
23634185Sbostic 				puts("tcopy: tapes are identical.");
23734185Sbostic 				return;
23834185Sbostic 			}
23934185Sbostic 		} else {
24034185Sbostic 			if (bcmp(inb, outb, inn))
24134185Sbostic 				break;
24234185Sbostic 			eot = 0;
24334185Sbostic 		}
24434185Sbostic 	}
24534185Sbostic 	puts("tcopy: tapes are different.");
24634185Sbostic 	exit(1);
24734185Sbostic }
24834185Sbostic 
24934185Sbostic static
25030870Skarels intr()
25124973Sbloom {
25230870Skarels 	if (record)
25330870Skarels 		if (record - lastrec > 1)
25430870Skarels 			printf("records %ld to %ld\n", lastrec, record);
25524973Sbloom 		else
25630870Skarels 			printf("record %ld\n", lastrec);
25730870Skarels 	printf("interrupt at file %d: record %ld\n", filen, record);
25834185Sbostic 	printf("total length: %ld bytes\n", tsize + size);
25924973Sbloom 	exit(1);
26024973Sbloom }
26134185Sbostic 
26234185Sbostic static char *
26334185Sbostic getspace(blk)
26434185Sbostic 	int blk;
26534185Sbostic {
26634185Sbostic 	char *bp, *malloc();
26734185Sbostic 
26834185Sbostic 	if ((bp = malloc((u_int)blk)) == NULL) {
26934185Sbostic 		fputs("tcopy: no memory\n", stderr);
27034185Sbostic 		exit(11);
27134185Sbostic 	}
27234185Sbostic 	return(bp);
27334185Sbostic }
27434185Sbostic 
27534185Sbostic static
27634185Sbostic writeop(fd, type)
27734185Sbostic 	int fd, type;
27834185Sbostic {
27934185Sbostic 	struct mtop op;
28034185Sbostic 
28134185Sbostic 	op.mt_op = type;
28234185Sbostic 	op.mt_count = (daddr_t)1;
28334185Sbostic 	if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) {
28434185Sbostic 		perror("tcopy: tape op");
28534185Sbostic 		exit(6);
28634185Sbostic 	}
28734185Sbostic }
28834185Sbostic 
28934185Sbostic static
29034185Sbostic usage()
29134185Sbostic {
29234185Sbostic 	fputs("usage: tcopy [-cv] [-s maxblk] src [dest]\n", stderr);
29334185Sbostic 	exit(1);
29434185Sbostic }
295