Hello, as requested in TODO, new option --total (-c) was added to df to produce grand total (in the same way as du). Proposed patch in attachment.
Kamil
From 6a688c574a03ccd7499fb9864ad9c568d29b6c5b Mon Sep 17 00:00:00 2001 From: Kamil Dudka <[EMAIL PROTECTED]> Date: Tue, 2 Sep 2008 10:13:33 +0200 Subject: [PATCH] df: new option: --total (-c) to produce grand total (in the same way as du) * src/df.c (add_uint_with_neg_flag): New function to add two integral values with separate negation flag. (show_dev): New parameter force_fsu to display numbers directly. Collect summary statistics on each printed device. (usage): Mention new option --total (-c) in --help. (main): Initialize summary on program start. Handle new option --total (-c). * doc/coreutils.texi: Mention new parameter --total (-c). * NEWS: Mention the change. * TODO: Removed completed task. --- NEWS | 3 ++ TODO | 2 - doc/coreutils.texi | 9 ++++++ src/df.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 84 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 4979dd5..9401135 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,9 @@ GNU coreutils NEWS -*- outline -*- sort accepts a new option --version-sort (-V, --sort=version), specifying that ordering is to be based on strverscmp(3). + df accepts a new option --total (-c), which produces a grand total of all + arguments after all arguments have been processed. + ** Bug fixes chcon --verbose now prints a newline after each message diff --git a/TODO b/TODO index c7b095c..c964933 100644 --- a/TODO +++ b/TODO @@ -66,8 +66,6 @@ Should printf '\0123' print "\n3"? printf: consider adapting builtins/printf.def from bash -df: add `--total' option, suggested here http://bugs.debian.org/186007 - tail: don't use xlseek; it *exits*. Instead, maybe use a macro and return nonzero. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 3a04176..c23b911 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -9692,6 +9692,15 @@ pseudo-file-systems, such as automounter entries. Scale sizes by @var{size} before printing them (@pxref{Block size}). For example, @option{-BG} prints sizes in units of 1,073,741,824 bytes. [EMAIL PROTECTED] -c [EMAIL PROTECTED] --total [EMAIL PROTECTED] -c [EMAIL PROTECTED] --total [EMAIL PROTECTED] grand total of disk size, usage and available space +Print a grand total of all arguments after all arguments have +been processed. This can be used to find out the total disk size, usage +and available space of all listed devices. + @optHumanReadable @item -H diff --git a/src/df.c b/src/df.c index 0769a1e..be08688 100644 --- a/src/df.c +++ b/src/df.c @@ -108,6 +108,12 @@ static struct mount_entry *mount_list; /* If true, print file system type as well. */ static bool print_type; +/* If true, print a grand total at the end. */ +static bool print_grand_total; + +/* Grand total data. */ +static struct fs_usage grand_fsu; + /* For long options that have no equivalent short option, use a non-character as a pseudo short option, starting with CHAR_MAX + 1. */ enum @@ -129,6 +135,7 @@ static struct option const long_options[] = {"print-type", no_argument, NULL, 'T'}, {"sync", no_argument, NULL, SYNC_OPTION}, {"no-sync", no_argument, NULL, NO_SYNC_OPTION}, + {"total", no_argument, NULL, 'c'}, {"type", required_argument, NULL, 't'}, {"exclude-type", required_argument, NULL, 'x'}, {GETOPT_HELP_OPTION_DECL}, @@ -247,6 +254,40 @@ df_readable (bool negative, uintmax_t n, char *buf, } } +/* Logical equivalence */ +#define LOG_EQ(a,b) (((a)&&(b))||(!(a)&&!(b))) + +/* Add integral value while using uintmax_t for value part and separate + negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG. + The result will be in DEST and DEST_NEG. See df_readable() to understand + how is the negation flag used. */ +static void +add_uint_with_neg_flag(uintmax_t *dest, bool *dest_neg, uintmax_t src, bool src_neg) +{ + if (LOG_EQ(*dest_neg, src_neg)) + { + *dest += src; + return; + } + + if (*dest_neg) + *dest = -*dest; + + if (src_neg) + src = -src; + + if (src < *dest) + *dest -= src; + else + { + *dest = src - *dest; + *dest_neg = src_neg; + } + + if (*dest_neg) + *dest = -*dest; +} + /* Display a space listing for the disk device with absolute file name DISK. If MOUNT_POINT is non-NULL, it is the name of the root of the file system on DISK. @@ -263,7 +304,8 @@ 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, + const struct fs_usage *force_fsu) { struct fs_usage fsu; char buf[3][LONGEST_HUMAN_READABLE + 2]; @@ -296,7 +338,9 @@ show_dev (char const *disk, char const *mount_point, if (!stat_file) stat_file = mount_point ? mount_point : disk; - if (get_fs_usage (stat_file, disk, &fsu)) + if (force_fsu) + memcpy(&fsu, force_fsu, sizeof(struct fs_usage)); + else if (get_fs_usage (stat_file, disk, &fsu)) { error (0, errno, "%s", quote (stat_file)); exit_status = EXIT_FAILURE; @@ -347,6 +391,9 @@ show_dev (char const *disk, char const *mount_point, available = fsu.fsu_ffree; negate_available = false; available_to_root = available; + + grand_fsu.fsu_files += total; + grand_fsu.fsu_ffree += available; } else { @@ -373,6 +420,12 @@ 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; + + grand_fsu.fsu_blocks += input_units * total; + grand_fsu.fsu_bfree += input_units * available_to_root; + add_uint_with_neg_flag( + &grand_fsu.fsu_bavail, &grand_fsu.fsu_bavail_top_bit_set, + input_units * available, negate_available); } used = UINTMAX_MAX; @@ -550,7 +603,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, NULL); return true; } @@ -654,7 +707,8 @@ 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, + NULL); else { /* We couldn't find the mount entry corresponding to POINT. Go ahead and @@ -665,7 +719,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, NULL); free (mp); } } @@ -694,7 +748,7 @@ 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, NULL); } /* Add FSTYPE to the list of file system types to display. */ @@ -743,6 +797,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 produce a grand total\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); @@ -794,11 +849,14 @@ main (int argc, char **argv) file_systems_processed = false; posix_format = false; exit_status = EXIT_SUCCESS; + print_grand_total = false; + bzero(&grand_fsu, sizeof(struct fs_usage)); + grand_fsu.fsu_blocksize = 1; 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; @@ -864,6 +922,10 @@ main (int argc, char **argv) add_excluded_fs_type (optarg); break; + case 'c': + print_grand_total = true; + break; + case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); @@ -959,6 +1021,9 @@ main (int argc, char **argv) else show_all_entries (); + if (print_grand_total) + show_dev("total", NULL, NULL, NULL, false, false, &grand_fsu); + if (! file_systems_processed) error (EXIT_FAILURE, 0, _("no file systems processed")); -- 1.5.4.1
_______________________________________________ Bug-coreutils mailing list [email protected] http://lists.gnu.org/mailman/listinfo/bug-coreutils
