Subject: Re: bug#12489: inconsistent output from 'dd' w/rt stats and suppression.
From: Pádraig Brady <[email-masked]>
To: [email-masked]
Cc: [email-masked], Linda Walsh <[email-masked]>
Date: Mon, 24 Sep 2012 03:47:25 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

On 09/23/2012 12:12 PM, Pádraig Brady wrote:
> I think there was general consensus that the status=noinfo should be applied
> http://lists.gnu.org/archive/html/bug-coreutils/2010-02/msg00159.html
>
> I'll look at that this evening.

I changed things a bit in the attached patch.
I used 'status=none' rather than 'status=noinfo',
to make it obvious all stderr messages were being suppressed.
Also, I kept the bitmask nature of the existing code
to make it more consistent and extendible.

cheers,
Pádraig.
From 3aa3181556f94567b29004f783523be3a76e2957 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pozs=C3=A1r=20Bal=C3=A1zs?= <[email-masked]>
Date: Mon, 24 Sep 2012 02:39:09 +0100
Subject: [PATCH] dd: add support for status=none to suppress all info to
 stderr

* src/dd.c (STATUS_NONE): A new bitmask combining all STATUS_
options, thus used to suppress all informational output.
(struct symbol_value statuses): Expose the "none" option,
corresponding to the STATUS_NONE bitmask above.
(print_stats): Return early if STATUS_NONE is specified.
Also move the call to gethrxtime() down so that it's only
called when needed.
(usage): Describe the new options.
* doc/coreutils.texi (dd invocation): Likewise.
* NEWS: Mention the new feature.
* tests/dd/misc.sh: Ensure the new option works.
---
 NEWS               |    2 ++
 doc/coreutils.texi |   20 +++++++++++++++++---
 src/dd.c           |   14 +++++++++++---
 tests/dd/misc.sh   |    7 +++++++
 4 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/NEWS b/NEWS
index 9bd5d58..edc436c 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** New features
 
+  dd now accepts 'status=none' to suppress all informational output.
+
   md5sum now accepts the --tag option to print BSD-style output with GNU
   file name escaping.  This also affects sha1sum, sha224sum, sha256sum,
   sha384sum and sha512sum.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index c0abd7f..31d9804 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -8115,10 +8115,24 @@ of everything until the end of the file.
 if @samp{iflag=count_bytes} is specified, @var{n} is interpreted
 as a byte count rather than a block count.
 
-@item status=noxfer
+@item status=@var{which}
 @opindex status
-Do not print the overall transfer rate and volume statistics
-that normally make up the third status line when @command{dd} exits.
+Transfer information is normally output to stderr upon
+receipt of the @samp{INFO} signal or when @command{dd} exits.
+Specifying @var{which} will identify which information to suppress.
+
+@table @samp
+
+@item noxfer
+@opindex noxfer
+Do not print the transfer rate and volume statistics
+that normally make up the last status line.
+
+@item none
+@opindex none
+Do not print any informational messages to stderr.
+
+@end table
 
 @item conv=@var{conversion}[,@var{conversion}]@dots{}
 @opindex conv
diff --git a/src/dd.c b/src/dd.c
index de51435..b613fcf 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -135,7 +135,10 @@ enum
 /* Status bit masks.  */
 enum
   {
-    STATUS_NOXFER = 01
+    STATUS_NOXFER = 01,
+    STATUS_NOCOUNTS = 02,
+    STATUS_LAST = STATUS_NOCOUNTS,
+    STATUS_NONE = STATUS_LAST | (STATUS_LAST - 1)
   };
 
 /* The name of the input file, or NULL for the standard input. */
@@ -370,6 +373,7 @@ static struct symbol_value const flags[] =
 static struct symbol_value const statuses[] =
 {
   {"noxfer",	STATUS_NOXFER},
+  {"none",	STATUS_NONE},
   {"",		0}
 };
 
@@ -536,7 +540,8 @@ Copy a file, converting and formatting according to the operands.\n\
   oflag=FLAGS     write as per the comma separated symbol list\n\
   seek=N          skip N obs-sized blocks at start of output\n\
   skip=N          skip N ibs-sized blocks at start of input\n\
-  status=noxfer   suppress transfer statistics\n\
+  status=WHICH    WHICH info to suppress outputting to stderr;\n\
+                  'noxfer' suppresses transfer stats, 'none' suppresses all\n\
 "), stdout);
       fputs (_("\
 \n\
@@ -664,7 +669,6 @@ multiple_bits_set (int i)
 static void
 print_stats (void)
 {
-  xtime_t now = gethrxtime ();
   char hbuf[LONGEST_HUMAN_READABLE + 1];
   int human_opts =
     (human_autoscale | human_round_to_nearest
@@ -672,6 +676,9 @@ print_stats (void)
   double delta_s;
   char const *bytes_per_second;
 
+  if ((status_flags & STATUS_NONE) == STATUS_NONE)
+    return;
+
   fprintf (stderr,
            _("%"PRIuMAX"+%"PRIuMAX" records in\n"
              "%"PRIuMAX"+%"PRIuMAX" records out\n"),
@@ -697,6 +704,7 @@ print_stats (void)
            w_bytes,
            human_readable (w_bytes, hbuf, human_opts, 1, 1));
 
+  xtime_t now = gethrxtime ();
   if (start_time < now)
     {
       double XTIME_PRECISIONe0 = XTIME_PRECISION;
diff --git a/tests/dd/misc.sh b/tests/dd/misc.sh
index 9a9bba1..f029a11 100755
--- a/tests/dd/misc.sh
+++ b/tests/dd/misc.sh
@@ -30,6 +30,13 @@ echo data > $tmp_in || framework_failure_
 ln $tmp_in $tmp_in2 || framework_failure_
 ln -s $tmp_in $tmp_sym || framework_failure_
 
+# check status=none suppresses all output to stderr
+dd status=none if=$tmp_in of=/dev/null 2> err || fail=1
+test -s err && fail=1
+# check status=none is cumulative with status=noxfer
+dd status=none status=noxfer if=$tmp_in of=/dev/null 2> err || fail=1
+test -s err && fail=1
+
 dd if=$tmp_in of=$tmp_out 2> /dev/null || fail=1
 compare $tmp_in $tmp_out || fail=1
 
-- 
1.7.6.4