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
siginfo_handler(int sig,siginfo_t * sip,void * ucp)477 siginfo_handler(int sig, siginfo_t *sip, void *ucp)
478 {
479 nstats = 1;
480 }
481
482 int
main(int argc,char ** argv)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
match(s)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
number(big)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
flsh()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
term(c)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
stats()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