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