#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <sys/time.h>
#include <errno.h>
#include <strings.h>
#include <libcmdutils.h>
#define BIG 0777777777777777777777LL
#define BSIZE 512
#define COPY 0
#define REBLOCK 1
#define LCREBLOCK 2
#define UCREBLOCK 3
#define NBASCII 4
#define LCNBASCII 5
#define UCNBASCII 6
#define NBEBCDIC 7
#define LCNBEBCDIC 8
#define UCNBEBCDIC 9
#define NBIBM 10
#define LCNBIBM 11
#define UCNBIBM 12
#define UNBLOCK 13
#define LCUNBLOCK 14
#define UCUNBLOCK 15
#define ASCII 16
#define LCASCII 17
#define UCASCII 18
#define BLOCK 19
#define LCBLOCK 20
#define UCBLOCK 21
#define EBCDIC 22
#define LCEBCDIC 23
#define UCEBCDIC 24
#define IBM 25
#define LCIBM 26
#define UCIBM 27
#define LCASE 01
#define UCASE 02
#define SWAB 04
#define NERR 010
#define SYNC 020
#define FULLBLOCK 040
#define BADLIMIT 5
#define SVR4XLATE 0
#define BSDXLATE 1
#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] [stride=n] [istride=n]\n"\
" [ostride=n] [count=n] [conv=[ascii][,ebcdic][,ibm]\n"\
" [,asciib][,ebcdicb][,ibmb][,block|unblock][,lcase|ucase]\n"\
" [,swab][,noerror][,notrunc][,sync]]\n"\
" [iflag=[fullblock]] [oflag=[dsync][sync]]\n"
static int match(char *);
static void term(int);
static unsigned long long number(long long);
static unsigned char *flsh(void);
static void stats(boolean_t);
static unsigned ibs;
static unsigned obs;
static unsigned bs;
static unsigned cbs;
static unsigned ibc;
static unsigned obc;
static unsigned cbc;
static int ibf;
static int obf;
static int cflag;
static int iflag;
static int oflag;
static int skipf;
static unsigned long long nifr;
static unsigned long long nipr;
static unsigned long long nofr;
static unsigned long long nopr;
static unsigned long long ntrunc;
static unsigned long long nbad;
static int files;
static off_t skip;
static off_t iseekn;
static off_t oseekn;
static unsigned long long count;
static boolean_t ecount;
static off_t ostriden;
static off_t istriden;
static int trantype;
static char *string;
static char *ifile;
static char *ofile;
static unsigned char *ibuf;
static unsigned char *obuf;
static hrtime_t startt;
static uint64_t prog_secs;
static unsigned long long obytes;
static sig_atomic_t nstats;
typedef enum dd_status {
DD_STATUS_DEFAULT = 0,
DD_STATUS_NONE = 1 << 0,
DD_STATUS_PROGRESS = 1 << 1,
DD_STATUS_NOXFER = 1 << 2
} dd_status_t;
static dd_status_t status_arg = DD_STATUS_DEFAULT;
static boolean_t stderr_tty = B_FALSE;
static boolean_t progress_printed = B_FALSE;
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
static unsigned char *atoe = svr4_atoe;
static unsigned char *etoa = svr4_etoa;
static unsigned char *atoibm = svr4_atoibm;
static void
siginfo_handler(int sig, siginfo_t *sip, void *ucp)
{
nstats = 1;
}
static ssize_t
iread(int fd, char *buf, size_t nbyte)
{
ssize_t count;
count = 0;
while (nbyte != 0) {
ssize_t nr = read(fd, buf, nbyte);
if (nr < 0)
return (nr);
if (nr == 0)
break;
buf += nr;
count += nr;
nbyte -= nr;
if ((iflag & FULLBLOCK) == 0)
break;
}
return (count);
}
int
main(int argc, char **argv)
{
unsigned char *ip, *op;
int c;
int ic;
int conv;
int trunc;
struct stat file_stat;
struct sigaction sact;
ibs = BSIZE;
obs = BSIZE;
files = 1;
conv = COPY;
trunc = 1;
trantype = SVR4XLATE;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
while ((c = getopt(argc, argv, "")) != EOF)
switch (c) {
case '?':
(void) fprintf(stderr, USAGE);
exit(2);
}
for (c = optind; c < argc; c++) {
string = argv[c];
if (match("ibs=")) {
ibs = (unsigned)number(BIG);
continue;
}
if (match("obs=")) {
obs = (unsigned)number(BIG);
continue;
}
if (match("cbs=")) {
cbs = (unsigned)number(BIG);
continue;
}
if (match("bs=")) {
bs = (unsigned)number(BIG);
continue;
}
if (match("if=")) {
ifile = string;
continue;
}
if (match("of=")) {
ofile = string;
continue;
}
if (match("skip=")) {
skip = number(BIG);
continue;
}
if (match("iseek=")) {
iseekn = number(BIG);
continue;
}
if (match("oseek=")) {
oseekn = number(BIG);
continue;
}
if (match("seek=")) {
oseekn = number(BIG);
continue;
}
if (match("ostride=")) {
ostriden = ((off_t)number(BIG)) - 1;
continue;
}
if (match("istride=")) {
istriden = ((off_t)number(BIG)) - 1;
continue;
}
if (match("stride=")) {
istriden = ostriden = ((off_t)number(BIG)) - 1;
continue;
}
if (match("count=")) {
count = number(BIG);
ecount = B_TRUE;
continue;
}
if (match("files=")) {
files = (int)number(BIG);
continue;
}
if (match("conv=")) {
for (;;) {
if (match(",")) {
continue;
}
if (*string == '\0') {
break;
}
if (match("block")) {
conv = BLOCK;
continue;
}
if (match("unblock")) {
conv = UNBLOCK;
continue;
}
if (match("ebcdicb")) {
conv = EBCDIC;
trantype = BSDXLATE;
continue;
}
if (match("ibmb")) {
conv = IBM;
trantype = BSDXLATE;
continue;
}
if (match("asciib")) {
conv = ASCII;
trantype = BSDXLATE;
continue;
}
if (match("ebcdic")) {
conv = EBCDIC;
trantype = SVR4XLATE;
continue;
}
if (match("ibm")) {
conv = IBM;
trantype = SVR4XLATE;
continue;
}
if (match("ascii")) {
conv = ASCII;
trantype = SVR4XLATE;
continue;
}
if (match("lcase")) {
cflag |= LCASE;
continue;
}
if (match("ucase")) {
cflag |= UCASE;
continue;
}
if (match("swab")) {
cflag |= SWAB;
continue;
}
if (match("noerror")) {
cflag |= NERR;
continue;
}
if (match("notrunc")) {
trunc = 0;
continue;
}
if (match("sync")) {
cflag |= SYNC;
continue;
}
goto badarg;
}
continue;
}
if (match("iflag=")) {
for (;;) {
if (match(",")) {
continue;
}
if (*string == '\0') {
break;
}
if (match("fullblock")) {
iflag |= FULLBLOCK;
continue;
}
goto badarg;
}
continue;
}
if (match("oflag=")) {
for (;;) {
if (match(",")) {
continue;
}
if (*string == '\0') {
break;
}
if (match("dsync")) {
oflag |= O_DSYNC;
continue;
}
if (match("sync")) {
oflag |= O_SYNC;
continue;
}
goto badarg;
}
continue;
}
if (match("status=")) {
if (match("none")) {
status_arg = DD_STATUS_NONE;
} else if (match("noxfer")) {
status_arg = DD_STATUS_NOXFER;
} else if (match("progress")) {
status_arg = DD_STATUS_PROGRESS;
} else {
goto badarg;
}
continue;
}
badarg:
(void) fprintf(stderr, "dd: %s \"%s\"\n",
gettext("bad argument:"), string);
exit(2);
}
if (bs) {
ibs = obs = bs;
}
if ((ibs == 0) || (obs == 0)) {
(void) fprintf(stderr, "dd: %s\n",
gettext("buffer sizes cannot be zero"));
exit(2);
}
if (ostriden == (off_t)-1) {
(void) fprintf(stderr, "dd: %s\n",
gettext("stride must be greater than zero"));
exit(2);
}
if (istriden == (off_t)-1) {
(void) fprintf(stderr, "dd: %s\n",
gettext("stride must be greater than zero"));
exit(2);
}
if (conv == COPY) {
if ((bs == 0) || (cflag & (LCASE | UCASE))) {
conv = REBLOCK;
}
}
if (cbs == 0) {
switch (conv) {
case BLOCK:
case UNBLOCK:
conv = REBLOCK;
break;
case ASCII:
conv = NBASCII;
break;
case EBCDIC:
conv = NBEBCDIC;
break;
case IBM:
conv = NBIBM;
break;
}
}
switch (conv) {
case REBLOCK:
if (cflag & LCASE)
conv = LCREBLOCK;
else if (cflag & UCASE)
conv = UCREBLOCK;
break;
case UNBLOCK:
if (cflag & LCASE)
conv = LCUNBLOCK;
else if (cflag & UCASE)
conv = UCUNBLOCK;
break;
case BLOCK:
if (cflag & LCASE)
conv = LCBLOCK;
else if (cflag & UCASE)
conv = UCBLOCK;
break;
case ASCII:
if (cflag & LCASE)
conv = LCASCII;
else if (cflag & UCASE)
conv = UCASCII;
break;
case NBASCII:
if (cflag & LCASE)
conv = LCNBASCII;
else if (cflag & UCASE)
conv = UCNBASCII;
break;
case EBCDIC:
if (cflag & LCASE)
conv = LCEBCDIC;
else if (cflag & UCASE)
conv = UCEBCDIC;
break;
case NBEBCDIC:
if (cflag & LCASE)
conv = LCNBEBCDIC;
else if (cflag & UCASE)
conv = UCNBEBCDIC;
break;
case IBM:
if (cflag & LCASE)
conv = LCIBM;
else if (cflag & UCASE)
conv = UCIBM;
break;
case NBIBM:
if (cflag & LCASE)
conv = LCNBIBM;
else if (cflag & UCASE)
conv = UCNBIBM;
break;
}
if (trantype == BSDXLATE) {
atoe = bsd_atoe;
atoibm = bsd_atoibm;
etoa = bsd_etoa;
}
ibf = -1;
if (ifile) {
ibf = open(ifile, 0);
} else {
ifile = "";
ibf = dup(STDIN_FILENO);
}
if (ibf == -1) {
(void) fprintf(stderr, "dd: %s: ", ifile);
perror("open");
exit(2);
}
obf = -1;
if (ofile) {
if (trunc == 0) {
obf = open(ofile, (O_WRONLY | O_CREAT | oflag),
(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH));
} else if (oseekn && (trunc == 1)) {
obf = open(ofile, O_WRONLY | O_CREAT | oflag,
(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH));
if (obf == -1) {
(void) fprintf(stderr, "dd: %s: ", ofile);
perror("open");
exit(2);
}
(void) fstat(obf, &file_stat);
if (((file_stat.st_mode & S_IFMT) == S_IFREG) &&
(ftruncate(obf, (((off_t)oseekn) * ((off_t)obs)))
== -1)) {
perror("ftruncate");
exit(2);
}
} else {
obf = open(ofile, O_WRONLY | O_CREAT | O_TRUNC | oflag,
(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH));
}
} else {
ofile = "";
obf = dup(STDOUT_FILENO);
}
if (obf == -1) {
(void) fprintf(stderr, "dd: %s: ", ofile);
perror("open");
exit(2);
}
ibuf = (unsigned char *)valloc(ibs + 10);
if (conv == COPY) {
obuf = ibuf;
} else {
obuf = (unsigned char *)valloc(obs + cbs + 10);
}
if ((ibuf == NULL) || (obuf == NULL)) {
(void) fprintf(stderr,
"dd: %s\n", gettext("not enough memory"));
exit(2);
}
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
(void) signal(SIGINT, term);
}
bzero(&sact, sizeof (struct sigaction));
sact.sa_flags = SA_SIGINFO;
sact.sa_sigaction = siginfo_handler;
(void) sigemptyset(&sact.sa_mask);
if (sigaction(SIGINFO, &sact, NULL) != 0) {
(void) fprintf(stderr, "dd: %s: %s\n",
gettext("failed to enable siginfo handler"),
gettext(strerror(errno)));
exit(2);
}
if (sigaction(SIGUSR1, &sact, NULL) != 0) {
(void) fprintf(stderr, "dd: %s: %s\n",
gettext("failed to enable sigusr1 handler"),
gettext(strerror(errno)));
exit(2);
}
if (isatty(STDERR_FILENO) == 1) {
stderr_tty = B_TRUE;
}
while (skip) {
ibc = iread(ibf, (char *)ibuf, ibs);
if (ibc == (unsigned)-1) {
if (++nbad > BADLIMIT) {
(void) fprintf(stderr, "dd: %s\n",
gettext("skip failed"));
exit(2);
} else {
perror("read");
}
} else {
if (ibc == 0) {
(void) fprintf(stderr, "dd: %s\n",
gettext("cannot skip past end-of-file"));
exit(3);
} else {
nbad = 0;
}
}
skip--;
}
if (iseekn && lseek(ibf, (((off_t)iseekn) * ((off_t)ibs)), 1) == -1) {
perror("lseek");
exit(2);
}
if (oseekn && lseek(obf, (((off_t)oseekn) * ((off_t)obs)), 1) == -1) {
perror("lseek");
exit(2);
}
skipf = 0;
ibc = 0;
obc = 0;
cbc = 0;
op = obuf;
startt = gethrtime();
for (;;) {
stats(B_TRUE);
if ((count == 0 && ecount == B_FALSE) || (nifr+nipr < count)) {
if (cflag & NERR) {
ip = ibuf + ibs;
c = ibs;
if (c & 1)
{
*--ip = 0;
}
if (c >>= 1)
{
do {
*--ip = 0;
*--ip = 0;
} while (--c);
}
}
ibc = iread(ibf, (char *)ibuf, ibs);
if (istriden > 0 && lseek(ibf, istriden * ((off_t)ibs),
SEEK_CUR) == -1) {
perror("lseek");
exit(2);
}
if (ibc == (unsigned)-1) {
perror("read");
if (((cflag & NERR) == 0) ||
(++nbad > BADLIMIT)) {
while (obc) {
(void) flsh();
}
term(2);
} else {
stats(B_FALSE);
ibc = ibs;
}
} else {
nbad = 0;
}
} else {
ibc = 0;
files = 1;
}
if (ibc == 0) {
switch (conv) {
case UNBLOCK:
case LCUNBLOCK:
case UCUNBLOCK:
case ASCII:
case LCASCII:
case UCASCII:
if ((c = cbc) != 0) {
do {
if ((*--op) != ' ') {
op++;
break;
}
} while (--c);
*op++ = '\n';
obc -= cbc - c - 1;
cbc = 0;
while (obc >= obs) {
op = flsh();
}
}
break;
case BLOCK:
case LCBLOCK:
case UCBLOCK:
case EBCDIC:
case LCEBCDIC:
case UCEBCDIC:
case IBM:
case LCIBM:
case UCIBM:
if (cbc) {
obc += c = cbs - cbc;
cbc = 0;
if (c > 0) {
switch (conv) {
case BLOCK:
case LCBLOCK:
case UCBLOCK:
ic = ' ';
break;
case EBCDIC:
case LCEBCDIC:
case UCEBCDIC:
ic = atoe[' '];
break;
case IBM:
case LCIBM:
case UCIBM:
ic = atoibm[' '];
break;
}
do {
*op++ = ic;
} while (--c);
}
}
while (obc >= obs) {
op = flsh();
}
break;
}
if (--files <= 0) {
(void) flsh();
if ((close(obf) != 0) ||
(fclose(stdout) != 0)) {
perror(gettext("dd: close error"));
exit(2);
}
term(0);
} else {
continue;
}
} else if (ibc == ibs) {
nifr++;
} else {
nipr++;
if ((cflag & SYNC) && ((cflag & NERR) == 0)) {
c = ibs - ibc;
ip = ibuf + ibs;
do {
if ((conv == BLOCK) ||
(conv == UNBLOCK))
*--ip = ' ';
else
*--ip = '\0';
} while (--c);
ibc = ibs;
}
}
if (cflag & SWAB) {
ip = ibuf;
if (ibc & 1) {
ip[ibc] = 0;
}
c = ibc >> 1;
do {
ic = *ip++;
ip[-1] = *ip;
*ip++ = ic;
} while (--c);
}
ip = ibuf;
switch (conv) {
case COPY:
obc = ibc;
(void) flsh();
break;
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) {
if (c > (obs - obc)) {
c = obs - obc;
}
ibc -= c;
obc += c;
switch (conv) {
case REBLOCK:
do {
*op++ = *ip++;
} while (--c);
break;
case LCREBLOCK:
do {
*op++ = utol[*ip++];
} while (--c);
break;
case UCREBLOCK:
do {
*op++ = ltou[*ip++];
} while (--c);
break;
case NBASCII:
do {
*op++ = etoa[*ip++];
} while (--c);
break;
case LCNBASCII:
do {
*op++ = utol[etoa[*ip++]];
} while (--c);
break;
case UCNBASCII:
do {
*op++ = ltou[etoa[*ip++]];
} while (--c);
break;
case NBEBCDIC:
do {
*op++ = atoe[*ip++];
} while (--c);
break;
case LCNBEBCDIC:
do {
*op++ = atoe[utol[*ip++]];
} while (--c);
break;
case UCNBEBCDIC:
do {
*op++ = atoe[ltou[*ip++]];
} while (--c);
break;
case NBIBM:
do {
*op++ = atoibm[*ip++];
} while (--c);
break;
case LCNBIBM:
do {
*op++ = atoibm[utol[*ip++]];
} while (--c);
break;
case UCNBIBM:
do {
*op++ = atoibm[ltou[*ip++]];
} while (--c);
break;
}
if (obc >= obs) {
op = flsh();
}
}
break;
case UNBLOCK:
case LCUNBLOCK:
case UCUNBLOCK:
case ASCII:
case LCASCII:
case UCASCII:
while ((c = ibc) != 0) {
if (c > (cbs - cbc)) {
c = cbs - cbc;
}
ibc -= c;
cbc += c;
obc += c;
switch (conv) {
case UNBLOCK:
do {
*op++ = *ip++;
} while (--c);
break;
case LCUNBLOCK:
do {
*op++ = utol[*ip++];
} while (--c);
break;
case UCUNBLOCK:
do {
*op++ = ltou[*ip++];
} while (--c);
break;
case ASCII:
do {
*op++ = etoa[*ip++];
} while (--c);
break;
case LCASCII:
do {
*op++ = utol[etoa[*ip++]];
} while (--c);
break;
case UCASCII:
do {
*op++ = ltou[etoa[*ip++]];
} while (--c);
break;
}
if (cbc == cbs) {
c = cbs;
do {
if ((*--op) != ' ') {
op++;
break;
}
} while (--c);
*op++ = '\n';
obc -= cbs - c - 1;
cbc = 0;
while (obc >= obs) {
op = flsh();
}
}
}
break;
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;
if (skipf) {
do {
if ((ic = *ip++) == '\n') {
skipf = 0;
c--;
break;
}
} while (--c);
if ((ibc = c) == 0) {
continue;
}
}
if (c > (cbs - cbc + 1)) {
c = cbs - cbc + 1;
}
ibc -= c;
cbc += c;
obc += c;
switch (conv) {
case BLOCK:
do {
if ((ic = *ip++) != '\n') {
*op++ = ic;
} else {
nlflag = 1;
break;
}
} while (--c);
break;
case LCBLOCK:
do {
if ((ic = *ip++) != '\n') {
*op++ = utol[ic];
} else {
nlflag = 1;
break;
}
} while (--c);
break;
case UCBLOCK:
do {
if ((ic = *ip++) != '\n') {
*op++ = ltou[ic];
} else {
nlflag = 1;
break;
}
} while (--c);
break;
case EBCDIC:
do {
if ((ic = *ip++) != '\n') {
*op++ = atoe[ic];
} else {
nlflag = 1;
break;
}
} while (--c);
break;
case LCEBCDIC:
do {
if ((ic = *ip++) != '\n') {
*op++ = atoe[utol[ic]];
} else {
nlflag = 1;
break;
}
} while (--c);
break;
case UCEBCDIC:
do {
if ((ic = *ip++) != '\n') {
*op++ = atoe[ltou[ic]];
} else {
nlflag = 1;
break;
}
} while (--c);
break;
case IBM:
do {
if ((ic = *ip++) != '\n') {
*op++ = atoibm[ic];
} else {
nlflag = 1;
break;
}
} while (--c);
break;
case LCIBM:
do {
if ((ic = *ip++) != '\n') {
*op++ =
atoibm[utol[ic]];
} else {
nlflag = 1;
break;
}
} while (--c);
break;
case UCIBM:
do {
if ((ic = *ip++) != '\n') {
*op++ =
atoibm[ltou[ic]];
} else {
nlflag = 1;
break;
}
} while (--c);
break;
}
if (nlflag) {
ibc += c - 1;
obc += cbs - cbc;
c += cbs - cbc;
cbc = 0;
if (c > 0) {
switch (conv) {
case BLOCK:
case LCBLOCK:
case UCBLOCK:
ic = ' ';
break;
case EBCDIC:
case LCEBCDIC:
case UCEBCDIC:
ic = atoe[' '];
break;
case IBM:
case LCIBM:
case UCIBM:
ic = atoibm[' '];
break;
}
do {
*op++ = ic;
} while (--c);
}
}
else if (cbc > cbs) {
skipf = 1;
obc--;
op--;
cbc = 0;
ntrunc++;
}
while (obc >= obs) {
op = flsh();
}
}
break;
}
}
return (0);
}
static int
match(char *s)
{
char *cs;
cs = string;
while (*cs++ == *s) {
if (*s++ == '\0') {
goto true;
}
}
if (*s != '\0') {
return (0);
}
true:
cs--;
string = cs;
return (1);
}
static unsigned long long
number(long long big)
{
char *cs;
long long n;
long long cut = BIG / 10;
cs = string;
n = 0;
while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) {
n = n * 10 + *cs++ - '0';
}
for (;;) {
switch (*cs++) {
case 'Z':
n *= 1024;
case 'E':
n *= 1024;
case 'P':
n *= 1024;
case 'T':
n *= 1024;
case 'G':
n *= 1024;
case 'M':
n *= 1024;
case 'k':
n *= 1024;
continue;
case 'w':
n *= 2;
continue;
case 'b':
n *= BSIZE;
continue;
case '*':
case 'x':
string = cs;
n *= number(BIG);
case '\0':
if ((n > big) || (n < 0)) {
(void) fprintf(stderr, "dd: %s \"%llu\"\n",
gettext("argument out of range:"), n);
exit(2);
}
return (n);
default:
(void) fprintf(stderr, "dd: %s \"%s\"\n",
gettext("bad numeric argument:"), string);
exit(2);
}
}
}
static unsigned char *
flsh(void)
{
unsigned char *op, *cp;
int bc;
unsigned int oc;
if (obc) {
if (obc >= obs) {
oc = obs;
nofr++;
} else {
oc = obc;
nopr++;
}
bc = write(obf, (char *)obuf, oc);
if (bc != oc) {
if (bc < 0) {
perror("write");
} else {
(void) fprintf(stderr,
gettext("dd: unexpected short write, "
"wrote %d bytes, expected %d\n"), bc, oc);
}
term(2);
}
if (ostriden > 0 && lseek(obf, ostriden * ((off_t)obs),
SEEK_CUR) == -1) {
perror("lseek");
exit(2);
}
obc -= oc;
op = obuf;
obytes += bc;
if (obc) {
cp = obuf + obs;
bc = obc;
do {
*op++ = *cp++;
} while (--bc);
}
return (op);
}
return (obuf);
}
static void
term(int c)
{
stats(B_FALSE);
exit(c);
}
static void
stats(boolean_t main_loop)
{
hrtime_t delta = gethrtime() - startt;
double secs = delta * 1e-9;
char bps[NN_NUMBUF_SZ], hobytes[NN_NUMBUF_SZ];
boolean_t is_progress = B_FALSE;
const char *head = "";
const char *tail = "\n";
if (status_arg == DD_STATUS_NONE) {
return;
}
if (main_loop) {
if (nstats == 0 && status_arg != DD_STATUS_PROGRESS) {
return;
}
if (nstats == 0 && status_arg == DD_STATUS_PROGRESS) {
uint64_t num_secs = delta / NANOSEC;
if (num_secs <= prog_secs) {
return;
}
prog_secs = num_secs;
is_progress = B_TRUE;
if (stderr_tty) {
head = "\r";
tail = "";
}
}
if (nstats == 1) {
nstats = 0;
}
}
if (!is_progress && status_arg == DD_STATUS_PROGRESS && stderr_tty &&
progress_printed) {
(void) fputc('\n', stderr);
}
if (!is_progress) {
(void) fprintf(stderr, gettext("%llu+%llu records in\n"),
nifr, nipr);
(void) fprintf(stderr, gettext("%llu+%llu records out\n"),
nofr, nopr);
if (ntrunc) {
(void) fprintf(stderr,
gettext("%llu truncated record(s)\n"), ntrunc);
}
}
if (startt == 0 || status_arg == DD_STATUS_NOXFER)
return;
nicenum_scale((uint64_t)obytes / secs, 1, bps, sizeof (bps),
NN_UNIT_SPACE);
nicenum_scale(obytes, 1, hobytes, sizeof (hobytes), NN_UNIT_SPACE);
(void) fprintf(stderr,
gettext("%s%llu bytes (%siB) transferred in %.6f secs "
"(%siB/sec)%s"), head, obytes, hobytes, secs, bps, tail);
progress_printed = is_progress;
}