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