dd.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* convert and copy
*/
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/sysmacros.h>
#include <unistd.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
/* The BIG parameter is machine dependent. It should be a long integer */
/* constant that can be used by the number parser to check the validity */
/* of numeric parameters. On 16-bit machines, it should probably be */
/* the maximum unsigned integer, 0177777L. On 32-bit machines where */
/* longs are the same size as ints, the maximum signed integer is more */
/* appropriate. This value is 017777777777L. In 64 bit environments, */
/* the maximum signed integer value is 0777777777777777777777LL */
#define BIG 0777777777777777777777LL
#define BSIZE 512
/* Option parameters */
#define COPY 0 /* file copy, preserve input block size */
#define SVR4XLATE 0 /* use default EBCDIC translation */
#define USAGE\
"usage: dd [if=file] [of=file] [ibs=n|nk|nb|nxm] [obs=n|nk|nb|nxm]\n"\
" [bs=n|nk|nb|nxm] [cbs=n|nk|nb|nxm] [files=n] [skip=n]\n"\
" [iseek=n] [oseek=n] [seek=n] [count=n] [conv=[ascii]\n"\
" [,ebcdic][,ibm][,asciib][,ebcdicb][,ibmb]\n"\
" [,block|unblock][,lcase|ucase][,swab]\n"\
" [,noerror][,notrunc][,sync]]\n"
/* Global references */
/* Local routine declarations */
static int match(char *);
static void term();
static unsigned long long number();
static unsigned char *flsh();
static void stats();
/* Local data definitions */
static unsigned ibs; /* input buffer size */
static unsigned obs; /* output buffer size */
static unsigned bs; /* buffer size, overrules ibs and obs */
static unsigned cbs; /* conversion buffer size, used for block conversions */
static unsigned ibc; /* number of bytes still in the input buffer */
static unsigned obc; /* number of bytes in the output buffer */
static unsigned cbc; /* number of bytes in the conversion buffer */
static int ibf; /* input file descriptor */
static int obf; /* output file descriptor */
static int cflag; /* conversion option flags */
static int skipf; /* if skipf == 1, skip rest of input line */
static unsigned long long nifr; /* count of full input records */
static unsigned long long nipr; /* count of partial input records */
static unsigned long long nofr; /* count of full output records */
static unsigned long long nopr; /* count of partial output records */
static unsigned long long ntrunc; /* count of truncated input lines */
static unsigned long long nbad; /* count of bad records since last */
/* good one */
static int files; /* number of input files to concatenate (tape only) */
static unsigned long long count; /* number of input records to copy */
/* (0 = all) */
static int trantype; /* BSD or SVr4 compatible EBCDIC */
static char *string; /* command arg pointer */
static char *ifile; /* input file name pointer */
static char *ofile; /* output file name pointer */
static unsigned char *ibuf; /* input buffer pointer */
static unsigned char *obuf; /* output buffer pointer */
/* This is an EBCDIC to ASCII conversion table */
/* from a proposed BTL standard April 16, 1979 */
static unsigned char svr4_etoa [] =
{
0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177,
0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207,
0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037,
0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033,
0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007,
0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004,
0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032,
0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174,
0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176,
0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077,
0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320,
0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170,
0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327,
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347,
0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377,
};
/* This is an ASCII to EBCDIC conversion table */
/* from a proposed BTL standard April 16, 1979 */
static unsigned char svr4_atoe [] =
{
0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057,
0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046,
0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037,
0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155,
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007,
0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027,
0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033,
0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010,
0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341,
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236,
0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277,
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377,
};
/* Table for ASCII to IBM (alternate EBCDIC) code conversion */
static unsigned char svr4_atoibm[] =
{
0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057,
0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046,
0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037,
0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155,
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007,
0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027,
0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033,
0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010,
0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341,
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377,
};
/* Table for conversion of ASCII to lower case ASCII */
static unsigned char utol[] =
{
0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
};
/* Table for conversion of ASCII to upper case ASCII */
static unsigned char ltou[] =
{
0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
};
/* BSD-compatible EBCDIC to ASCII translate table */
static unsigned char bsd_etoa[] =
{
0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177,
0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207,
0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037,
0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033,
0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007,
0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004,
0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032,
0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041,
0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136,
0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077,
0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320,
0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170,
0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327,
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377,
};
/* BSD-compatible ASCII to EBCDIC translate table */
static unsigned char bsd_atoe[] =
{
0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057,
0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046,
0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037,
0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175,
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155,
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007,
0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027,
0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033,
0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010,
0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341,
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377,
};
/* BSD-compatible ASCII to IBM translate table */
static unsigned char bsd_atoibm[] =
{
0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057,
0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046,
0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037,
0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155,
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007,
0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027,
0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033,
0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010,
0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341,
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377,
};
/* set up to use SVr4 ascii-ebcdic translation by default */
static unsigned char *atoibm = svr4_atoibm;
void
int argc;
char **argv;
{
int c; /* character counter */
int ic; /* input character */
int conv; /* conversion option code */
int trunc; /* whether output file is truncated */
/* Set option defaults */
files = 1;
/* Parse command options */
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
switch (c) {
case '?':
exit(2);
}
/* not getopt()'ed because dd has no options but only operand(s) */
{
if (match("ibs="))
{
continue;
}
if (match("obs="))
{
continue;
}
if (match("cbs="))
{
continue;
}
if (match("bs="))
{
continue;
}
if (match("if="))
{
continue;
}
if (match("of="))
{
continue;
}
if (match("skip="))
{
continue;
}
if (match("iseek="))
{
continue;
}
if (match("oseek="))
{
continue;
}
{
continue;
}
if (match("count="))
{
continue;
}
if (match("files="))
{
continue;
}
if (match("conv="))
{
for (;;)
{
if (match(","))
{
continue;
}
if (*string == '\0')
{
break;
}
if (match("block"))
{
continue;
}
if (match("unblock"))
{
continue;
}
/* ebcdicb, ibmb, and asciib must precede */
/* ebcdic, ibm, and ascii in this test */
if (match("ebcdicb"))
{
continue;
}
if (match("ibmb"))
{
continue;
}
if (match("asciib"))
{
continue;
}
if (match("ebcdic"))
{
continue;
}
if (match("ibm"))
{
continue;
}
if (match("ascii"))
{
continue;
}
if (match("lcase"))
{
continue;
}
if (match("ucase"))
{
continue;
}
if (match("swab"))
{
continue;
}
if (match("noerror"))
{
continue;
}
if (match("notrunc"))
{
trunc = 0;
continue;
}
if (match("sync"))
{
continue;
}
goto badarg;
}
continue;
}
exit(2);
}
/* Perform consistency checks on options, decode strange conventions */
if (bs)
{
}
{
gettext("buffer sizes cannot be zero"));
exit(2);
}
{
{
}
}
if (cbs == 0)
{
switch (conv)
{
case BLOCK:
case UNBLOCK:
break;
case ASCII:
break;
case EBCDIC:
break;
case IBM:
break;
}
}
/* Expand options into lower and upper case versions if necessary */
switch (conv)
{
case REBLOCK:
break;
case UNBLOCK:
break;
case BLOCK:
break;
case ASCII:
break;
case NBASCII:
break;
case EBCDIC:
break;
case NBEBCDIC:
conv = LCNBEBCDIC;
conv = UCNBEBCDIC;
break;
case IBM:
break;
case NBIBM:
break;
}
/* If BSD-compatible translation is selected, change the tables */
atoibm = bsd_atoibm;
}
/* Open the input file, or duplicate standard input */
ibf = -1;
if (ifile)
{
}
#ifndef STANDALONE
else
{
ifile = "";
}
#endif
if (ibf == -1)
{
perror("open");
exit(2);
}
/* Open the output file, or duplicate standard output */
obf = -1;
if (ofile)
{
if (trunc == 0) /* do not truncate output file */
{
if (obf == -1)
{
perror("open");
exit(2);
}
== -1))
{
perror("ftruncate");
exit(2);
}
}
else
}
#ifndef STANDALONE
else
{
ofile = "";
}
#endif
if (obf == -1)
{
perror("open");
exit(2);
}
/* Expand memory to get an input buffer */
/* If no conversions, the input buffer is the output buffer */
{
}
/* Expand memory to get an output buffer. Leave enough room at the */
/* end to convert a logical record when doing block conversions. */
else
{
}
{
exit(2);
}
/* Enable a statistics message on SIGINT */
#ifndef STANDALONE
{
}
#endif
/* Skip input blocks */
while (skip)
{
if (ibc == (unsigned)-1)
{
{
gettext("skip failed"));
exit(2);
}
else
{
perror("read");
}
}
else
{
if (ibc == 0)
{
gettext("cannot skip past end-of-file"));
exit(3);
}
else
{
nbad = 0;
}
}
skip--;
}
/* Seek past input blocks */
{
perror("lseek");
exit(2);
}
/* Seek past output blocks */
{
perror("lseek");
exit(2);
}
/* Initialize all buffer pointers */
skipf = 0; /* not skipping an input line */
ibc = 0; /* no input characters yet */
obc = 0; /* no output characters yet */
cbc = 0; /* the conversion buffer is empty */
/* Read and convert input blocks until end of file(s) */
for (;;)
{
{
/* If proceed on error is enabled, zero the input buffer */
{
c = ibs;
if (c & 1) /* if the size is odd, */
{
*--ip = 0; /* clear the odd byte */
}
if (c >>= 1) /* divide by two */
{
do { /* clear two at a time */
*--ip = 0;
*--ip = 0;
} while (--c);
}
}
/* Read the next input block */
/* Process input errors */
if (ibc == (unsigned)-1)
{
perror("read");
{
while (obc)
{
(void) flsh();
}
term(2);
}
else
{
stats();
}
}
else
{
nbad = 0;
}
}
/* Record count satisfied, simulate end of file */
else
{
ibc = 0;
files = 1;
}
/* Process end of file */
if (ibc == 0)
{
switch (conv)
{
case UNBLOCK:
case LCUNBLOCK:
case UCUNBLOCK:
case ASCII:
case LCASCII:
case UCASCII:
/* Trim trailing blanks from the last line */
if ((c = cbc) != 0)
{
do {
if ((*--op) != ' ')
{
op++;
break;
}
} while (--c);
*op++ = '\n';
cbc = 0;
/* Flush the output buffer if full */
{
}
}
break;
case BLOCK:
case LCBLOCK:
case UCBLOCK:
case EBCDIC:
case LCEBCDIC:
case UCEBCDIC:
case IBM:
case LCIBM:
case UCIBM:
/* Pad trailing blanks if the last line is short */
if (cbc)
{
cbc = 0;
if (c > 0)
{
/* Use the right kind of blank */
switch (conv)
{
case BLOCK:
case LCBLOCK:
case UCBLOCK:
ic = ' ';
break;
case EBCDIC:
case LCEBCDIC:
case UCEBCDIC:
break;
case IBM:
case LCIBM:
case UCIBM:
break;
}
/* Pad with trailing blanks */
do {
} while (--c);
}
}
/* Flush the output buffer if full */
{
}
break;
}
/* If no more files to read, flush the output buffer */
if (--files <= 0)
{
(void) flsh();
{
exit(2);
}
term(0); /* successful exit */
}
else
{
continue; /* read the next file */
}
}
/* Normal read, check for special cases */
{
nifr++; /* count another full input record */
}
else
{
nipr++; /* count a partial input record */
/* If `sync' enabled, pad nulls */
{
do {
*--ip = ' ';
else
*--ip = '\0';
} while (--c);
}
}
/* Swap the bytes in the input buffer if necessary */
{
{
}
do {
} while (--c); /* do two bytes at a time */
}
/* Select the appropriate conversion loop */
switch (conv)
{
/* Simple copy: no conversion, preserve the input block size */
case COPY:
(void) flsh();
break;
/* Simple copy: pack all output into equal sized blocks */
case REBLOCK:
case LCREBLOCK:
case UCREBLOCK:
case NBASCII:
case LCNBASCII:
case UCNBASCII:
case NBEBCDIC:
case LCNBEBCDIC:
case UCNBEBCDIC:
case NBIBM:
case LCNBIBM:
case UCNBIBM:
while ((c = ibc) != 0)
{
{
}
ibc -= c;
obc += c;
switch (conv)
{
case REBLOCK:
do {
} while (--c);
break;
case LCREBLOCK:
do {
} while (--c);
break;
case UCREBLOCK:
do {
} while (--c);
break;
case NBASCII:
do {
} while (--c);
break;
case LCNBASCII:
do {
} while (--c);
break;
case UCNBASCII:
do {
} while (--c);
break;
case NBEBCDIC:
do {
} while (--c);
break;
case LCNBEBCDIC:
do {
} while (--c);
break;
case UCNBEBCDIC:
do {
} while (--c);
break;
case NBIBM:
do {
} while (--c);
break;
case LCNBIBM:
do {
} while (--c);
break;
case UCNBIBM:
do {
} while (--c);
break;
}
{
}
}
break;
/* Convert from blocked records to lines terminated by newline */
case UNBLOCK:
case LCUNBLOCK:
case UCUNBLOCK:
case ASCII:
case LCASCII:
case UCASCII:
while ((c = ibc) != 0)
{
/* if more than one record, */
{
/* only copy one record */
}
ibc -= c;
cbc += c;
obc += c;
switch (conv)
{
case UNBLOCK:
do {
} while (--c);
break;
case LCUNBLOCK:
do {
} while (--c);
break;
case UCUNBLOCK:
do {
} while (--c);
break;
case ASCII:
do {
} while (--c);
break;
case LCASCII:
do {
} while (--c);
break;
case UCASCII:
do {
} while (--c);
break;
}
/* Trim trailing blanks if the line is full */
{
c = cbs; /* `do - while' is usually */
do { /* faster than `for' */
if ((*--op) != ' ')
{
op++;
break;
}
} while (--c);
*op++ = '\n';
cbc = 0;
/* Flush the output buffer if full */
{
}
}
}
break;
/* Convert to blocked records */
case BLOCK:
case LCBLOCK:
case UCBLOCK:
case EBCDIC:
case LCEBCDIC:
case UCEBCDIC:
case IBM:
case LCIBM:
case UCIBM:
while ((c = ibc) != 0)
{
int nlflag = 0;
/* We may have to skip to the end of a long line */
if (skipf)
{
do {
{
skipf = 0;
c--;
break;
}
} while (--c);
if ((ibc = c) == 0)
{
continue;
/* read another block */
}
}
/* If anything left, copy until newline */
{
}
ibc -= c;
cbc += c;
obc += c;
switch (conv)
{
case BLOCK:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
case LCBLOCK:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
case UCBLOCK:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
case EBCDIC:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
case LCEBCDIC:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
case UCEBCDIC:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
case IBM:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
case LCIBM:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
case UCIBM:
do {
{
}
else
{
nlflag = 1;
break;
}
} while (--c);
break;
}
/* If newline found, update all the counters and */
/* pointers, pad with trailing blanks if necessary */
if (nlflag)
{
ibc += c - 1;
cbc = 0;
if (c > 0)
{
/* Use the right kind of blank */
switch (conv)
{
case BLOCK:
case LCBLOCK:
case UCBLOCK:
ic = ' ';
break;
case EBCDIC:
case LCEBCDIC:
case UCEBCDIC:
break;
case IBM:
case LCIBM:
case UCIBM:
break;
}
/* Pad with trailing blanks */
do {
} while (--c);
}
}
/* If not end of line, this line may be too long */
{
obc--;
op--;
cbc = 0;
ntrunc++; /* count another long line */
}
/* Flush the output buffer if full */
{
}
}
break;
}
}
}
/* match ************************************************************** */
/* */
/* Compare two text strings for equality */
/* */
/* Arg: s - pointer to string to match with a command arg */
/* Global arg: string - pointer to command arg */
/* */
/* Return: 1 if match, 0 if no match */
/* If match, also reset `string' to point to the text */
/* that follows the matching text. */
/* */
/* ******************************************************************** */
static int
match(s)
char *s;
{
char *cs;
while (*cs++ == *s)
{
if (*s++ == '\0')
{
goto true;
}
}
if (*s != '\0')
{
return (0);
}
true:
cs--;
return (1);
}
/* number ************************************************************* */
/* */
/* Convert a numeric arg to binary */
/* */
/* Arg: big - maximum valid input number */
/* Global arg: string - pointer to command arg */
/* */
/* Valid forms: 123 | 123k | 123w | 123b | 123*123 | 123x123 */
/* plus combinations such as 2b*3kw*4w */
/* */
/* Return: converted number */
/* */
/* ******************************************************************** */
static unsigned long long
long long big;
{
char *cs;
long long n;
n = 0;
{
}
for (;;)
{
switch (*cs++)
{
case 'k':
n *= 1024;
continue;
case 'w':
n *= 2;
continue;
case 'b':
n *= BSIZE;
continue;
case '*':
case 'x':
/* FALLTHROUGH */
/* Fall into exit test, recursion has read rest of string */
/* End of string, check for a valid number */
case '\0':
if ((n > big) || (n < 0))
{
gettext("argument out of range:"), n);
exit(2);
}
return (n);
default:
exit(2);
}
} /* never gets here */
}
/* flsh *************************************************************** */
/* */
/* Flush the output buffer, move any excess bytes down to the beginning */
/* */
/* Arg: none */
/* Global args: obuf, obc, obs, nofr, nopr */
/* */
/* Return: Pointer to the first free byte in the output buffer. */
/* Also reset `obc' to account for moved bytes. */
/* */
/* ******************************************************************** */
static unsigned char
*flsh()
{
int bc;
unsigned int oc;
if (obc) /* don't flush if the buffer is empty */
{
nofr++; /* count a full output buffer */
}
else
{
nopr++; /* count a partial output buffer */
}
if (bc < 0)
perror("write");
else
gettext("dd: unexpected short write, "
term(2);
}
/* If any data in the conversion buffer, move it into */
/* the output buffer */
if (obc) {
do {
} while (--bc);
}
return (op);
}
return (obuf);
}
/* term *************************************************************** */
/* */
/* Write record statistics, then exit */
/* */
/* Arg: c - exit status code */
/* */
/* Return: no return, calls exit */
/* */
/* ******************************************************************** */
static void
term(c)
int c;
{
stats();
exit(c);
}
/* stats ************************************************************** */
/* */
/* Write record statistics onto standard error */
/* */
/* Args: none */
/* Global args: nifr, nipr, nofr, nopr, ntrunc */
/* */
/* Return: void */
/* */
/* ******************************************************************** */
static void
stats()
{
if (ntrunc) {
}
}