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 }