1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 #include <stdio.h>
43 #include <signal.h>
44 #include <sys/types.h>
45 #include <sys/file.h>
46 #include <sys/fcntl.h>
47 #include <sys/mtio.h>
48 #include <stdlib.h>
49 #include <limits.h>
50 #include <errno.h>
51
52 char *buff; /* buffer for read/write */
53 int filen = 1; /* file number being processed */
54 long count, lcount; /* number of blocks for file */
55 extern void RUBOUT();
56 int nfile; /* used for ??? */
57 off64_t size, tsize; /* number of bytes in file, total */
58 int ln;
59 char *inf, *outf;
60 int copy;
61 size_t size_64K = 64 * 1024;
62 size_t size_256K = 256 * 1024;
63
64
65 int
main(argc,argv)66 main(argc, argv)
67 char **argv;
68 {
69 int n, nw, inp, outp;
70 struct mtop op;
71 size_t buf_size = size_64K;
72
73 if (argc <= 1 || argc > 3) {
74 (void) fprintf(stderr, "Usage: tcopy src [dest]\n");
75 return (1);
76 }
77 inf = argv[1];
78 if (argc == 3) {
79 outf = argv[2];
80 copy = 1;
81 }
82 if ((inp = open(inf, O_RDONLY, 0666)) < 0) {
83 (void) fprintf(stderr, "Can't open %s\n", inf);
84 return (1);
85 }
86 if (copy) {
87 if ((outp = open(outf, O_WRONLY, 0666)) < 0) {
88 (void) fprintf(stderr, "Can't open %s\n", outf);
89 return (3);
90 }
91 }
92 if ((buff = malloc(buf_size)) == NULL) {
93 (void) fprintf(stderr, "Can't allocate memory for tcopy\n");
94 return (4);
95 }
96 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
97 (void) signal(SIGINT, RUBOUT);
98 ln = -2;
99 for (;;) {
100 count++;
101 errno = 0;
102 while ((n = read(inp, buff, buf_size)) < 0 &&
103 errno == ENOMEM && buf_size < INT_MAX) {
104 if (buf_size < size_256K)
105 buf_size = size_256K;
106 else
107 buf_size *= 2;
108 free(buff);
109 if ((buff = malloc(buf_size)) == NULL) {
110 (void) fprintf(stderr,
111 "Can't allocate memory for tcopy\n");
112 return (4);
113 }
114 op.mt_op = MTFSF; /* Rewind to start of file */
115 op.mt_count = (daddr_t)0;
116 if (ioctl(inp, MTIOCTOP, (char *)&op) < 0) {
117 perror("Read record size");
118 return (6);
119 }
120 errno = 0;
121 }
122 if (n > 0) {
123 if (copy) {
124 nw = write(outp, buff, (size_t)n);
125 if (nw != n) {
126 (void) fprintf(stderr, "write (%d) !="
127 " read (%d)\n", nw, n);
128 (void) fprintf(stderr, "COPY "
129 "Aborted\n");
130 return (5);
131 }
132 }
133 size += n;
134 if (n != ln) {
135 if (ln > 0)
136 if (count - lcount > 1)
137 (void) printf("file %d: records"
138 " %ld to %ld: size %d\n",
139 filen, lcount, count-1, ln);
140 else
141 (void) printf("file %d: record"
142 " %ld: size %d\n",
143 filen, lcount, ln);
144 ln = n;
145 lcount = count;
146 }
147 } else {
148 if (ln <= 0 && ln != -2) {
149 (void) printf("eot\n");
150 break;
151 }
152 if (ln > 0)
153 if (count - lcount > 1)
154 (void) printf("file %d: records %ld to"
155 " %ld: size " "%d\n",
156 filen, lcount, count-1, ln);
157 else
158 (void) printf("file %d: record %ld:"
159 " size %d\n", filen, lcount, ln);
160 (void) printf("file %d: eof after %ld records:"
161 " %lld bytes\n", filen, count-1, size);
162 if (copy) {
163 op.mt_op = MTWEOF;
164 op.mt_count = (daddr_t)1;
165 if (ioctl(outp, MTIOCTOP, (char *)&op) < 0) {
166 perror("Write EOF");
167 return (6);
168 }
169 }
170 filen++;
171 count = 0;
172 lcount = 0;
173 tsize += size;
174 size = 0;
175 if (nfile && filen > nfile)
176 break;
177 ln = n;
178 }
179 }
180 if (copy)
181 (void) close(outp);
182 (void) printf("total length: %lld bytes\n", tsize);
183 return (0);
184 }
185
186 void
RUBOUT()187 RUBOUT()
188 {
189 if (count > lcount)
190 --count;
191 if (count)
192 if (count > lcount)
193 (void) printf("file %d: records %ld to %ld: size"
194 " %d\n", filen, lcount, count, ln);
195 else
196 (void) printf("file %d: record %ld: size %d\n",
197 filen, lcount, ln);
198 (void) printf("interrupted at file %d: record %ld\n", filen, count);
199 (void) printf("total length: %lld bytes\n", tsize+size);
200 exit(1);
201 }
202