*** dd.c.orig	2003-07-31 08:04:34.000000000 +0800
--- dd.c	2003-07-31 08:07:01.000000000 +0800
***************
*** 97,102 ****
--- 97,107 ----
  /* The number of bytes in which atomic writes are done. */
  static size_t output_blocksize = 0;
  
+ /* Keeping track of verbosity: time last updated, mode, target blocks */
+ static time_t verbositime = 0;
+ static char *verbosity = NULL;
+ static unsigned long blocks = 0;
+ 
  /* Conversion buffer size, in bytes.  0 prevents conversions. */
  static size_t conversion_blocksize = 0;
  
***************
*** 301,306 ****
--- 306,312 ----
    of=FILE         write to FILE instead of stdout\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\
+   progress=type   report progress (none, count, %%/percentage, #/hashes)\n\
  "), stdout);
        fputs (HELP_OPTION_DESCRIPTION, stdout);
        fputs (VERSION_OPTION_DESCRIPTION, stdout);
***************
*** 359,364 ****
--- 365,372 ----
  print_stats (void)
  {
    char buf[2][INT_BUFSIZE_BOUND (uintmax_t)];
+   if (verbosity != NULL && * verbosity != 'n')
+     fprintf (stderr, "\r%63s\r", "");
    fprintf (stderr, _("%s+%s records in\n"),
  	   umaxtostr (r_full, buf[0]), umaxtostr (r_partial, buf[1]));
    fprintf (stderr, _("%s+%s records out\n"),
***************
*** 442,452 ****
--- 450,474 ----
  open_fd (int desired_fd, char const *filename, int options, mode_t mode)
  {
    int fd;
+   struct stat stats;
+ 
    close (desired_fd);
    fd = open (filename, options, mode);
    if (fd < 0)
      return -1;
  
+   if ((options & O_RDWR) == O_RDONLY)
+     {
+       fstat (fd, &stats);
+       if (stats.st_size == 0)
+ 	if (max_records == -1)
+ 	  blocks = 0;
+ 	else
+ 	  blocks = max_records;
+       else
+ 	blocks = stats.st_size / input_blocksize - skip_records;
+     }
+ 
    if (fd != desired_fd)
      {
        if (dup2 (fd, desired_fd) != desired_fd)
***************
*** 474,479 ****
--- 496,529 ----
    else
      w_full++;
    oc = 0;
+ 
+   if (verbosity != NULL && * verbosity != 'n')
+     {
+       time_t now;
+       now = time(NULL);
+       if (now > verbositime || w_full == blocks)
+ 	{
+ 	switch (blocks ? * verbosity : 'c')
+ 	  {
+ 	  case '%':	/* percentage */
+ 	  case 'p':
+ 	    fprintf (stderr, "\r %ld%% ", 100L * w_full / blocks);
+ 	    break;
+ 	  case '#':
+ 	  case 'h':
+ 	    fprintf (stderr, "\r [%s", 
+ 	      "############################################################" +
+ 	      59 - (int) (60L * w_full / blocks));
+ 	    break;
+ 	  default:
+ 	    if (blocks)
+ 	      fprintf (stderr, "\r %ld+%ld/%ld ", w_full, w_partial, blocks);
+ 	    else
+ 	      fprintf (stderr, "\r %ld+%ld ", w_full, w_partial);
+ 	  }
+ 	}
+       verbositime = now;
+     }
  }
  
  /* Interpret one "conv=..." option.
***************
*** 565,570 ****
--- 615,626 ----
  	output_file = val;
        else if (STREQ (name, "conv"))
  	parse_conversion (val);
+       else if (STREQ (name, "progress"))
+ 	{
+ 	  verbosity = val;
+ 	  if (* verbosity == 'h' || * verbosity == '#')
+ 	    fprintf (stderr, "\r [%60s] ", "");
+ 	}
        else
  	{
  	  int invalid = 0;
