Merge illumos-gate
[unleashed.git] / usr / src / cmd / dd / dd.c
blob043301d16fa738cb5aa3e779b35ddc849b0ad3b7
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
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.
31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
32 /* All Rights Reserved */
35 * convert and copy
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>
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 */
62 #define BIG 0777777777777777777777LL
64 #define BSIZE 512
66 /* Option parameters */
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 */
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"
114 /* Global references */
116 /* Local routine declarations */
118 static int match(char *);
119 static void term();
120 static unsigned long long number();
121 static unsigned char *flsh();
122 static void stats();
124 /* Local data definitions */
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 */
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 */
158 static int trantype; /* BSD or SVr4 compatible EBCDIC */
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 */
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 */
170 /* This is an EBCDIC to ASCII conversion table */
171 /* from a proposed BTL standard April 16, 1979 */
173 static unsigned char svr4_etoa[] =
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,
209 /* This is an ASCII to EBCDIC conversion table */
210 /* from a proposed BTL standard April 16, 1979 */
212 static unsigned char svr4_atoe[] =
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,
248 /* Table for ASCII to IBM (alternate EBCDIC) code conversion */
250 static unsigned char svr4_atoibm[] =
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,
286 /* Table for conversion of ASCII to lower case ASCII */
288 static unsigned char utol[] =
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,
324 /* Table for conversion of ASCII to upper case ASCII */
326 static unsigned char ltou[] =
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,
362 /* BSD-compatible EBCDIC to ASCII translate table */
364 static unsigned char bsd_etoa[] =
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,
400 /* BSD-compatible ASCII to EBCDIC translate table */
402 static unsigned char bsd_atoe[] =
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,
438 /* BSD-compatible ASCII to IBM translate table */
440 static unsigned char bsd_atoibm[] =
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,
476 /* set up to use SVr4 ascii-ebcdic translation by default */
478 static unsigned char *atoe = svr4_atoe;
479 static unsigned char *etoa = svr4_etoa;
480 static unsigned char *atoibm = svr4_atoibm;
482 /*ARGSUSED*/
483 static void
484 siginfo_handler(int sig, siginfo_t *sip, void *ucp)
486 nstats = 1;
490 main(int argc, char **argv)
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;
500 /* Set option defaults */
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 */
509 /* Parse command options */
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);
517 while ((c = getopt(argc, argv, "")) != EOF)
518 switch (c) {
519 case '?':
520 (void) fprintf(stderr, USAGE);
521 exit(2);
524 /* not getopt()'ed because dd has no options but only operand(s) */
526 for (c = optind; c < argc; c++) {
527 string = argv[c];
528 if (match("ibs=")) {
529 ibs = (unsigned)number(BIG);
530 continue;
532 if (match("obs=")) {
533 obs = (unsigned)number(BIG);
534 continue;
536 if (match("cbs=")) {
537 cbs = (unsigned)number(BIG);
538 continue;
540 if (match("bs=")) {
541 bs = (unsigned)number(BIG);
542 continue;
544 if (match("if=")) {
545 ifile = string;
546 continue;
548 if (match("of=")) {
549 ofile = string;
550 continue;
552 if (match("skip=")) {
553 skip = number(BIG);
554 continue;
556 if (match("iseek=")) {
557 iseekn = number(BIG);
558 continue;
560 if (match("oseek=")) {
561 oseekn = number(BIG);
562 continue;
564 if (match("seek=")) { /* retained for compatibility */
565 oseekn = number(BIG);
566 continue;
568 if (match("ostride=")) {
569 ostriden = ((off_t)number(BIG)) - 1;
570 continue;
572 if (match("istride=")) {
573 istriden = ((off_t)number(BIG)) - 1;
574 continue;
576 if (match("stride=")) {
577 istriden = ostriden = ((off_t)number(BIG)) - 1;
578 continue;
580 if (match("count=")) {
581 count = number(BIG);
582 ecount = B_TRUE;
583 continue;
585 if (match("files=")) {
586 files = (int)number(BIG);
587 continue;
589 if (match("conv=")) {
590 for (;;) {
591 if (match(",")) {
592 continue;
594 if (*string == '\0') {
595 break;
597 if (match("block")) {
598 conv = BLOCK;
599 continue;
601 if (match("unblock")) {
602 conv = UNBLOCK;
603 continue;
606 /* ebcdicb, ibmb, and asciib must precede */
607 /* ebcdic, ibm, and ascii in this test */
609 if (match("ebcdicb")) {
610 conv = EBCDIC;
611 trantype = BSDXLATE;
612 continue;
614 if (match("ibmb")) {
615 conv = IBM;
616 trantype = BSDXLATE;
617 continue;
619 if (match("asciib")) {
620 conv = ASCII;
621 trantype = BSDXLATE;
622 continue;
624 if (match("ebcdic")) {
625 conv = EBCDIC;
626 trantype = SVR4XLATE;
627 continue;
629 if (match("ibm")) {
630 conv = IBM;
631 trantype = SVR4XLATE;
632 continue;
634 if (match("ascii")) {
635 conv = ASCII;
636 trantype = SVR4XLATE;
637 continue;
639 if (match("lcase")) {
640 cflag |= LCASE;
641 continue;
643 if (match("ucase")) {
644 cflag |= UCASE;
645 continue;
647 if (match("swab")) {
648 cflag |= SWAB;
649 continue;
651 if (match("noerror")) {
652 cflag |= NERR;
653 continue;
655 if (match("notrunc")) {
656 trunc = 0;
657 continue;
659 if (match("sync")) {
660 cflag |= SYNC;
661 continue;
663 goto badarg;
665 continue;
667 if (match("oflag=")) {
668 for (;;) {
669 if (match(",")) {
670 continue;
672 if (*string == '\0') {
673 break;
675 if (match("dsync")) {
676 oflag |= O_DSYNC;
677 continue;
679 if (match("sync")) {
680 oflag |= O_SYNC;
681 continue;
683 goto badarg;
685 continue;
687 badarg:
688 (void) fprintf(stderr, "dd: %s \"%s\"\n",
689 gettext("bad argument:"), string);
690 exit(2);
693 /* Perform consistency checks on options, decode strange conventions */
695 if (bs) {
696 ibs = obs = bs;
698 if ((ibs == 0) || (obs == 0)) {
699 (void) fprintf(stderr, "dd: %s\n",
700 gettext("buffer sizes cannot be zero"));
701 exit(2);
703 if (ostriden == (off_t)-1) {
704 (void) fprintf(stderr, "dd: %s\n",
705 gettext("stride must be greater than zero"));
706 exit(2);
708 if (istriden == (off_t)-1) {
709 (void) fprintf(stderr, "dd: %s\n",
710 gettext("stride must be greater than zero"));
711 exit(2);
713 if (conv == COPY) {
714 if ((bs == 0) || (cflag & (LCASE | UCASE))) {
715 conv = REBLOCK;
718 if (cbs == 0) {
719 switch (conv) {
720 case BLOCK:
721 case UNBLOCK:
722 conv = REBLOCK;
723 break;
725 case ASCII:
726 conv = NBASCII;
727 break;
729 case EBCDIC:
730 conv = NBEBCDIC;
731 break;
733 case IBM:
734 conv = NBIBM;
735 break;
739 /* Expand options into lower and upper case versions if necessary */
741 switch (conv) {
742 case REBLOCK:
743 if (cflag & LCASE)
744 conv = LCREBLOCK;
745 else if (cflag & UCASE)
746 conv = UCREBLOCK;
747 break;
749 case UNBLOCK:
750 if (cflag & LCASE)
751 conv = LCUNBLOCK;
752 else if (cflag & UCASE)
753 conv = UCUNBLOCK;
754 break;
756 case BLOCK:
757 if (cflag & LCASE)
758 conv = LCBLOCK;
759 else if (cflag & UCASE)
760 conv = UCBLOCK;
761 break;
763 case ASCII:
764 if (cflag & LCASE)
765 conv = LCASCII;
766 else if (cflag & UCASE)
767 conv = UCASCII;
768 break;
770 case NBASCII:
771 if (cflag & LCASE)
772 conv = LCNBASCII;
773 else if (cflag & UCASE)
774 conv = UCNBASCII;
775 break;
777 case EBCDIC:
778 if (cflag & LCASE)
779 conv = LCEBCDIC;
780 else if (cflag & UCASE)
781 conv = UCEBCDIC;
782 break;
784 case NBEBCDIC:
785 if (cflag & LCASE)
786 conv = LCNBEBCDIC;
787 else if (cflag & UCASE)
788 conv = UCNBEBCDIC;
789 break;
791 case IBM:
792 if (cflag & LCASE)
793 conv = LCIBM;
794 else if (cflag & UCASE)
795 conv = UCIBM;
796 break;
798 case NBIBM:
799 if (cflag & LCASE)
800 conv = LCNBIBM;
801 else if (cflag & UCASE)
802 conv = UCNBIBM;
803 break;
806 /* If BSD-compatible translation is selected, change the tables */
808 if (trantype == BSDXLATE) {
809 atoe = bsd_atoe;
810 atoibm = bsd_atoibm;
811 etoa = bsd_etoa;
813 /* Open the input file, or duplicate standard input */
815 ibf = -1;
816 if (ifile) {
817 ibf = open(ifile, O_RDONLY);
818 } else {
819 ifile = "";
820 ibf = dup(STDIN_FILENO);
823 if (ibf == -1) {
824 (void) fprintf(stderr, "dd: %s: ", ifile);
825 perror("open");
826 exit(2);
829 /* Open the output file, or duplicate standard output */
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);
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);
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));
858 } else {
859 ofile = "";
860 obf = dup(STDOUT_FILENO);
863 if (obf == -1) {
864 (void) fprintf(stderr, "dd: %s: ", ofile);
865 perror("open");
866 exit(2);
869 /* Expand memory to get an input buffer */
871 ibuf = (unsigned char *)valloc(ibs + 10);
873 /* If no conversions, the input buffer is the output buffer */
875 if (conv == COPY) {
876 obuf = ibuf;
877 } else {
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.
885 obuf = (unsigned char *)valloc(obs + cbs + 10);
887 if ((ibuf == NULL) || (obuf == NULL)) {
888 (void) fprintf(stderr,
889 "dd: %s\n", gettext("not enough memory"));
890 exit(2);
894 * Enable a statistics message when we terminate on SIGINT
895 * Also enable it to be queried via SIGINFO and SIGUSR1
898 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
899 (void) signal(SIGINT, term);
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);
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);
919 /* Skip input blocks */
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");
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;
940 skip--;
943 /* Seek past input blocks */
945 if (iseekn && lseek(ibf, (((off_t)iseekn) * ((off_t)ibs)), 1) == -1) {
946 perror("lseek");
947 exit(2);
950 /* Seek past output blocks */
952 if (oseekn && lseek(obf, (((off_t)oseekn) * ((off_t)obs)), 1) == -1) {
953 perror("lseek");
954 exit(2);
957 /* Initialize all buffer pointers */
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 */
965 /* Read and convert input blocks until end of file(s) */
967 /* Grab our start time for siginfo purposes */
968 startt = gethrtime();
970 for (;;) {
971 if (nstats != 0) {
972 stats();
973 nstats = 0;
976 if ((count == 0 && ecount == B_FALSE) || (nifr+nipr < count)) {
977 /* If proceed on error is enabled, zero the input buffer */
979 if (cflag & NERR) {
980 ip = ibuf + ibs;
981 c = ibs;
982 if (c & 1) /* if the size is odd, */
984 *--ip = 0; /* clear the odd byte */
986 if (c >>= 1) /* divide by two */
988 do { /* clear two at a time */
989 *--ip = 0;
990 *--ip = 0;
991 } while (--c);
995 /* Read the next input block */
997 ibc = read(ibf, (char *)ibuf, ibs);
999 if (istriden > 0 && lseek(ibf, istriden * ((off_t)ibs),
1000 SEEK_CUR) == -1) {
1001 perror("lseek");
1002 exit(2);
1005 /* Process input errors */
1007 if (ibc == (unsigned)-1) {
1008 perror("read");
1009 if (((cflag & NERR) == 0) ||
1010 (++nbad > BADLIMIT)) {
1011 while (obc) {
1012 (void) flsh();
1014 term(2);
1015 } else {
1016 stats();
1017 ibc = ibs; /* assume a full block */
1019 } else {
1020 nbad = 0;
1022 } else {
1023 /* Record count satisfied, simulate end of file */
1024 ibc = 0;
1025 files = 1;
1028 /* Process end of file */
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:
1039 /* Trim trailing blanks from the last line */
1041 if ((c = cbc) != 0) {
1042 do {
1043 if ((*--op) != ' ') {
1044 op++;
1045 break;
1047 } while (--c);
1048 *op++ = '\n';
1049 obc -= cbc - c - 1;
1050 cbc = 0;
1052 /* Flush the output buffer if full */
1054 while (obc >= obs) {
1055 op = flsh();
1058 break;
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:
1070 /* Pad trailing blanks if the last line is short */
1072 if (cbc) {
1073 obc += c = cbs - cbc;
1074 cbc = 0;
1075 if (c > 0) {
1076 /* Use the right kind of blank */
1078 switch (conv) {
1079 case BLOCK:
1080 case LCBLOCK:
1081 case UCBLOCK:
1082 ic = ' ';
1083 break;
1085 case EBCDIC:
1086 case LCEBCDIC:
1087 case UCEBCDIC:
1088 ic = atoe[' '];
1089 break;
1091 case IBM:
1092 case LCIBM:
1093 case UCIBM:
1094 ic = atoibm[' '];
1095 break;
1098 /* Pad with trailing blanks */
1100 do {
1101 *op++ = ic;
1102 } while (--c);
1107 /* Flush the output buffer if full */
1109 while (obc >= obs) {
1110 op = flsh();
1112 break;
1115 /* If no more files to read, flush the output buffer */
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);
1124 term(0); /* successful exit */
1125 } else {
1126 continue; /* read the next file */
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 */
1134 /* If `sync' enabled, pad nulls */
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;
1150 /* Swap the bytes in the input buffer if necessary */
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 */
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 */
1165 /* Select the appropriate conversion loop */
1167 ip = ibuf;
1168 switch (conv) {
1170 /* Simple copy: no conversion, preserve the input block size */
1172 case COPY:
1173 obc = ibc;
1174 (void) flsh();
1175 break;
1177 /* Simple copy: pack all output into equal sized blocks */
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;
1195 ibc -= c;
1196 obc += c;
1197 switch (conv) {
1198 case REBLOCK:
1199 do {
1200 *op++ = *ip++;
1201 } while (--c);
1202 break;
1204 case LCREBLOCK:
1205 do {
1206 *op++ = utol[*ip++];
1207 } while (--c);
1208 break;
1210 case UCREBLOCK:
1211 do {
1212 *op++ = ltou[*ip++];
1213 } while (--c);
1214 break;
1216 case NBASCII:
1217 do {
1218 *op++ = etoa[*ip++];
1219 } while (--c);
1220 break;
1222 case LCNBASCII:
1223 do {
1224 *op++ = utol[etoa[*ip++]];
1225 } while (--c);
1226 break;
1228 case UCNBASCII:
1229 do {
1230 *op++ = ltou[etoa[*ip++]];
1231 } while (--c);
1232 break;
1234 case NBEBCDIC:
1235 do {
1236 *op++ = atoe[*ip++];
1237 } while (--c);
1238 break;
1240 case LCNBEBCDIC:
1241 do {
1242 *op++ = atoe[utol[*ip++]];
1243 } while (--c);
1244 break;
1246 case UCNBEBCDIC:
1247 do {
1248 *op++ = atoe[ltou[*ip++]];
1249 } while (--c);
1250 break;
1252 case NBIBM:
1253 do {
1254 *op++ = atoibm[*ip++];
1255 } while (--c);
1256 break;
1258 case LCNBIBM:
1259 do {
1260 *op++ = atoibm[utol[*ip++]];
1261 } while (--c);
1262 break;
1264 case UCNBIBM:
1265 do {
1266 *op++ = atoibm[ltou[*ip++]];
1267 } while (--c);
1268 break;
1270 if (obc >= obs) {
1271 op = flsh();
1274 break;
1276 /* Convert from blocked records to lines terminated by newline */
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 */
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;
1300 case LCUNBLOCK:
1301 do {
1302 *op++ = utol[*ip++];
1303 } while (--c);
1304 break;
1306 case UCUNBLOCK:
1307 do {
1308 *op++ = ltou[*ip++];
1309 } while (--c);
1310 break;
1312 case ASCII:
1313 do {
1314 *op++ = etoa[*ip++];
1315 } while (--c);
1316 break;
1318 case LCASCII:
1319 do {
1320 *op++ = utol[etoa[*ip++]];
1321 } while (--c);
1322 break;
1324 case UCASCII:
1325 do {
1326 *op++ = ltou[etoa[*ip++]];
1327 } while (--c);
1328 break;
1331 /* Trim trailing blanks if the line is full */
1333 if (cbc == cbs) {
1334 c = cbs; /* `do - while' is usually */
1335 do { /* faster than `for' */
1336 if ((*--op) != ' ') {
1337 op++;
1338 break;
1340 } while (--c);
1341 *op++ = '\n';
1342 obc -= cbs - c - 1;
1343 cbc = 0;
1345 /* Flush the output buffer if full */
1347 while (obc >= obs) {
1348 op = flsh();
1352 break;
1354 /* Convert to blocked records */
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;
1369 * We may have to skip to the end of a long
1370 * line.
1373 if (skipf) {
1374 do {
1375 if ((ic = *ip++) == '\n') {
1376 skipf = 0;
1377 c--;
1378 break;
1380 } while (--c);
1381 if ((ibc = c) == 0) {
1382 continue;
1383 /* read another block */
1387 /* If anything left, copy until newline */
1389 if (c > (cbs - cbc + 1)) {
1390 c = cbs - cbc + 1;
1392 ibc -= c;
1393 cbc += c;
1394 obc += c;
1396 switch (conv) {
1397 case BLOCK:
1398 do {
1399 if ((ic = *ip++) != '\n') {
1400 *op++ = ic;
1401 } else {
1402 nlflag = 1;
1403 break;
1405 } while (--c);
1406 break;
1408 case LCBLOCK:
1409 do {
1410 if ((ic = *ip++) != '\n') {
1411 *op++ = utol[ic];
1412 } else {
1413 nlflag = 1;
1414 break;
1416 } while (--c);
1417 break;
1419 case UCBLOCK:
1420 do {
1421 if ((ic = *ip++) != '\n') {
1422 *op++ = ltou[ic];
1423 } else {
1424 nlflag = 1;
1425 break;
1427 } while (--c);
1428 break;
1430 case EBCDIC:
1431 do {
1432 if ((ic = *ip++) != '\n') {
1433 *op++ = atoe[ic];
1434 } else {
1435 nlflag = 1;
1436 break;
1438 } while (--c);
1439 break;
1441 case LCEBCDIC:
1442 do {
1443 if ((ic = *ip++) != '\n') {
1444 *op++ = atoe[utol[ic]];
1445 } else {
1446 nlflag = 1;
1447 break;
1449 } while (--c);
1450 break;
1452 case UCEBCDIC:
1453 do {
1454 if ((ic = *ip++) != '\n') {
1455 *op++ = atoe[ltou[ic]];
1456 } else {
1457 nlflag = 1;
1458 break;
1460 } while (--c);
1461 break;
1463 case IBM:
1464 do {
1465 if ((ic = *ip++) != '\n') {
1466 *op++ = atoibm[ic];
1467 } else {
1468 nlflag = 1;
1469 break;
1471 } while (--c);
1472 break;
1474 case LCIBM:
1475 do {
1476 if ((ic = *ip++) != '\n') {
1477 *op++ =
1478 atoibm[utol[ic]];
1479 } else {
1480 nlflag = 1;
1481 break;
1483 } while (--c);
1484 break;
1486 case UCIBM:
1487 do {
1488 if ((ic = *ip++) != '\n') {
1489 *op++ =
1490 atoibm[ltou[ic]];
1491 } else {
1492 nlflag = 1;
1493 break;
1495 } while (--c);
1496 break;
1499 /* If newline found, update all the counters and */
1500 /* pointers, pad with trailing blanks if necessary */
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 */
1510 switch (conv) {
1511 case BLOCK:
1512 case LCBLOCK:
1513 case UCBLOCK:
1514 ic = ' ';
1515 break;
1517 case EBCDIC:
1518 case LCEBCDIC:
1519 case UCEBCDIC:
1520 ic = atoe[' '];
1521 break;
1523 case IBM:
1524 case LCIBM:
1525 case UCIBM:
1526 ic = atoibm[' '];
1527 break;
1530 /* Pad with trailing blanks */
1532 do {
1533 *op++ = ic;
1534 } while (--c);
1538 /* If not end of line, this line may be too long */
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 */
1548 /* Flush the output buffer if full */
1550 while (obc >= obs) {
1551 op = flsh();
1554 break;
1557 /* NOTREACHED */
1558 return (0);
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 /* ******************************************************************** */
1574 static int
1575 match(char *s)
1577 char *cs;
1579 cs = string;
1580 while (*cs++ == *s) {
1581 if (*s++ == '\0') {
1582 goto true;
1585 if (*s != '\0') {
1586 return (0);
1589 true:
1590 cs--;
1591 string = cs;
1592 return (1);
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 /* ******************************************************************** */
1610 static unsigned long long
1611 number(long long big)
1613 char *cs;
1614 long long n;
1615 long long cut = BIG / 10; /* limit to avoid overflow */
1617 cs = string;
1618 n = 0;
1619 while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) {
1620 n = n * 10 + *cs++ - '0';
1622 for (;;) {
1623 switch (*cs++) {
1625 case 'Z':
1626 n *= 1024;
1627 /* FALLTHROUGH */
1629 case 'E':
1630 n *= 1024;
1631 /* FALLTHROUGH */
1633 case 'P':
1634 n *= 1024;
1635 /* FALLTHROUGH */
1637 case 'T':
1638 n *= 1024;
1639 /* FALLTHROUGH */
1641 case 'G':
1642 n *= 1024;
1643 /* FALLTHROUGH */
1645 case 'M':
1646 n *= 1024;
1647 /* FALLTHROUGH */
1649 case 'k':
1650 n *= 1024;
1651 continue;
1653 case 'w':
1654 n *= 2;
1655 continue;
1657 case 'b':
1658 n *= BSIZE;
1659 continue;
1661 case '*':
1662 case 'x':
1663 string = cs;
1664 n *= number(BIG);
1666 /* FALLTHROUGH */
1667 /* Fall into exit test, recursion has read rest of string */
1668 /* End of string, check for a valid number */
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);
1676 return (n);
1678 default:
1679 (void) fprintf(stderr, "dd: %s \"%s\"\n",
1680 gettext("bad numeric argument:"), string);
1681 exit(2);
1683 } /* never gets here */
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 /* ******************************************************************** */
1698 static unsigned char *
1699 flsh(void)
1701 unsigned char *op, *cp;
1702 int bc;
1703 unsigned int oc;
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 */
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);
1722 term(2);
1725 if (ostriden > 0 && lseek(obf, ostriden * ((off_t)obs),
1726 SEEK_CUR) == -1) {
1727 perror("lseek");
1728 exit(2);
1731 obc -= oc;
1732 op = obuf;
1733 obytes += bc;
1735 /* If any data in the conversion buffer, move it into */
1736 /* the output buffer */
1738 if (obc) {
1739 cp = obuf + obs;
1740 bc = obc;
1741 do {
1742 *op++ = *cp++;
1743 } while (--bc);
1745 return (op);
1747 return (obuf);
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 /* ******************************************************************** */
1760 static void
1761 term(int c)
1763 stats();
1764 exit(c);
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 /* ******************************************************************** */
1778 static void
1779 stats(void)
1781 hrtime_t delta = gethrtime() - startt;
1782 double secs = delta * 1e-9;
1783 char nnum[NN_NUMBUF_SZ];
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);
1793 * If we got here before we started copying somehow, don't bother
1794 * printing the rest.
1796 if (startt == 0)
1797 return;
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);