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