--- ../../coreutils/src/dd.c	2007-02-10 22:48:16.000000000 +0100
+++ dd.c	2007-02-13 23:52:34.000000000 +0100
@@ -126,6 +126,33 @@ enum
     STATUS_NOXFER = 01
   };
 
+enum Display_mode
+{
+  /* Generate the default, standards-conforming, style of output:
+     $ dd if=/dev/zero of=/dev/null count=10
+     10+0 records in
+     10+0 records out  */
+  DISP_DEFAULT,
+
+  /* Generate no such output.
+     $ dd if=/dev/zero of=/dev/null count=10 display=quiet
+     $ */
+  DISP_QUIET,
+
+  /* Generate more readable output:
+       $ dd if=/dev/zero of=/dev/null count=10 display=human
+       5.0K+0 bytes in
+       5.0K+0 bytes out
+     You can also specify the display block size:
+       $ dd if=/dev/zero of=/dev/null count=10 display=human dbs=1
+       5120+0 bytes in
+       5120+0 bytes out */
+  DISP_HUMAN_READABLE
+};
+
+/* This is aimed to choose diplay type */
+static enum Display_mode display_mode = DISP_DEFAULT;
+
 /* The name this program was run with. */
 char *program_name;
 
@@ -229,6 +256,12 @@ static sig_atomic_t volatile info_signal
 /* A longest symbol in the struct symbol_values tables below.  */
 #define LONGEST_SYMBOL "fdatasync"
 
