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 66 main(argc, argv) 67 char **argv; 68 { 69 register 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 /* NOTREACHED */ 185 } 186 187 void 188 RUBOUT() 189 { 190 if (count > lcount) 191 --count; 192 if (count) 193 if (count > lcount) 194 (void) printf("file %d: records %ld to %ld: size" 195 " %d\n", filen, lcount, count, ln); 196 else 197 (void) printf("file %d: record %ld: size %d\n", 198 filen, lcount, ln); 199 (void) printf("interrupted at file %d: record %ld\n", filen, count); 200 (void) printf("total length: %lld bytes\n", tsize+size); 201 exit(1); 202 } 203