summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dd.c99
1 files changed, 68 insertions, 31 deletions
diff --git a/src/dd.c b/src/dd.c
index 19014a752..e4f6f1e59 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -74,23 +74,36 @@
#define MAX_BLOCKSIZE MIN (SIZE_MAX, MIN (SSIZE_MAX, OFF_T_MAX))
/* Conversions bit masks. */
-#define C_ASCII 01
-#define C_EBCDIC 02
-#define C_IBM 04
-#define C_BLOCK 010
-#define C_UNBLOCK 020
-#define C_LCASE 040
-#define C_UCASE 0100
-#define C_SWAB 0200
-#define C_NOERROR 0400
-#define C_NOTRUNC 01000
-#define C_SYNC 02000
-/* Use separate input and output buffers, and combine partial input blocks. */
-#define C_TWOBUFS 04000
-#define C_NOCREAT 010000
-#define C_EXCL 020000
-#define C_FDATASYNC 040000
-#define C_FSYNC 0100000
+enum
+ {
+ C_ASCII = 01,
+
+ C_EBCDIC = 02,
+ C_IBM = 04,
+ C_BLOCK = 010,
+ C_UNBLOCK = 020,
+ C_LCASE = 040,
+ C_UCASE = 0100,
+ C_SWAB = 0200,
+ C_NOERROR = 0400,
+ C_NOTRUNC = 01000,
+ C_SYNC = 02000,
+
+ /* Use separate input and output buffers, and combine partial
+ input blocks. */
+ C_TWOBUFS = 04000,
+
+ C_NOCREAT = 010000,
+ C_EXCL = 020000,
+ C_FDATASYNC = 040000,
+ C_FSYNC = 0100000
+ };
+
+/* Status bit masks. */
+enum
+ {
+ STATUS_NOXFER = 01
+ };
/* The name this program was run with. */
char *program_name;
@@ -126,6 +139,9 @@ static int conversions_mask = 0;
static int input_flags = 0;
static int output_flags = 0;
+/* Status flags for what is printed to stderr. */
+static int status_flags = 0;
+
/* If nonzero, filter characters through the translation table. */
static bool translation_needed = false;
@@ -220,6 +236,13 @@ static struct symbol_value const flags[] =
{"", 0}
};
+/* Status, for status="...". */
+static struct symbol_value const statuses[] =
+{
+ {"noxfer", STATUS_NOXFER},
+ {"", 0}
+};
+
/* Translation table formed by applying successive transformations. */
static unsigned char trans_table[256];
@@ -361,6 +384,7 @@ Copy a file, converting and formatting according to the operands.\n\
oflag=FLAGS write as per the comma separated symbol list\n\
seek=BLOCKS skip BLOCKS obs-sized blocks at start of output\n\
skip=BLOCKS skip BLOCKS ibs-sized blocks at start of input\n\
+ status=noxfer suppress transfer statistics\n\
"), stdout);
fputs (_("\
\n\
@@ -414,9 +438,9 @@ print I/O statistics to standard error, then to resume copying.\n\
\n\
$ dd if=/dev/zero of=/dev/null& pid=$!\n\
$ kill -USR1 $pid; sleep 1; kill $pid\n\
- 10807656+0 records in\n\
- 10807656+0 records out\n\
- 5.5GB copied in 20.8225s (266MB/s)\n\
+ 18335302+0 records in\n\
+ 18335302+0 records out\n\
+ 9387674624 bytes (9.4 GB) copied, 34.6279 seconds, 271 MB/s\n\
\n\
Options are:\n\
\n\
@@ -452,9 +476,11 @@ print_stats (void)
char buf[2][MAX (INT_BUFSIZE_BOUND (uintmax_t), LONGEST_HUMAN_READABLE + 1)];
struct timespec now;
int human_opts =
- human_autoscale | human_round_to_nearest | human_SI | human_B;
+ (human_autoscale | human_round_to_nearest
+ | human_space_before_unit | human_SI | human_B);
uintmax_t start_sec = start_time.tv_sec;
enum { BILLION = 1000000000 };
+ double BILLIONe0 = BILLION;
double delta_s;
char const *bytes_per_second;
@@ -472,10 +498,19 @@ print_stats (void)
: _("truncated records")));
}
+ if (status_flags & STATUS_NOXFER)
+ return;
+
/* Use integer arithmetic to compute the transfer rate if possible,
since that makes it easy to use SI abbreviations; otherwise, fall
back on floating-point without abbreviations. */
+ fprintf (stderr,
+ ngettext ("%s byte (%s) copied",
+ "%s bytes (%s) copied", w_bytes == 1),
+ umaxtostr (w_bytes, buf[0]),
+ human_readable (w_bytes, buf[1], human_opts, 1, 1));
+
if ((start_time.tv_sec < now.tv_sec
|| (start_time.tv_sec == now.tv_sec
&& start_time.tv_nsec < now.tv_nsec))
@@ -483,7 +518,7 @@ print_stats (void)
{
uintmax_t delta_ns = (BILLION * (now.tv_sec - start_sec)
+ now.tv_nsec - start_time.tv_nsec);
- delta_s = delta_ns / 1e9;
+ delta_s = delta_ns / BILLIONe0;
bytes_per_second = human_readable (w_bytes, buf[1], human_opts,
BILLION, delta_ns);
}
@@ -491,7 +526,7 @@ print_stats (void)
{
delta_s = now.tv_sec;
delta_s -= start_time.tv_sec;
- delta_s += 1e-9 * (now.tv_nsec - start_time.tv_nsec);
+ delta_s += (now.tv_nsec - start_time.tv_nsec) / BILLIONe0;
if (0 < delta_s)
sprintf (buf[1], "%gB", w_bytes / delta_s);
else
@@ -499,8 +534,9 @@ print_stats (void)
bytes_per_second = buf[1];
}
- fprintf (stderr, _("%s copied in %gs (%s/s)\n"),
- human_readable (w_bytes, buf[0], human_opts, 1, 1),
+ fprintf (stderr,
+ ngettext (", %g second, %s/s\n",
+ ", %g seconds, %s/s\n", delta_s == 1),
delta_s, bytes_per_second);
}
@@ -608,10 +644,6 @@ write_output (void)
oc = 0;
}
-/* Diagnostics for invalid iflag="..." and oflag="..." symbols. */
-static char const iflag_error_msgid[] = N_("invalid input flag: %s");
-static char const oflag_error_msgid[] = N_("invalid output flag: %s");
-
/* Interpret one "conv=..." or similar operand STR according to the
symbols in TABLE, returning the flags specified. If the operand
cannot be parsed, use ERROR_MSGID to generate a diagnostic.
@@ -709,9 +741,14 @@ scanargs (int argc, char **argv)
conversions_mask |= parse_symbols (val, conversions,
N_("invalid conversion: %s"));
else if (STREQ (name, "iflag"))
- input_flags |= parse_symbols (val, flags, iflag_error_msgid);
+ input_flags |= parse_symbols (val, flags,
+ N_("invalid input flag: %s"));
else if (STREQ (name, "oflag"))
- output_flags |= parse_symbols (val, flags, oflag_error_msgid);
+ output_flags |= parse_symbols (val, flags,
+ N_("invalid output flag: %s"));
+ else if (STREQ (name, "status"))
+ status_flags |= parse_symbols (val, statuses,
+ N_("invalid status flag: %s"));
else
{
bool invalid = false;