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 #include <stdio.h> 41 #include <signal.h> 42 #include <sys/types.h> 43 #include <sys/file.h> 44 #include <sys/fcntl.h> 45 #include <sys/mtio.h> 46 #include <stdlib.h> 47 #include <limits.h> 48 #include <errno.h> 49 50 char *buff; /* buffer for read/write */ 51 int filen = 1; /* file number being processed */ 52 long count, lcount; /* number of blocks for file */ 53 extern void RUBOUT(); 54 int nfile; /* used for ??? */ 55 off64_t size, tsize; /* number of bytes in file, total */ 56 int ln; 57 char *inf, *outf; 58 int copy; 59 size_t size_64K = 64 * 1024; 60 size_t size_256K = 256 * 1024; 61 62 63 int 64 main(int argc, char **argv) 65 { 66 int n, nw, inp, outp; 67 struct mtop op; 68 size_t buf_size = size_64K; 69 70 if (argc <= 1 || argc > 3) { 71 (void) fprintf(stderr, "Usage: tcopy src [dest]\n"); 72 return (1); 73 } 74 inf = argv[1]; 75 if (argc == 3) { 76 outf = argv[2]; 77 copy = 1; 78 } 79 if ((inp = open(inf, O_RDONLY, 0666)) < 0) { 80 (void) fprintf(stderr, "Can't open %s\n", inf); 81 return (1); 82 } 83 if (copy) { 84 if ((outp = open(outf, O_WRONLY, 0666)) < 0) { 85 (void) fprintf(stderr, "Can't open %s\n", outf); 86 return (3); 87 } 88 } 89 if ((buff = malloc(buf_size)) == NULL) { 90 (void) fprintf(stderr, "Can't allocate memory for tcopy\n"); 91 return (4); 92 } 93 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 94 (void) signal(SIGINT, RUBOUT); 95 ln = -2; 96 for (;;) { 97 count++; 98 errno = 0; 99 while ((n = read(inp, buff, buf_size)) < 0 && 100 errno == ENOMEM && buf_size < INT_MAX) { 101 if (buf_size < size_256K) 102 buf_size = size_256K; 103 else 104 buf_size *= 2; 105 free(buff); 106 if ((buff = malloc(buf_size)) == NULL) { 107 (void) fprintf(stderr, 108 "Can't allocate memory for tcopy\n"); 109 return (4); 110 } 111 op.mt_op = MTFSF; /* Rewind to start of file */ 112 op.mt_count = (daddr_t)0; 113 if (ioctl(inp, MTIOCTOP, (char *)&op) < 0) { 114 perror("Read record size"); 115 return (6); 116 } 117 errno = 0; 118 } 119 if (n > 0) { 120 if (copy) { 121 nw = write(outp, buff, (size_t)n); 122 if (nw != n) { 123 (void) fprintf(stderr, "write (%d) !=" 124 " read (%d)\n", nw, n); 125 (void) fprintf(stderr, "COPY " 126 "Aborted\n"); 127 return (5); 128 } 129 } 130 size += n; 131 if (n != ln) { 132 if (ln > 0) 133 if (count - lcount > 1) 134 (void) printf("file %d: records" 135 " %ld to %ld: size %d\n", 136 filen, lcount, count-1, ln); 137 else 138 (void) printf("file %d: record" 139 " %ld: size %d\n", 140 filen, lcount, ln); 141 ln = n; 142 lcount = count; 143 } 144 } else { 145 if (ln <= 0 && ln != -2) { 146 (void) printf("eot\n"); 147 break; 148 } 149 if (ln > 0) 150 if (count - lcount > 1) 151 (void) printf("file %d: records %ld to" 152 " %ld: size " "%d\n", 153 filen, lcount, count-1, ln); 154 else 155 (void) printf("file %d: record %ld:" 156 " size %d\n", filen, lcount, ln); 157 (void) printf("file %d: eof after %ld records:" 158 " %lld bytes\n", filen, count-1, size); 159 if (copy) { 160 op.mt_op = MTWEOF; 161 op.mt_count = (daddr_t)1; 162 if (ioctl(outp, MTIOCTOP, (char *)&op) < 0) { 163 perror("Write EOF"); 164 return (6); 165 } 166 } 167 filen++; 168 count = 0; 169 lcount = 0; 170 tsize += size; 171 size = 0; 172 if (nfile && filen > nfile) 173 break; 174 ln = n; 175 } 176 } 177 if (copy) 178 (void) close(outp); 179 (void) printf("total length: %lld bytes\n", tsize); 180 return (0); 181 } 182 183 void 184 RUBOUT(void) 185 { 186 if (count > lcount) 187 --count; 188 if (count) 189 if (count > lcount) 190 (void) printf("file %d: records %ld to %ld: size" 191 " %d\n", filen, lcount, count, ln); 192 else 193 (void) printf("file %d: record %ld: size %d\n", 194 filen, lcount, ln); 195 (void) printf("interrupted at file %d: record %ld\n", filen, count); 196 (void) printf("total length: %lld bytes\n", tsize+size); 197 exit(1); 198 } 199