xref: /original-bsd/usr.bin/tcopy/tcopy.c (revision cd18b70b)
1 /*
2  * Copyright (c) 1985, 1987 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif not lint
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)tcopy.c	5.5 (Berkeley) 04/09/87";
15 #endif not lint
16 
17 #include <stdio.h>
18 #include <signal.h>
19 #include <sys/file.h>
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
22 #include <sys/mtio.h>
23 #include <sys/errno.h>
24 
25 #define MAXREC	(64 * 1024)
26 #define NOCOUNT	(-2)
27 #undef DEFTAPE
28 #define	DEFTAPE	"/dev/rmt0"
29 
30 char	*buff;
31 char	*inf = DEFTAPE;
32 int	maxblk = MAXREC;
33 int	filen;
34 long	record, lastrec;
35 int	intr();
36 long	itol();
37 char	*malloc();
38 long	size, tsize;
39 int	nfile;
40 int	lastread;
41 int	copy;
42 extern	int errno;
43 
44 main(argc, argv)
45 char **argv;
46 {
47 	register nread, nw, inp, outp;
48 	struct mtop op;
49 	int needeof = 0, guesslen = 1;
50 
51 	while (argc > 1 && *argv[1] == '-') {
52 		switch (*++argv[1]) {
53 		case 's':
54 			if (argc < 3)
55 				goto usage;
56 			maxblk = atoi(argv[2]);
57 			if (maxblk <= 0) {
58 				fprintf(stderr, "illegal block size\n");
59 				goto usage;
60 			}
61 			argc--;
62 			argv++;
63 			guesslen = 0;
64 			break;
65 		}
66 		argc--;
67 		argv++;
68 	}
69 	if (argc < 1 || argc > 3) {
70 usage:
71 		fprintf(stderr, "Usage: tcopy [-s maxblk] src [dest]\n");
72 		exit(1);
73 	}
74 	if (argc > 1)
75 		inf = argv[1];
76 	if ((inp = open(inf, O_RDONLY, 0)) < 0) {
77 		perror(inf);
78 		exit(1);
79 	}
80 	if (argc == 3) {
81 		copy = 1;
82 		if ((outp = open(argv[2], O_WRONLY, 0666)) < 0) {
83 			perror(argv[2]);
84 			exit(3);
85 		}
86 	}
87 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
88 		(void) signal(SIGINT, intr);
89 	buff = malloc(maxblk);
90 	if (buff == NULL) {
91 		fprintf("tcopy: no memory\n");
92 		exit(11);
93 	}
94 	lastread = NOCOUNT;
95 	for (;;) {
96 		nread = read(inp, buff, maxblk);
97 		if (nread == -1) {
98 			if (errno == EINVAL && guesslen &&
99 			    maxblk > MAXREC / 2) {
100 				maxblk -= 1024;
101 				continue;
102 			}
103 			fprintf(stderr, "read error, file %d, record %d: ",
104 			    filen, record);
105 			perror("");
106 		} else if (nread != lastread) {
107 			if (lastread != 0 && lastread != NOCOUNT) {
108 				if (lastrec == 0 && nread == 0)
109 					printf("%d records\n", record);
110 				else if (record - lastrec > 1)
111 					printf("records %ld to %ld\n",
112 					    lastrec, record);
113 				else
114 					printf("record %ld\n", lastrec);
115 			}
116 			if (nread != 0)
117 				printf("file %d: block size %d: ",
118 				    filen, nread);
119 			fflush(stdout);
120 			lastrec = record;
121 		}
122 		guesslen = 0;
123 		if (nread > 0) {
124 			if (copy) {
125 				if (needeof) {
126 				    op.mt_op = MTWEOF;
127 				    op.mt_count = (daddr_t) 1;
128 				    if (ioctl(outp, MTIOCTOP, (char *)&op) < 0) {
129 					    perror("write tape mark");
130 					    exit(6);
131 				    }
132 				    needeof = 0;
133 				}
134 				nw = write(outp, buff, nread);
135 				if (nw != nread) {
136 				    fprintf(stderr,
137 					"write error, file %d, record %d: ",
138 					filen, record);
139 				    if (nw == -1)
140 					perror("");
141 				    else
142 					fprintf(stderr,
143 					    "write (%d) != read (%d)\n",
144 					    nw, nread);
145 				    fprintf(stderr, "copy aborted\n");
146 				    exit(5);
147 				}
148 			}
149 			size += nread;
150 			record++;
151 		} else {
152 			if (lastread <= 0 && lastread != NOCOUNT) {
153 				printf("eot\n");
154 				break;
155 			}
156 			printf("file %d: eof after %ld records: %ld bytes\n",
157 				filen, record, size);
158 			needeof = 1;
159 			filen++;
160 			tsize += size;
161 			record = 0;
162 			lastrec = 0;
163 			lastread = 0;
164 			size = 0;
165 			if (nfile && filen > nfile)
166 				break;
167 		}
168 		lastread = nread;
169 	}
170 	if (copy)
171 		(void) close(outp);
172 	printf("total length: %ld bytes\n", tsize);
173 }
174 
175 intr()
176 {
177 	if (record)
178 		if (record - lastrec > 1)
179 			printf("records %ld to %ld\n", lastrec, record);
180 		else
181 			printf("record %ld\n", lastrec);
182 	printf("interrupt at file %d: record %ld\n", filen, record);
183 	printf("total length: %ld bytes\n", tsize+size);
184 	exit(1);
185 }
186