Given that the attached patch works, except that the SIZE argument specified to -B/--block-size parameter doesn't currently make it into the totals, I'd like to hear some opinions how you would make it happen (I have some ideas, but I'd certainly prefer to have some peer- driven effort).
Steven Schubiger diff --git a/src/df.c b/src/df.c index f0fdcd7..e010f87 100644 --- a/src/df.c +++ b/src/df.c @@ -46,6 +46,20 @@ char *program_name; /* If true, show inode information. */ static bool inode_format; +/* If true, output disk "usage" summary. */ +static bool summarize_total; + +/* The summary container. */ +struct summary_total +{ + unsigned long blocks; + unsigned long used; + unsigned long avail; + int spacing; + int width; + int adjustment; +} summary; + /* If true, show even file systems with zero size or uninteresting types. */ static bool show_all_fs; @@ -122,6 +136,7 @@ static struct option const long_options[] = { {"all", no_argument, NULL, 'a'}, {"block-size", required_argument, NULL, 'B'}, + {"total", no_argument, NULL, 'c' }, {"inodes", no_argument, NULL, 'i'}, {"human-readable", no_argument, NULL, 'h'}, {"si", no_argument, NULL, 'H'}, @@ -226,6 +241,17 @@ excluded_fstype (const char *fstype) return false; } +static int +integer_length (unsigned long num) +{ + int length = 1; + while ((num /= 10) >= 1) + { + length++; + } + return length; +} + /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS), except: @@ -265,7 +291,7 @@ df_readable (bool negative, uintmax_t n, char *buf, static void show_dev (char const *disk, char const *mount_point, char const *stat_file, char const *fstype, - bool me_dummy, bool me_remote) + bool me_dummy, bool me_remote, bool show_summary) { struct fs_usage fsu; char buf[3][LONGEST_HUMAN_READABLE + 2]; @@ -281,6 +307,10 @@ show_dev (char const *disk, char const *mount_point, uintmax_t used; bool negate_used; double pct = -1; + char *buf_readable[3]; + + if (show_summary) + goto output_numbers; if (me_remote & show_local_fs) return; @@ -326,18 +356,33 @@ show_dev (char const *disk, char const *mount_point, size_t disk_name_len = strlen (disk); size_t fstype_len = strlen (fstype); if (disk_name_len + fstype_len < 18) - printf ("%s%*s ", disk, 18 - (int) disk_name_len, fstype); + { + printf ("%s%*s ", disk, 18 - (int) disk_name_len, fstype); + summary.spacing = disk_name_len + (18 - (int) disk_name_len + 2); + } else if (!posix_format) - printf ("%s\n%18s ", disk, fstype); + { + printf ("%s\n%18s ", disk, fstype); + summary.spacing = 20; + } else - printf ("%s %s", disk, fstype); + { + printf ("%s %s", disk, fstype); + summary.spacing = disk_name_len + 1 + fstype_len; + } } else { if (strlen (disk) > 20 && !posix_format) - printf ("%s\n%20s", disk, ""); + { + printf ("%s\n%20s", disk, ""); + summary.spacing = 20; + } else - printf ("%-20s", disk); + { + printf ("%-20s", disk); + summary.spacing = 20; + } } if (inode_format) @@ -375,6 +420,7 @@ show_dev (char const *disk, char const *mount_point, negate_available = (fsu.fsu_bavail_top_bit_set & (available != UINTMAX_MAX)); available_to_root = fsu.fsu_bfree; + } used = UINTMAX_MAX; @@ -384,15 +430,33 @@ show_dev (char const *disk, char const *mount_point, used = total - available_to_root; negate_used = (total < available_to_root); } - - printf (" %*s %*s %*s ", - width + col1_adjustment, - df_readable (false, total, - buf[0], input_units, output_units), - width, df_readable (negate_used, used, - buf[1], input_units, output_units), - width, df_readable (negate_available, available, - buf[2], input_units, output_units)); + + output_numbers: + if (!show_summary) + { + buf_readable[0] = (char *) df_readable (false, total, buf[0], input_units, output_units); + buf_readable[1] = (char *) df_readable (negate_used, used, buf[1], input_units, output_units); + buf_readable[2] = (char *) df_readable (negate_available, available, buf[2], input_units, output_units); + printf (" %*s %*s %*s ", + width + col1_adjustment, buf_readable[0], + width, buf_readable[1], + width, buf_readable[2]); + summary.blocks += atol (buf_readable[0]); + summary.used += atol (buf_readable[1]); + summary.avail += atol (buf_readable[2]); + summary.width = width; + summary.adjustment = col1_adjustment; + } + else + { + printf ("%*s %*s%lu %*s%lu %*s%lu ", + summary.spacing, "", + (summary.width + summary.adjustment) - integer_length (summary.blocks), "", summary.blocks, + summary.width - integer_length (summary.used), "", summary.used, + summary.width - integer_length (summary.avail), "", summary.avail); + putchar ('\n'); + return; + } if (used == UINTMAX_MAX || available == UINTMAX_MAX) ; @@ -552,7 +616,7 @@ show_disk (char const *disk) { show_dev (best_match->me_devname, best_match->me_mountdir, NULL, best_match->me_type, best_match->me_dummy, - best_match->me_remote); + best_match->me_remote, false); return true; } @@ -656,7 +720,7 @@ show_point (const char *point, const struct stat *statp) if (best_match) show_dev (best_match->me_devname, best_match->me_mountdir, point, - best_match->me_type, best_match->me_dummy, best_match->me_remote); + best_match->me_type, best_match->me_dummy, best_match->me_remote, false); else { /* We couldn't find the mount entry corresponding to POINT. Go ahead and @@ -667,7 +731,7 @@ show_point (const char *point, const struct stat *statp) char *mp = find_mount_point (point, statp); if (mp) { - show_dev (NULL, mp, NULL, NULL, false, false); + show_dev (NULL, mp, NULL, NULL, false, false, false); free (mp); } } @@ -696,7 +760,13 @@ show_all_entries (void) for (me = mount_list; me; me = me->me_next) show_dev (me->me_devname, me->me_mountdir, NULL, me->me_type, - me->me_dummy, me->me_remote); + me->me_dummy, me->me_remote, false); +} + +static void +show_summary (void) +{ + show_dev (NULL, NULL, NULL, NULL, NULL, NULL, true); } /* Add FSTYPE to the list of file system types to display. */ @@ -745,6 +815,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\ fputs (_("\ -a, --all include dummy file systems\n\ -B, --block-size=SIZE use SIZE-byte blocks\n\ + -c, --total summarize disk usage\n\ -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\ -H, --si likewise, but use powers of 1000 not 1024\n\ "), stdout); @@ -791,6 +862,7 @@ main (int argc, char **argv) inode_format = false; show_all_fs = false; show_listed_fs = false; + summarize_total = false; human_output_opts = -1; print_type = false; file_systems_processed = false; @@ -800,7 +872,7 @@ main (int argc, char **argv) for (;;) { int oi = -1; - int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options, + int c = getopt_long (argc, argv, "aB:ciF:hHklmPTt:vx:", long_options, &oi); if (c == -1) break; @@ -818,6 +890,9 @@ main (int argc, char **argv) xstrtol_fatal (e, oi, c, long_options, optarg); } break; + case 'c': + summarize_total = true; + break; case 'i': inode_format = true; break; @@ -964,5 +1039,8 @@ main (int argc, char **argv) if (! file_systems_processed) error (EXIT_FAILURE, 0, _("no file systems processed")); + if (summarize_total) + show_summary (); + exit (exit_status); } _______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils