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