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