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 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 * Copyright 2012, Josef 'Jeff' Sipek <jeffpc@31bits.net>. All rights reserved. 27 * Copyright (c) 2014, Joyent, Inc. All rights reserved. 28 */ 29 30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 31 /* All Rights Reserved */ 32 33 /* 34 * convert and copy 35 */ 36 37 #include <stdio.h> 38 #include <signal.h> 39 #include <fcntl.h> 40 #include <sys/param.h> 41 #include <sys/types.h> 42 #include <sys/sysmacros.h> 43 #include <sys/stat.h> 44 #include <unistd.h> 45 #include <stdlib.h> 46 #include <locale.h> 47 #include <string.h> 48 #include <sys/time.h> 49 #include <errno.h> 50 #include <strings.h> 51 52 /* The BIG parameter is machine dependent. It should be a long integer */ 53 /* constant that can be used by the number parser to check the validity */ 54 /* of numeric parameters. On 16-bit machines, it should probably be */ 55 /* the maximum unsigned integer, 0177777L. On 32-bit machines where */ 56 /* longs are the same size as ints, the maximum signed integer is more */ 57 /* appropriate. This value is 017777777777L. In 64 bit environments, */ 58 /* the maximum signed integer value is 0777777777777777777777LL */ 59 60 #define BIG 0777777777777777777777LL 61 62 #define BSIZE 512 63 64 /* Option parameters */ 65 66 #define COPY 0 /* file copy, preserve input block size */ 67 #define REBLOCK 1 /* file copy, change block size */ 68 #define LCREBLOCK 2 /* file copy, convert to lower case */ 69 #define UCREBLOCK 3 /* file copy, convert to upper case */ 70 #define NBASCII 4 /* file copy, convert from EBCDIC to ASCII */ 71 #define LCNBASCII 5 /* file copy, EBCDIC to lower case ASCII */ 72 #define UCNBASCII 6 /* file copy, EBCDIC to upper case ASCII */ 73 #define NBEBCDIC 7 /* file copy, convert from ASCII to EBCDIC */ 74 #define LCNBEBCDIC 8 /* file copy, ASCII to lower case EBCDIC */ 75 #define UCNBEBCDIC 9 /* file copy, ASCII to upper case EBCDIC */ 76 #define NBIBM 10 /* file copy, convert from ASCII to IBM */ 77 #define LCNBIBM 11 /* file copy, ASCII to lower case IBM */ 78 #define UCNBIBM 12 /* file copy, ASCII to upper case IBM */ 79 #define UNBLOCK 13 /* convert blocked ASCII to ASCII */ 80 #define LCUNBLOCK 14 /* convert blocked ASCII to lower case ASCII */ 81 #define UCUNBLOCK 15 /* convert blocked ASCII to upper case ASCII */ 82 #define ASCII 16 /* convert blocked EBCDIC to ASCII */ 83 #define LCASCII 17 /* convert blocked EBCDIC to lower case ASCII */ 84 #define UCASCII 18 /* convert blocked EBCDIC to upper case ASCII */ 85 #define BLOCK 19 /* convert ASCII to blocked ASCII */ 86 #define LCBLOCK 20 /* convert ASCII to lower case blocked ASCII */ 87 #define UCBLOCK 21 /* convert ASCII to upper case blocked ASCII */ 88 #define EBCDIC 22 /* convert ASCII to blocked EBCDIC */ 89 #define LCEBCDIC 23 /* convert ASCII to lower case blocked EBCDIC */ 90 #define UCEBCDIC 24 /* convert ASCII to upper case blocked EBCDIC */ 91 #define IBM 25 /* convert ASCII to blocked IBM */ 92 #define LCIBM 26 /* convert ASCII to lower case blocked IBM */ 93 #define UCIBM 27 /* convert ASCII to upper case blocked IBM */ 94 #define LCASE 01 /* flag - convert to lower case */ 95 #define UCASE 02 /* flag - convert to upper case */ 96 #define SWAB 04 /* flag - swap bytes before conversion */ 97 #define NERR 010 /* flag - proceed on input errors */ 98 #define SYNC 020 /* flag - pad short input blocks with nulls */ 99 #define BADLIMIT 5 /* give up if no progress after BADLIMIT trys */ 100 #define SVR4XLATE 0 /* use default EBCDIC translation */ 101 #define BSDXLATE 1 /* use BSD-compatible EBCDIC translation */ 102 103 #define USAGE\ 104 "usage: dd [if=file] [of=file] [ibs=n|nk|nb|nxm] [obs=n|nk|nb|nxm]\n"\ 105 " [bs=n|nk|nb|nxm] [cbs=n|nk|nb|nxm] [files=n] [skip=n]\n"\ 106 " [iseek=n] [oseek=n] [seek=n] [count=n] [conv=[ascii]\n"\ 107 " [,ebcdic][,ibm][,asciib][,ebcdicb][,ibmb]\n"\ 108 " [,block|unblock][,lcase|ucase][,swab]\n"\ 109 " [,noerror][,notrunc][,sync]]\n"\ 110 " [oflag=[dsync][sync]]\n" 111 112 /* Global references */ 113 114 /* Local routine declarations */ 115 116 static int match(char *); 117 static void term(); 118 static unsigned long long number(); 119 static unsigned char *flsh(); 120 static void stats(); 121 122 /* Local data definitions */ 123 124 static unsigned ibs; /* input buffer size */ 125 static unsigned obs; /* output buffer size */ 126 static unsigned bs; /* buffer size, overrules ibs and obs */ 127 static unsigned cbs; /* conversion buffer size, used for block conversions */ 128 static unsigned ibc; /* number of bytes still in the input buffer */ 129 static unsigned obc; /* number of bytes in the output buffer */ 130 static unsigned cbc; /* number of bytes in the conversion buffer */ 131 132 static int ibf; /* input file descriptor */ 133 static int obf; /* output file descriptor */ 134 static int cflag; /* conversion option flags */ 135 static int oflag; /* output flag options */ 136 static int skipf; /* if skipf == 1, skip rest of input line */ 137 static unsigned long long nifr; /* count of full input records */ 138 static unsigned long long nipr; /* count of partial input records */ 139 static unsigned long long nofr; /* count of full output records */ 140 static unsigned long long nopr; /* count of partial output records */ 141 static unsigned long long ntrunc; /* count of truncated input lines */ 142 static unsigned long long nbad; /* count of bad records since last */ 143 /* good one */ 144 static int files; /* number of input files to concatenate (tape only) */ 145 static off_t skip; /* number of input records to skip */ 146 static off_t iseekn; /* number of input records to seek past */ 147 static off_t oseekn; /* number of output records to seek past */ 148 static unsigned long long count; /* number of input records to copy */ 149 /* (0 = all) */ 150 static boolean_t ecount; /* explicit count given */ 151 static int trantype; /* BSD or SVr4 compatible EBCDIC */ 152 153 static char *string; /* command arg pointer */ 154 static char *ifile; /* input file name pointer */ 155 static char *ofile; /* output file name pointer */ 156 static unsigned char *ibuf; /* input buffer pointer */ 157 static unsigned char *obuf; /* output buffer pointer */ 158 159 static hrtime_t startt; /* hrtime copy started */ 160 static unsigned long long obytes; /* output bytes */ 161 static sig_atomic_t nstats; /* do we need to output stats */ 162 163 /* This is an EBCDIC to ASCII conversion table */ 164 /* from a proposed BTL standard April 16, 1979 */ 165 166 static unsigned char svr4_etoa [] = 167 { 168 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, 169 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, 170 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, 171 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, 172 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, 173 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, 174 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, 175 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, 176 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, 177 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174, 178 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 179 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176, 180 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, 181 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077, 182 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, 183 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, 184 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 185 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, 186 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, 187 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320, 188 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170, 189 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327, 190 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 191 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347, 192 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 193 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, 194 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, 195 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, 196 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, 197 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, 198 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 199 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, 200 }; 201 202 /* This is an ASCII to EBCDIC conversion table */ 203 /* from a proposed BTL standard April 16, 1979 */ 204 205 static unsigned char svr4_atoe [] = 206 { 207 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, 208 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, 209 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, 210 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, 211 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, 212 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, 213 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 214 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, 215 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 216 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, 217 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, 218 0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155, 219 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 220 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, 221 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, 222 0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007, 223 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, 224 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, 225 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, 226 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, 227 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 228 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 229 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, 230 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, 231 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, 232 0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236, 233 0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257, 234 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 235 0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277, 236 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, 237 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, 238 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, 239 }; 240 241 /* Table for ASCII to IBM (alternate EBCDIC) code conversion */ 242 243 static unsigned char svr4_atoibm[] = 244 { 245 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, 246 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, 247 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, 248 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, 249 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, 250 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, 251 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 252 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, 253 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 254 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, 255 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, 256 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, 257 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 258 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, 259 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, 260 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, 261 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, 262 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, 263 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, 264 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, 265 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 266 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 267 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, 268 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, 269 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, 270 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, 271 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, 272 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 273 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 274 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, 275 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, 276 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, 277 }; 278 279 /* Table for conversion of ASCII to lower case ASCII */ 280 281 static unsigned char utol[] = 282 { 283 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 284 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, 285 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, 286 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, 287 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, 288 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, 289 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 290 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, 291 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 292 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 293 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 294 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, 295 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 296 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 297 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 298 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, 299 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 300 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 301 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 302 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 303 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 304 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 305 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 306 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 307 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 308 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 309 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 310 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 311 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 312 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 313 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 314 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, 315 }; 316 317 /* Table for conversion of ASCII to upper case ASCII */ 318 319 static unsigned char ltou[] = 320 { 321 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 322 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, 323 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, 324 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, 325 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, 326 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, 327 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 328 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, 329 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 330 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, 331 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 332 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, 333 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 334 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, 335 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 336 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, 337 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 338 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 339 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 340 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 341 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 342 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 343 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 344 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 345 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 346 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 347 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 348 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 349 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 350 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 351 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 352 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, 353 }; 354 355 /* BSD-compatible EBCDIC to ASCII translate table */ 356 357 static unsigned char bsd_etoa[] = 358 { 359 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, 360 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, 361 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, 362 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, 363 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, 364 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, 365 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, 366 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, 367 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, 368 0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041, 369 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 370 0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136, 371 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, 372 0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077, 373 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, 374 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, 375 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 376 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, 377 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, 378 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, 379 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170, 380 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, 381 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 382 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 383 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 384 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, 385 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, 386 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, 387 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, 388 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, 389 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 390 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, 391 }; 392 393 /* BSD-compatible ASCII to EBCDIC translate table */ 394 395 static unsigned char bsd_atoe[] = 396 { 397 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, 398 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, 399 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, 400 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, 401 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, 402 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, 403 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 404 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, 405 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 406 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, 407 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, 408 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155, 409 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 410 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, 411 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, 412 0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007, 413 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, 414 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, 415 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, 416 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, 417 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 418 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 419 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, 420 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, 421 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, 422 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, 423 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, 424 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 425 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 426 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, 427 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, 428 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, 429 }; 430 431 /* BSD-compatible ASCII to IBM translate table */ 432 433 static unsigned char bsd_atoibm[] = 434 { 435 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, 436 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, 437 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, 438 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, 439 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, 440 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, 441 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 442 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, 443 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 444 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, 445 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, 446 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, 447 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 448 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, 449 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, 450 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, 451 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, 452 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, 453 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, 454 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, 455 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 456 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 457 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, 458 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, 459 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, 460 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, 461 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, 462 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 463 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 464 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, 465 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, 466 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, 467 }; 468 469 /* set up to use SVr4 ascii-ebcdic translation by default */ 470 471 static unsigned char *atoe = svr4_atoe; 472 static unsigned char *etoa = svr4_etoa; 473 static unsigned char *atoibm = svr4_atoibm; 474 475 /*ARGSUSED*/ 476 static void 477 siginfo_handler(int sig, siginfo_t *sip, void *ucp) 478 { 479 nstats = 1; 480 } 481 482 int 483 main(int argc, char **argv) 484 { 485 unsigned char *ip, *op; /* input and output buffer pointers */ 486 int c; /* character counter */ 487 int ic; /* input character */ 488 int conv; /* conversion option code */ 489 int trunc; /* whether output file is truncated */ 490 struct stat file_stat; 491 struct sigaction sact; 492 493 /* Set option defaults */ 494 495 ibs = BSIZE; 496 obs = BSIZE; 497 files = 1; 498 conv = COPY; 499 trunc = 1; /* default: truncate output file */ 500 trantype = SVR4XLATE; /* use SVR4 EBCDIC by default */ 501 502 /* Parse command options */ 503 504 (void) setlocale(LC_ALL, ""); 505 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 506 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 507 #endif 508 (void) textdomain(TEXT_DOMAIN); 509 510 while ((c = getopt(argc, argv, "")) != EOF) 511 switch (c) { 512 case '?': 513 (void) fprintf(stderr, USAGE); 514 exit(2); 515 } 516 517 /* not getopt()'ed because dd has no options but only operand(s) */ 518 519 for (c = optind; c < argc; c++) 520 { 521 string = argv[c]; 522 if (match("ibs=")) 523 { 524 ibs = (unsigned)number(BIG); 525 continue; 526 } 527 if (match("obs=")) 528 { 529 obs = (unsigned)number(BIG); 530 continue; 531 } 532 if (match("cbs=")) 533 { 534 cbs = (unsigned)number(BIG); 535 continue; 536 } 537 if (match("bs=")) 538 { 539 bs = (unsigned)number(BIG); 540 continue; 541 } 542 if (match("if=")) 543 { 544 ifile = string; 545 continue; 546 } 547 if (match("of=")) 548 { 549 ofile = string; 550 continue; 551 } 552 if (match("skip=")) 553 { 554 skip = number(BIG); 555 continue; 556 } 557 if (match("iseek=")) 558 { 559 iseekn = number(BIG); 560 continue; 561 } 562 if (match("oseek=")) 563 { 564 oseekn = number(BIG); 565 continue; 566 } 567 if (match("seek=")) /* retained for compatibility */ 568 { 569 oseekn = number(BIG); 570 continue; 571 } 572 if (match("count=")) 573 { 574 count = number(BIG); 575 ecount = B_TRUE; 576 continue; 577 } 578 if (match("files=")) 579 { 580 files = (int)number(BIG); 581 continue; 582 } 583 if (match("conv=")) 584 { 585 for (;;) 586 { 587 if (match(",")) 588 { 589 continue; 590 } 591 if (*string == '\0') 592 { 593 break; 594 } 595 if (match("block")) 596 { 597 conv = BLOCK; 598 continue; 599 } 600 if (match("unblock")) 601 { 602 conv = UNBLOCK; 603 continue; 604 } 605 606 /* ebcdicb, ibmb, and asciib must precede */ 607 /* ebcdic, ibm, and ascii in this test */ 608 609 if (match("ebcdicb")) 610 { 611 conv = EBCDIC; 612 trantype = BSDXLATE; 613 continue; 614 } 615 if (match("ibmb")) 616 { 617 conv = IBM; 618 trantype = BSDXLATE; 619 continue; 620 } 621 if (match("asciib")) 622 { 623 conv = ASCII; 624 trantype = BSDXLATE; 625 continue; 626 } 627 if (match("ebcdic")) 628 { 629 conv = EBCDIC; 630 trantype = SVR4XLATE; 631 continue; 632 } 633 if (match("ibm")) 634 { 635 conv = IBM; 636 trantype = SVR4XLATE; 637 continue; 638 } 639 if (match("ascii")) 640 { 641 conv = ASCII; 642 trantype = SVR4XLATE; 643 continue; 644 } 645 if (match("lcase")) 646 { 647 cflag |= LCASE; 648 continue; 649 } 650 if (match("ucase")) 651 { 652 cflag |= UCASE; 653 continue; 654 } 655 if (match("swab")) 656 { 657 cflag |= SWAB; 658 continue; 659 } 660 if (match("noerror")) 661 { 662 cflag |= NERR; 663 continue; 664 } 665 if (match("notrunc")) 666 { 667 trunc = 0; 668 continue; 669 } 670 if (match("sync")) 671 { 672 cflag |= SYNC; 673 continue; 674 } 675 goto badarg; 676 } 677 continue; 678 } 679 if (match("oflag=")) 680 { 681 for (;;) 682 { 683 if (match(",")) 684 { 685 continue; 686 } 687 if (*string == '\0') 688 { 689 break; 690 } 691 if (match("dsync")) 692 { 693 oflag |= O_DSYNC; 694 continue; 695 } 696 if (match("sync")) 697 { 698 oflag |= O_SYNC; 699 continue; 700 } 701 goto badarg; 702 } 703 continue; 704 } 705 badarg: 706 (void) fprintf(stderr, "dd: %s \"%s\"\n", 707 gettext("bad argument:"), string); 708 exit(2); 709 } 710 711 /* Perform consistency checks on options, decode strange conventions */ 712 713 if (bs) 714 { 715 ibs = obs = bs; 716 } 717 if ((ibs == 0) || (obs == 0)) 718 { 719 (void) fprintf(stderr, "dd: %s\n", 720 gettext("buffer sizes cannot be zero")); 721 exit(2); 722 } 723 if (conv == COPY) 724 { 725 if ((bs == 0) || (cflag&(LCASE|UCASE))) 726 { 727 conv = REBLOCK; 728 } 729 } 730 if (cbs == 0) 731 { 732 switch (conv) 733 { 734 case BLOCK: 735 case UNBLOCK: 736 conv = REBLOCK; 737 break; 738 739 case ASCII: 740 conv = NBASCII; 741 break; 742 743 case EBCDIC: 744 conv = NBEBCDIC; 745 break; 746 747 case IBM: 748 conv = NBIBM; 749 break; 750 } 751 } 752 753 /* Expand options into lower and upper case versions if necessary */ 754 755 switch (conv) 756 { 757 case REBLOCK: 758 if (cflag&LCASE) 759 conv = LCREBLOCK; 760 else if (cflag&UCASE) 761 conv = UCREBLOCK; 762 break; 763 764 case UNBLOCK: 765 if (cflag&LCASE) 766 conv = LCUNBLOCK; 767 else if (cflag&UCASE) 768 conv = UCUNBLOCK; 769 break; 770 771 case BLOCK: 772 if (cflag&LCASE) 773 conv = LCBLOCK; 774 else if (cflag&UCASE) 775 conv = UCBLOCK; 776 break; 777 778 case ASCII: 779 if (cflag&LCASE) 780 conv = LCASCII; 781 else if (cflag&UCASE) 782 conv = UCASCII; 783 break; 784 785 case NBASCII: 786 if (cflag&LCASE) 787 conv = LCNBASCII; 788 else if (cflag&UCASE) 789 conv = UCNBASCII; 790 break; 791 792 case EBCDIC: 793 if (cflag&LCASE) 794 conv = LCEBCDIC; 795 else if (cflag&UCASE) 796 conv = UCEBCDIC; 797 break; 798 799 case NBEBCDIC: 800 if (cflag&LCASE) 801 conv = LCNBEBCDIC; 802 else if (cflag&UCASE) 803 conv = UCNBEBCDIC; 804 break; 805 806 case IBM: 807 if (cflag&LCASE) 808 conv = LCIBM; 809 else if (cflag&UCASE) 810 conv = UCIBM; 811 break; 812 813 case NBIBM: 814 if (cflag&LCASE) 815 conv = LCNBIBM; 816 else if (cflag&UCASE) 817 conv = UCNBIBM; 818 break; 819 } 820 821 /* If BSD-compatible translation is selected, change the tables */ 822 823 if (trantype == BSDXLATE) { 824 atoe = bsd_atoe; 825 atoibm = bsd_atoibm; 826 etoa = bsd_etoa; 827 } 828 /* Open the input file, or duplicate standard input */ 829 830 ibf = -1; 831 if (ifile) 832 { 833 ibf = open(ifile, 0); 834 } 835 else 836 { 837 ifile = ""; 838 ibf = dup(0); 839 } 840 841 if (ibf == -1) 842 { 843 (void) fprintf(stderr, "dd: %s: ", ifile); 844 perror("open"); 845 exit(2); 846 } 847 848 /* Open the output file, or duplicate standard output */ 849 850 obf = -1; 851 if (ofile) 852 { 853 if (trunc == 0) /* do not truncate output file */ 854 obf = open(ofile, (O_WRONLY|O_CREAT|oflag), 855 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)); 856 else if (oseekn && (trunc == 1)) 857 { 858 obf = open(ofile, O_WRONLY|O_CREAT|oflag, 859 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)); 860 if (obf == -1) 861 { 862 (void) fprintf(stderr, "dd: %s: ", ofile); 863 perror("open"); 864 exit(2); 865 } 866 (void) fstat(obf, &file_stat); 867 if (((file_stat.st_mode & S_IFMT) == S_IFREG) && 868 (ftruncate(obf, (((off_t)oseekn) * ((off_t)obs))) 869 == -1)) 870 { 871 perror("ftruncate"); 872 exit(2); 873 } 874 } 875 else 876 obf = open(ofile, O_WRONLY|O_CREAT|O_TRUNC|oflag, 877 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)); 878 } 879 else 880 { 881 ofile = ""; 882 obf = dup(1); 883 } 884 885 if (obf == -1) 886 { 887 (void) fprintf(stderr, "dd: %s: ", ofile); 888 perror("open"); 889 exit(2); 890 } 891 892 /* Expand memory to get an input buffer */ 893 894 ibuf = (unsigned char *)valloc(ibs + 10); 895 896 /* If no conversions, the input buffer is the output buffer */ 897 898 if (conv == COPY) 899 { 900 obuf = ibuf; 901 } 902 903 /* Expand memory to get an output buffer. Leave enough room at the */ 904 /* end to convert a logical record when doing block conversions. */ 905 906 else 907 { 908 obuf = (unsigned char *)valloc(obs + cbs + 10); 909 } 910 if ((ibuf == (unsigned char *)NULL) || (obuf == (unsigned char *)NULL)) 911 { 912 (void) fprintf(stderr, 913 "dd: %s\n", gettext("not enough memory")); 914 exit(2); 915 } 916 917 /* 918 * Enable a statistics message when we terminate on SIGINT 919 * Also enable it to be queried via SIGINFO and SIGUSR1 920 */ 921 922 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 923 { 924 (void) signal(SIGINT, term); 925 } 926 927 bzero(&sact, sizeof (struct sigaction)); 928 sact.sa_flags = SA_SIGINFO; 929 sact.sa_sigaction = siginfo_handler; 930 (void) sigemptyset(&sact.sa_mask); 931 if (sigaction(SIGINFO, &sact, NULL) != 0) { 932 (void) fprintf(stderr, "dd: %s: %s\n", 933 gettext("failed to enable siginfo handler"), 934 gettext(strerror(errno))); 935 exit(2); 936 } 937 if (sigaction(SIGUSR1, &sact, NULL) != 0) { 938 (void) fprintf(stderr, "dd: %s: %s\n", 939 gettext("failed to enable sigusr1 handler"), 940 gettext(strerror(errno))); 941 exit(2); 942 } 943 944 /* Skip input blocks */ 945 946 while (skip) 947 { 948 ibc = read(ibf, (char *)ibuf, ibs); 949 if (ibc == (unsigned)-1) 950 { 951 if (++nbad > BADLIMIT) 952 { 953 (void) fprintf(stderr, "dd: %s\n", 954 gettext("skip failed")); 955 exit(2); 956 } 957 else 958 { 959 perror("read"); 960 } 961 } 962 else 963 { 964 if (ibc == 0) 965 { 966 (void) fprintf(stderr, "dd: %s\n", 967 gettext("cannot skip past end-of-file")); 968 exit(3); 969 } 970 else 971 { 972 nbad = 0; 973 } 974 } 975 skip--; 976 } 977 978 /* Seek past input blocks */ 979 980 if (iseekn && lseek(ibf, (((off_t)iseekn) * ((off_t)ibs)), 1) == -1) 981 { 982 perror("lseek"); 983 exit(2); 984 } 985 986 /* Seek past output blocks */ 987 988 if (oseekn && lseek(obf, (((off_t)oseekn) * ((off_t)obs)), 1) == -1) 989 { 990 perror("lseek"); 991 exit(2); 992 } 993 994 /* Initialize all buffer pointers */ 995 996 skipf = 0; /* not skipping an input line */ 997 ibc = 0; /* no input characters yet */ 998 obc = 0; /* no output characters yet */ 999 cbc = 0; /* the conversion buffer is empty */ 1000 op = obuf; /* point to the output buffer */ 1001 1002 /* Read and convert input blocks until end of file(s) */ 1003 1004 /* Grab our start time for siginfo purposes */ 1005 startt = gethrtime(); 1006 1007 for (;;) 1008 { 1009 if (nstats != 0) { 1010 stats(); 1011 nstats = 0; 1012 } 1013 1014 if ((count == 0 && ecount == B_FALSE) || (nifr+nipr < count)) { 1015 /* If proceed on error is enabled, zero the input buffer */ 1016 1017 if (cflag&NERR) 1018 { 1019 ip = ibuf + ibs; 1020 c = ibs; 1021 if (c & 1) /* if the size is odd, */ 1022 { 1023 *--ip = 0; /* clear the odd byte */ 1024 } 1025 if (c >>= 1) /* divide by two */ 1026 { 1027 do { /* clear two at a time */ 1028 *--ip = 0; 1029 *--ip = 0; 1030 } while (--c); 1031 } 1032 } 1033 1034 /* Read the next input block */ 1035 1036 ibc = read(ibf, (char *)ibuf, ibs); 1037 1038 /* Process input errors */ 1039 1040 if (ibc == (unsigned)-1) 1041 { 1042 perror("read"); 1043 if (((cflag&NERR) == 0) || (++nbad > BADLIMIT)) 1044 { 1045 while (obc) 1046 { 1047 (void) flsh(); 1048 } 1049 term(2); 1050 } 1051 else 1052 { 1053 stats(); 1054 ibc = ibs; /* assume a full block */ 1055 } 1056 } 1057 else 1058 { 1059 nbad = 0; 1060 } 1061 } 1062 1063 /* Record count satisfied, simulate end of file */ 1064 1065 else 1066 { 1067 ibc = 0; 1068 files = 1; 1069 } 1070 1071 /* Process end of file */ 1072 1073 if (ibc == 0) 1074 { 1075 switch (conv) 1076 { 1077 case UNBLOCK: 1078 case LCUNBLOCK: 1079 case UCUNBLOCK: 1080 case ASCII: 1081 case LCASCII: 1082 case UCASCII: 1083 1084 /* Trim trailing blanks from the last line */ 1085 1086 if ((c = cbc) != 0) 1087 { 1088 do { 1089 if ((*--op) != ' ') 1090 { 1091 op++; 1092 break; 1093 } 1094 } while (--c); 1095 *op++ = '\n'; 1096 obc -= cbc - c - 1; 1097 cbc = 0; 1098 1099 /* Flush the output buffer if full */ 1100 1101 while (obc >= obs) 1102 { 1103 op = flsh(); 1104 } 1105 } 1106 break; 1107 1108 case BLOCK: 1109 case LCBLOCK: 1110 case UCBLOCK: 1111 case EBCDIC: 1112 case LCEBCDIC: 1113 case UCEBCDIC: 1114 case IBM: 1115 case LCIBM: 1116 case UCIBM: 1117 1118 /* Pad trailing blanks if the last line is short */ 1119 1120 if (cbc) 1121 { 1122 obc += c = cbs - cbc; 1123 cbc = 0; 1124 if (c > 0) 1125 { 1126 /* Use the right kind of blank */ 1127 1128 switch (conv) 1129 { 1130 case BLOCK: 1131 case LCBLOCK: 1132 case UCBLOCK: 1133 ic = ' '; 1134 break; 1135 1136 case EBCDIC: 1137 case LCEBCDIC: 1138 case UCEBCDIC: 1139 ic = atoe[' ']; 1140 break; 1141 1142 case IBM: 1143 case LCIBM: 1144 case UCIBM: 1145 ic = atoibm[' ']; 1146 break; 1147 } 1148 1149 /* Pad with trailing blanks */ 1150 1151 do { 1152 *op++ = ic; 1153 } while (--c); 1154 } 1155 } 1156 1157 1158 /* Flush the output buffer if full */ 1159 1160 while (obc >= obs) 1161 { 1162 op = flsh(); 1163 } 1164 break; 1165 } 1166 1167 /* If no more files to read, flush the output buffer */ 1168 1169 if (--files <= 0) 1170 { 1171 (void) flsh(); 1172 if ((close(obf) != 0) || (fclose(stdout) != 0)) 1173 { 1174 perror(gettext("dd: close error")); 1175 exit(2); 1176 } 1177 term(0); /* successful exit */ 1178 } 1179 else 1180 { 1181 continue; /* read the next file */ 1182 } 1183 } 1184 1185 /* Normal read, check for special cases */ 1186 1187 else if (ibc == ibs) 1188 { 1189 nifr++; /* count another full input record */ 1190 } 1191 else 1192 { 1193 nipr++; /* count a partial input record */ 1194 1195 /* If `sync' enabled, pad nulls */ 1196 1197 if ((cflag&SYNC) && ((cflag&NERR) == 0)) 1198 { 1199 c = ibs - ibc; 1200 ip = ibuf + ibs; 1201 do { 1202 if ((conv == BLOCK) || (conv == UNBLOCK)) 1203 *--ip = ' '; 1204 else 1205 *--ip = '\0'; 1206 } while (--c); 1207 ibc = ibs; 1208 } 1209 } 1210 1211 /* Swap the bytes in the input buffer if necessary */ 1212 1213 if (cflag&SWAB) 1214 { 1215 ip = ibuf; 1216 if (ibc & 1) /* if the byte count is odd, */ 1217 { 1218 ip[ibc] = 0; /* make it even, pad with zero */ 1219 } 1220 c = ibc >> 1; /* compute the pair count */ 1221 do { 1222 ic = *ip++; 1223 ip[-1] = *ip; 1224 *ip++ = ic; 1225 } while (--c); /* do two bytes at a time */ 1226 } 1227 1228 /* Select the appropriate conversion loop */ 1229 1230 ip = ibuf; 1231 switch (conv) 1232 { 1233 1234 /* Simple copy: no conversion, preserve the input block size */ 1235 1236 case COPY: 1237 obc = ibc; 1238 (void) flsh(); 1239 break; 1240 1241 /* Simple copy: pack all output into equal sized blocks */ 1242 1243 case REBLOCK: 1244 case LCREBLOCK: 1245 case UCREBLOCK: 1246 case NBASCII: 1247 case LCNBASCII: 1248 case UCNBASCII: 1249 case NBEBCDIC: 1250 case LCNBEBCDIC: 1251 case UCNBEBCDIC: 1252 case NBIBM: 1253 case LCNBIBM: 1254 case UCNBIBM: 1255 while ((c = ibc) != 0) 1256 { 1257 if (c > (obs - obc)) 1258 { 1259 c = obs - obc; 1260 } 1261 ibc -= c; 1262 obc += c; 1263 switch (conv) 1264 { 1265 case REBLOCK: 1266 do { 1267 *op++ = *ip++; 1268 } while (--c); 1269 break; 1270 1271 case LCREBLOCK: 1272 do { 1273 *op++ = utol[*ip++]; 1274 } while (--c); 1275 break; 1276 1277 case UCREBLOCK: 1278 do { 1279 *op++ = ltou[*ip++]; 1280 } while (--c); 1281 break; 1282 1283 case NBASCII: 1284 do { 1285 *op++ = etoa[*ip++]; 1286 } while (--c); 1287 break; 1288 1289 case LCNBASCII: 1290 do { 1291 *op++ = utol[etoa[*ip++]]; 1292 } while (--c); 1293 break; 1294 1295 case UCNBASCII: 1296 do { 1297 *op++ = ltou[etoa[*ip++]]; 1298 } while (--c); 1299 break; 1300 1301 case NBEBCDIC: 1302 do { 1303 *op++ = atoe[*ip++]; 1304 } while (--c); 1305 break; 1306 1307 case LCNBEBCDIC: 1308 do { 1309 *op++ = atoe[utol[*ip++]]; 1310 } while (--c); 1311 break; 1312 1313 case UCNBEBCDIC: 1314 do { 1315 *op++ = atoe[ltou[*ip++]]; 1316 } while (--c); 1317 break; 1318 1319 case NBIBM: 1320 do { 1321 *op++ = atoibm[*ip++]; 1322 } while (--c); 1323 break; 1324 1325 case LCNBIBM: 1326 do { 1327 *op++ = atoibm[utol[*ip++]]; 1328 } while (--c); 1329 break; 1330 1331 case UCNBIBM: 1332 do { 1333 *op++ = atoibm[ltou[*ip++]]; 1334 } while (--c); 1335 break; 1336 } 1337 if (obc >= obs) 1338 { 1339 op = flsh(); 1340 } 1341 } 1342 break; 1343 1344 /* Convert from blocked records to lines terminated by newline */ 1345 1346 case UNBLOCK: 1347 case LCUNBLOCK: 1348 case UCUNBLOCK: 1349 case ASCII: 1350 case LCASCII: 1351 case UCASCII: 1352 while ((c = ibc) != 0) 1353 { 1354 if (c > (cbs - cbc)) 1355 /* if more than one record, */ 1356 { 1357 c = cbs - cbc; 1358 /* only copy one record */ 1359 } 1360 ibc -= c; 1361 cbc += c; 1362 obc += c; 1363 switch (conv) 1364 { 1365 case UNBLOCK: 1366 do { 1367 *op++ = *ip++; 1368 } while (--c); 1369 break; 1370 1371 case LCUNBLOCK: 1372 do { 1373 *op++ = utol[*ip++]; 1374 } while (--c); 1375 break; 1376 1377 case UCUNBLOCK: 1378 do { 1379 *op++ = ltou[*ip++]; 1380 } while (--c); 1381 break; 1382 1383 case ASCII: 1384 do { 1385 *op++ = etoa[*ip++]; 1386 } while (--c); 1387 break; 1388 1389 case LCASCII: 1390 do { 1391 *op++ = utol[etoa[*ip++]]; 1392 } while (--c); 1393 break; 1394 1395 case UCASCII: 1396 do { 1397 *op++ = ltou[etoa[*ip++]]; 1398 } while (--c); 1399 break; 1400 } 1401 1402 /* Trim trailing blanks if the line is full */ 1403 1404 if (cbc == cbs) 1405 { 1406 c = cbs; /* `do - while' is usually */ 1407 do { /* faster than `for' */ 1408 if ((*--op) != ' ') 1409 { 1410 op++; 1411 break; 1412 } 1413 } while (--c); 1414 *op++ = '\n'; 1415 obc -= cbs - c - 1; 1416 cbc = 0; 1417 1418 /* Flush the output buffer if full */ 1419 1420 while (obc >= obs) 1421 { 1422 op = flsh(); 1423 } 1424 } 1425 } 1426 break; 1427 1428 /* Convert to blocked records */ 1429 1430 case BLOCK: 1431 case LCBLOCK: 1432 case UCBLOCK: 1433 case EBCDIC: 1434 case LCEBCDIC: 1435 case UCEBCDIC: 1436 case IBM: 1437 case LCIBM: 1438 case UCIBM: 1439 while ((c = ibc) != 0) 1440 { 1441 int nlflag = 0; 1442 1443 /* We may have to skip to the end of a long line */ 1444 1445 if (skipf) 1446 { 1447 do { 1448 if ((ic = *ip++) == '\n') 1449 { 1450 skipf = 0; 1451 c--; 1452 break; 1453 } 1454 } while (--c); 1455 if ((ibc = c) == 0) 1456 { 1457 continue; 1458 /* read another block */ 1459 } 1460 } 1461 1462 /* If anything left, copy until newline */ 1463 1464 if (c > (cbs - cbc + 1)) 1465 { 1466 c = cbs - cbc + 1; 1467 } 1468 ibc -= c; 1469 cbc += c; 1470 obc += c; 1471 1472 switch (conv) 1473 { 1474 case BLOCK: 1475 do { 1476 if ((ic = *ip++) != '\n') 1477 { 1478 *op++ = ic; 1479 } 1480 else 1481 { 1482 nlflag = 1; 1483 break; 1484 } 1485 } while (--c); 1486 break; 1487 1488 case LCBLOCK: 1489 do { 1490 if ((ic = *ip++) != '\n') 1491 { 1492 *op++ = utol[ic]; 1493 } 1494 else 1495 { 1496 nlflag = 1; 1497 break; 1498 } 1499 } while (--c); 1500 break; 1501 1502 case UCBLOCK: 1503 do { 1504 if ((ic = *ip++) != '\n') 1505 { 1506 *op++ = ltou[ic]; 1507 } 1508 else 1509 { 1510 nlflag = 1; 1511 break; 1512 } 1513 } while (--c); 1514 break; 1515 1516 case EBCDIC: 1517 do { 1518 if ((ic = *ip++) != '\n') 1519 { 1520 *op++ = atoe[ic]; 1521 } 1522 else 1523 { 1524 nlflag = 1; 1525 break; 1526 } 1527 } while (--c); 1528 break; 1529 1530 case LCEBCDIC: 1531 do { 1532 if ((ic = *ip++) != '\n') 1533 { 1534 *op++ = atoe[utol[ic]]; 1535 } 1536 else 1537 { 1538 nlflag = 1; 1539 break; 1540 } 1541 } while (--c); 1542 break; 1543 1544 case UCEBCDIC: 1545 do { 1546 if ((ic = *ip++) != '\n') 1547 { 1548 *op++ = atoe[ltou[ic]]; 1549 } 1550 else 1551 { 1552 nlflag = 1; 1553 break; 1554 } 1555 } while (--c); 1556 break; 1557 1558 case IBM: 1559 do { 1560 if ((ic = *ip++) != '\n') 1561 { 1562 *op++ = atoibm[ic]; 1563 } 1564 else 1565 { 1566 nlflag = 1; 1567 break; 1568 } 1569 } while (--c); 1570 break; 1571 1572 case LCIBM: 1573 do { 1574 if ((ic = *ip++) != '\n') 1575 { 1576 *op++ = atoibm[utol[ic]]; 1577 } 1578 else 1579 { 1580 nlflag = 1; 1581 break; 1582 } 1583 } while (--c); 1584 break; 1585 1586 case UCIBM: 1587 do { 1588 if ((ic = *ip++) != '\n') 1589 { 1590 *op++ = atoibm[ltou[ic]]; 1591 } 1592 else 1593 { 1594 nlflag = 1; 1595 break; 1596 } 1597 } while (--c); 1598 break; 1599 } 1600 1601 /* If newline found, update all the counters and */ 1602 /* pointers, pad with trailing blanks if necessary */ 1603 1604 if (nlflag) 1605 { 1606 ibc += c - 1; 1607 obc += cbs - cbc; 1608 c += cbs - cbc; 1609 cbc = 0; 1610 if (c > 0) 1611 { 1612 /* Use the right kind of blank */ 1613 1614 switch (conv) 1615 { 1616 case BLOCK: 1617 case LCBLOCK: 1618 case UCBLOCK: 1619 ic = ' '; 1620 break; 1621 1622 case EBCDIC: 1623 case LCEBCDIC: 1624 case UCEBCDIC: 1625 ic = atoe[' ']; 1626 break; 1627 1628 case IBM: 1629 case LCIBM: 1630 case UCIBM: 1631 ic = atoibm[' ']; 1632 break; 1633 } 1634 1635 /* Pad with trailing blanks */ 1636 1637 do { 1638 *op++ = ic; 1639 } while (--c); 1640 } 1641 } 1642 1643 /* If not end of line, this line may be too long */ 1644 1645 else if (cbc > cbs) 1646 { 1647 skipf = 1; /* note skip in progress */ 1648 obc--; 1649 op--; 1650 cbc = 0; 1651 ntrunc++; /* count another long line */ 1652 } 1653 1654 /* Flush the output buffer if full */ 1655 1656 while (obc >= obs) 1657 { 1658 op = flsh(); 1659 } 1660 } 1661 break; 1662 } 1663 } 1664 /* NOTREACHED */ 1665 return (0); 1666 } 1667 1668 /* match ************************************************************** */ 1669 /* */ 1670 /* Compare two text strings for equality */ 1671 /* */ 1672 /* Arg: s - pointer to string to match with a command arg */ 1673 /* Global arg: string - pointer to command arg */ 1674 /* */ 1675 /* Return: 1 if match, 0 if no match */ 1676 /* If match, also reset `string' to point to the text */ 1677 /* that follows the matching text. */ 1678 /* */ 1679 /* ******************************************************************** */ 1680 1681 static int 1682 match(s) 1683 char *s; 1684 { 1685 char *cs; 1686 1687 cs = string; 1688 while (*cs++ == *s) 1689 { 1690 if (*s++ == '\0') 1691 { 1692 goto true; 1693 } 1694 } 1695 if (*s != '\0') 1696 { 1697 return (0); 1698 } 1699 1700 true: 1701 cs--; 1702 string = cs; 1703 return (1); 1704 } 1705 1706 /* number ************************************************************* */ 1707 /* */ 1708 /* Convert a numeric arg to binary */ 1709 /* */ 1710 /* Arg: big - maximum valid input number */ 1711 /* Global arg: string - pointer to command arg */ 1712 /* */ 1713 /* Valid forms: 123 | 123k | 123M | 123G | 123T | 123P | 123E | 123Z | */ 1714 /* 123w | 123b | 123*123 | 123x123 */ 1715 /* plus combinations such as 2b*3kw*4w */ 1716 /* */ 1717 /* Return: converted number */ 1718 /* */ 1719 /* ******************************************************************** */ 1720 1721 static unsigned long long 1722 number(big) 1723 long long big; 1724 { 1725 char *cs; 1726 long long n; 1727 long long cut = BIG / 10; /* limit to avoid overflow */ 1728 1729 cs = string; 1730 n = 0; 1731 while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) 1732 { 1733 n = n*10 + *cs++ - '0'; 1734 } 1735 for (;;) 1736 { 1737 switch (*cs++) 1738 { 1739 1740 case 'Z': 1741 n *= 1024; 1742 /* FALLTHROUGH */ 1743 1744 case 'E': 1745 n *= 1024; 1746 /* FALLTHROUGH */ 1747 1748 case 'P': 1749 n *= 1024; 1750 /* FALLTHROUGH */ 1751 1752 case 'T': 1753 n *= 1024; 1754 /* FALLTHROUGH */ 1755 1756 case 'G': 1757 n *= 1024; 1758 /* FALLTHROUGH */ 1759 1760 case 'M': 1761 n *= 1024; 1762 /* FALLTHROUGH */ 1763 1764 case 'k': 1765 n *= 1024; 1766 continue; 1767 1768 case 'w': 1769 n *= 2; 1770 continue; 1771 1772 case 'b': 1773 n *= BSIZE; 1774 continue; 1775 1776 case '*': 1777 case 'x': 1778 string = cs; 1779 n *= number(BIG); 1780 1781 /* FALLTHROUGH */ 1782 /* Fall into exit test, recursion has read rest of string */ 1783 /* End of string, check for a valid number */ 1784 1785 case '\0': 1786 if ((n > big) || (n < 0)) 1787 { 1788 (void) fprintf(stderr, "dd: %s \"%llu\"\n", 1789 gettext("argument out of range:"), n); 1790 exit(2); 1791 } 1792 return (n); 1793 1794 default: 1795 (void) fprintf(stderr, "dd: %s \"%s\"\n", 1796 gettext("bad numeric argument:"), string); 1797 exit(2); 1798 } 1799 } /* never gets here */ 1800 } 1801 1802 /* flsh *************************************************************** */ 1803 /* */ 1804 /* Flush the output buffer, move any excess bytes down to the beginning */ 1805 /* */ 1806 /* Arg: none */ 1807 /* Global args: obuf, obc, obs, nofr, nopr */ 1808 /* */ 1809 /* Return: Pointer to the first free byte in the output buffer. */ 1810 /* Also reset `obc' to account for moved bytes. */ 1811 /* */ 1812 /* ******************************************************************** */ 1813 1814 static unsigned char 1815 *flsh() 1816 { 1817 unsigned char *op, *cp; 1818 int bc; 1819 unsigned int oc; 1820 1821 if (obc) /* don't flush if the buffer is empty */ 1822 { 1823 if (obc >= obs) { 1824 oc = obs; 1825 nofr++; /* count a full output buffer */ 1826 } 1827 else 1828 { 1829 oc = obc; 1830 nopr++; /* count a partial output buffer */ 1831 } 1832 bc = write(obf, (char *)obuf, oc); 1833 if (bc != oc) { 1834 if (bc < 0) 1835 perror("write"); 1836 else 1837 (void) fprintf(stderr, 1838 gettext("dd: unexpected short write, " 1839 "wrote %d bytes, expected %d\n"), bc, oc); 1840 term(2); 1841 } 1842 obc -= oc; 1843 op = obuf; 1844 obytes += bc; 1845 1846 /* If any data in the conversion buffer, move it into */ 1847 /* the output buffer */ 1848 1849 if (obc) { 1850 cp = obuf + obs; 1851 bc = obc; 1852 do { 1853 *op++ = *cp++; 1854 } while (--bc); 1855 } 1856 return (op); 1857 } 1858 return (obuf); 1859 } 1860 1861 /* term *************************************************************** */ 1862 /* */ 1863 /* Write record statistics, then exit */ 1864 /* */ 1865 /* Arg: c - exit status code */ 1866 /* */ 1867 /* Return: no return, calls exit */ 1868 /* */ 1869 /* ******************************************************************** */ 1870 1871 static void 1872 term(c) 1873 int c; 1874 { 1875 stats(); 1876 exit(c); 1877 } 1878 1879 /* stats ************************************************************** */ 1880 /* */ 1881 /* Write record statistics onto standard error */ 1882 /* */ 1883 /* Args: none */ 1884 /* Global args: nifr, nipr, nofr, nopr, ntrunc */ 1885 /* */ 1886 /* Return: void */ 1887 /* */ 1888 /* ******************************************************************** */ 1889 1890 static void 1891 stats() 1892 { 1893 hrtime_t delta = gethrtime() - startt; 1894 double secs = delta * 1e-9; 1895 1896 (void) fprintf(stderr, gettext("%llu+%llu records in\n"), nifr, nipr); 1897 (void) fprintf(stderr, gettext("%llu+%llu records out\n"), nofr, nopr); 1898 if (ntrunc) { 1899 (void) fprintf(stderr, 1900 gettext("%llu truncated record(s)\n"), ntrunc); 1901 } 1902 1903 /* 1904 * If we got here before we started copying somehow, don't bother 1905 * printing the rest. 1906 */ 1907 if (startt == 0) 1908 return; 1909 1910 (void) fprintf(stderr, 1911 gettext("%llu bytes transferred in %.6f secs (%.0f bytes/sec)\n"), 1912 obytes, secs, obytes / secs); 1913 } 1914