+/* Human-readable options for output.  */
+static int human_output_opts;
+
+/* The units to use when printing sizes.  */
+static uintmax_t display_block_size;
+
 /* A symbol and the corresponding integer value.  */
 struct symbol_value
 {
@@ -424,6 +457,18 @@ Copy a file, converting and formatting a
   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\
+  display=MODE    uses display mode according to MODE\n\
+  dbs=SIZE        uses SIZE-byte blocks to display statistics\n\
+"), stdout);
+      fputs (_("\
+MODE may be:\n\
+  quiet          do not display statistics\n\
+  human          display statistics in a human readable format\n\
+\n\
+SIZE may be:\n\
+  human          prints all sizes in human readable format (e.g. 1K, 234M)\n\
+  si             likewise, but uses powers of 1000 instead of 1024\n\
+  BYTES          likewise, but use powers of BYTES\n\
 "), stdout);
       fputs (_("\
 \n\
@@ -530,6 +575,37 @@ multiple_bits_set (int i)
   return (i & (i - 1)) != 0;
 }
 
+static void
+print_human_stats (void)
+{
+  char display_buf[5][MAX (LONGEST_HUMAN_READABLE + 1,
+			   INT_BUFSIZE_BOUND (uintmax_t))];
+
+  fprintf (stderr, _("%s+%s bytes in\n"),
+	   human_readable (r_full, display_buf[0], human_output_opts,
+			   input_blocksize, display_block_size),
+	   human_readable (r_partial, display_buf[1], human_output_opts,
+			   input_blocksize, display_block_size));
+
+  fprintf (stderr, _("%s+%s bytes out\n"),
+	   human_readable (w_full, display_buf[2],  human_output_opts,
+			   output_blocksize , display_block_size),
+	   human_readable (w_partial, display_buf[3], human_output_opts,
+			   output_blocksize, display_block_size));
+
+  if (0 < r_truncate)
+    {
+      fprintf (stderr, "%s %s\n",
+	       human_readable (r_truncate, display_buf[4],
+			       human_output_opts, output_blocksize,
+			       display_block_size),
+	       (r_truncate == 1
+		? _("truncated record")
+		: _("truncated records")));
+    }
+}
+
+
 /* Print transfer statistics.  */
 
 static void
@@ -537,25 +613,29 @@ print_stats (void)
 {
   xtime_t now = gethrxtime ();
   char hbuf[LONGEST_HUMAN_READABLE + 1];
-  int human_opts =
-    (human_autoscale | human_round_to_nearest
-     | human_space_before_unit | human_SI | human_B);
+  
   double delta_s;
   char const *bytes_per_second;
 
-  fprintf (stderr,
-	   _("%"PRIuMAX"+%"PRIuMAX" records in\n"
-	     "%"PRIuMAX"+%"PRIuMAX" records out\n"),
-	   r_full, r_partial, w_full, w_partial);
-
-  if (r_truncate != 0)
-    fprintf (stderr,
-	     ngettext ("%"PRIuMAX" truncated record\n",
-		       "%"PRIuMAX" truncated records\n",
-		       select_plural (r_truncate)),
-	     r_truncate);
+  if (display_mode == DISP_HUMAN_READABLE)
+    {
+      print_human_stats ();
+    }
+  else if (display_mode == DISP_DEFAULT)
+    {
+      fprintf (stderr,
+	       _("%"PRIuMAX"+%"PRIuMAX" records in\n"
+		 "%"PRIuMAX"+%"PRIuMAX" records out\n"),
+	       r_full, r_partial, w_full, w_partial);
 
-  if (status_flags & STATUS_NOXFER)
+      if (r_truncate != 0)
+	fprintf (stderr,
+		 ngettext ("%"PRIuMAX" truncated record\n",
+			   "%"PRIuMAX" truncated records\n",
+			   select_plural (r_truncate)),
+		 r_truncate);
+    }
+  if ((status_flags & STATUS_NOXFER) | display_mode == DISP_QUIET)
     return;
 
   /* Use integer arithmetic to compute the transfer rate,
@@ -566,7 +646,7 @@ print_stats (void)
 		     "%"PRIuMAX" bytes (%s) copied",
 		     select_plural (w_bytes)),
 	   w_bytes,
-	   human_readable (w_bytes, hbuf, human_opts, 1, 1));
+	   human_readable (w_bytes, hbuf, human_output_opts, 1, 1));
 
   if (start_time < now)
     {
@@ -574,7 +654,7 @@ print_stats (void)
       uintmax_t delta_xtime = now;
       delta_xtime -= start_time;
       delta_s = delta_xtime / XTIME_PRECISIONe0;
-      bytes_per_second = human_readable (w_bytes, hbuf, human_opts,
+      bytes_per_second = human_readable (w_bytes, hbuf, human_output_opts,
 					 XTIME_PRECISION, delta_xtime);
     }
   else
@@ -904,6 +984,26 @@ scanargs (int argc, char **argv)
       else if (STREQ (name, "status"))
 	status_flags |= parse_symbols (val, statuses,
 				       N_("invalid status flag: %s"));
+      else if (STREQ (name, "display")) /* select display mode */
+	{
+	  if (STREQ (val, "human"))
+	    {
+	      display_mode = DISP_HUMAN_READABLE;
+	      human_output_opts = human_autoscale | human_SI | human_base_1024;
+	      display_block_size = 1;
+	    }
+	  else if (STREQ (val, "quiet"))
+	    {
+	      display_mode = DISP_QUIET;
+	    }
+	  else
+	    {
+	      error (0, 0, _("unrecognized display= argument %s"), quote (val));
+	      usage (EXIT_FAILURE);
+	    }
+	}
+      else if (STREQ (name, "dbs")) /* select display block size */
+	human_output_opts = human_options (val, true, &display_block_size);
       else
 	{
 	  bool invalid = false;
@@ -1650,6 +1750,13 @@ main (int argc, char **argv)
   if (getopt_long (argc, argv, "", NULL, NULL) != -1)
     usage (EXIT_FAILURE);
 
+  if (getenv ("DD_DISPLAY_BLOCK_SIZE"))
+    human_output_opts = human_options (getenv ("DD_DISPLAY_BLOCK_SIZE"),
+				       false, &display_block_size);
+  else
+    human_output_opts = (human_autoscale | human_round_to_nearest
+			 | human_space_before_unit | human_SI | human_B);
+
   /* Initialize translation table to identity translation. */
   for (i = 0; i < 256; i++)
     trans_table[i] = i;
