Everyone needs a --total option.

The patch I've attached has undetected overflow issues.  I'm sure it
needs to be cleaned up a little, but I'm not sure how to do it.  Maybe
by detecting whether the total just summed is less than the thing
added to it.  It works on my system with my sub-terabyte levels of
disk storage, though.

Also, I used -o as the short form.  I'm not sure whether POSIX has a
problem with that.
--- orig/coreutils-5.0/src/df.c 2003-03-04 16:07:53.000000000 -0500
+++ coreutils-5.0/src/df.c      2003-07-13 13:52:01.000000000 -0400
@@ -115,6 +115,14 @@
 /* If nonzero, print filesystem type as well.  */
 static int print_type;
 
+/* If nonzero, print a total line at the end. */
+static int grand_total;
+
+/* Totals for the grand_total option. */
+static uintmax_t total_blocks;
+static uintmax_t total_used;
+static uintmax_t total_avail;
+
 /* For long options that have no equivalent short option, use a
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
 enum
@@ -139,6 +147,7 @@
   {"no-sync", no_argument, NULL, NO_SYNC_OPTION},
   {"type", required_argument, NULL, 't'},
   {"exclude-type", required_argument, NULL, 'x'},
+  {"total", no_argument, NULL, 'o'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -373,6 +382,14 @@
        }
     }
 
+  if (grand_total)
+    {
+      total_blocks += total * input_units;
+      total_used += (negate_used ? -used : used) * input_units;
+      total_avail +=
+       (negate_available ? -available : available) * input_units;
+    }
+
   printf (" %*s %*s %*s ",
          width, df_readable (0, total,
                              buf[0], input_units, output_units),
@@ -774,8 +791,13 @@
   print_type = 0;
   posix_format = 0;
   exit_status = 0;
+  grand_total = 0;
+  total_blocks = 0;
+  total_used = 0;
+  total_avail = 0;
 
-  while ((c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options, NULL))
+  while ((c = getopt_long (argc, argv, "aB:iF:hHklmoPTt:vx:", long_options,
+                          NULL))
         != -1)
     {
       switch (c)
@@ -810,6 +832,9 @@
          human_output_opts = 0;
          output_block_size = 1024 * 1024;
          break;
+       case 'o':
+         grand_total = 1;
+         break;
        case 'T':
          print_type = 1;
          break;
@@ -929,5 +954,70 @@
          show_entry (argv[i], &stats[i - optind]);
     }
 
+  if (grand_total)
+    {
+      int width;
+      int use_width;
+      uintmax_t output_units;
+      double pct = -1;
+      char buf[3][LONGEST_HUMAN_READABLE + 2];
+
+      if (inode_format)
+       {
+         width = 7;
+         use_width = 5;
+         output_units = 1;
+       }
+      else
+       {
+         width = (human_output_opts & human_autoscale
+                  ? 5 + ! (human_output_opts & human_base_1024)
+                  : 9);
+         use_width = ((posix_format
+                       && ! (human_output_opts & human_autoscale))
+                      ? 8 : 4);
+         output_units = output_block_size;
+       }
+
+      printf ("%-20s", "total");
+      printf (" %*s %*s %*s ",
+             width, df_readable (0, total_blocks, buf[0], 1, output_units),
+             width, df_readable (0, total_used, buf[1], 1, output_units),
+             width, df_readable (0, total_avail, buf[2], 1, output_units));
+
+      if (total_used <= TYPE_MAXIMUM (uintmax_t) / 100
+         && total_used + total_avail != 0
+         && total_avail >= 0)
+       {
+         uintmax_t u100 = total_used * 100;
+         uintmax_t nonroot_total = total_used + total_avail;
+         pct = u100 / nonroot_total + (u100 % nonroot_total != 0);
+       }
+      else
+       {
+         double u = total_used;
+         double a = total_avail;
+         double nonroot_total = u + a;
+         if (nonroot_total)
+           {
+             double ipct;
+             pct = u * 100 / nonroot_total;
+             ipct = (long) pct;
+
+             /* Like `pct = ceil (dpct);', but avoid ceil so that
+                the math library needn't be linked.  */
+             if (ipct - 1 < pct && pct <= ipct + 1)
+               pct = ipct + (ipct < pct);
+           }
+       }
+
+      if (0 <= pct)
+       printf ("%*.0f%%", use_width - 1, pct);
+      else
+       printf ("%*s", use_width, "- ");
+
+      printf ("\n");
+    }
+
   exit (exit_status);
 }
_______________________________________________
Bug-coreutils mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/bug-coreutils

Reply via email to