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