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