Introduce option '--total', and '-c' for it's short name. This patch is based on the patch posted by Dennis Smit, but he didn't make further effort to revise and improve the patch.
http://lists.gnu.org/archive/html/bug-coreutils/2003-11/msg00064.html The main idea is to split a new function print_info() from show_dev(), and thus show_grand_total() can make utilization of print_info(). There are 2 main differences between this patch and Dennis': - In this patch, the totals are represented in bytes internally, and converted to output units when printing. - Dennis mistaked to take total_negate_available as type uintmax_t, and dealt with it in a wrong way. v2: - Remove global variable total_negate_available. Fix the calculation of total_available. Any comments? Signed-off-by: Shan Wei <[EMAIL PROTECTED]> Signed-off-by: Li Yucai <[EMAIL PROTECTED]> Signed-off-by: Xu Wanchao <[EMAIL PROTECTED]> Signed-off-by: Li Zefan <[EMAIL PROTECTED]> --- TODO | 2 - src/df.c | 207 +++++++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 137 insertions(+), 72 deletions(-) diff --git a/TODO b/TODO index 93f5f54..a470477 100644 --- a/TODO +++ b/TODO @@ -49,8 +49,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 - seq: give better diagnostics for invalid formats: e.g. no or too many % directives seq: consider allowing format string to contain no %-directives diff --git a/src/df.c b/src/df.c index e9c82f5..4621efc 100644 --- a/src/df.c +++ b/src/df.c @@ -40,6 +40,9 @@ #define AUTHORS \ "Torbjorn Granlund", "David MacKenzie", "Paul Eggert" +/* Convert data from one unit to byte. */ +#define TO_BYTE(num, size) ((num) * (size)) + /* Name this program was run with. */ char *program_name; @@ -69,6 +72,14 @@ static bool posix_format; /* True if a file system has been processed for output. */ static bool file_systems_processed; +/* If true, show the grand total. */ +static bool show_total; + +/* The following variables are used for storing the total statistics. */ +static uintmax_t total_total; +static uintmax_t total_available; +static uintmax_t total_available_to_root; + /* If true, invoke the `sync' system call before getting any usage data. Using this option can make df very slow, especially with many or very busy disks. Note that this may make a difference on some systems -- @@ -121,6 +132,7 @@ enum static struct option const long_options[] = { {"all", no_argument, NULL, 'a'}, + {"total", no_argument, NULL, 'c'}, {"block-size", required_argument, NULL, 'B'}, {"inodes", no_argument, NULL, 'i'}, {"human-readable", no_argument, NULL, 'h'}, @@ -249,71 +261,22 @@ df_readable (bool negative, uintmax_t n, char *buf, } } -/* 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. - If STAT_FILE is non-null, it is the name of a file within the file - system that the user originally asked for; this provides better - diagnostics, and sometimes it provides better results on networked - file systems that give different free-space results depending on - where in the file system you probe. - If FSTYPE is non-NULL, it is the type of the file system on DISK. - If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may - not be able to produce statistics in this case. - ME_DUMMY and ME_REMOTE are the mount entry flags. */ - +/* This function handles the printing of an filesystem entry.*/ static void -show_dev (char const *disk, char const *mount_point, - char const *stat_file, char const *fstype, - bool me_dummy, bool me_remote) +print_info (char const *disk, char const *mount_point, + char const *fstype, uintmax_t total, + uintmax_t available, bool negate_available, + uintmax_t available_to_root, uintmax_t input_units, + uintmax_t output_units) { - struct fs_usage fsu; char buf[3][LONGEST_HUMAN_READABLE + 2]; + uintmax_t used; int width; - int col1_adjustment = 0; int use_width; - uintmax_t input_units; - uintmax_t output_units; - uintmax_t total; - uintmax_t available; - bool negate_available; - uintmax_t available_to_root; - uintmax_t used; + int col1_adjustment = 0; bool negate_used; double pct = -1; - if (me_remote & show_local_fs) - return; - - if (me_dummy & !show_all_fs & !show_listed_fs) - return; - - if (!selected_fstype (fstype) || excluded_fstype (fstype)) - return; - - /* If MOUNT_POINT is NULL, then the file system is not mounted, and this - program reports on the file system that the special file is on. - It would be better to report on the unmounted file system, - but statfs doesn't do that on most systems. */ - if (!stat_file) - stat_file = mount_point ? mount_point : disk; - - if (get_fs_usage (stat_file, disk, &fsu)) - { - error (0, errno, "%s", quote (stat_file)); - exit_status = EXIT_FAILURE; - return; - } - - if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs) - return; - - if (! file_systems_processed) - { - file_systems_processed = true; - print_header (); - } - if (! disk) disk = "-"; /* unknown */ if (! fstype) @@ -344,11 +307,6 @@ show_dev (char const *disk, char const *mount_point, { width = 7; use_width = 5; - input_units = output_units = 1; - total = fsu.fsu_files; - available = fsu.fsu_ffree; - negate_available = false; - available_to_root = available; } else { @@ -368,13 +326,6 @@ show_dev (char const *disk, char const *mount_point, use_width = ((posix_format && ! (human_output_opts & human_autoscale)) ? 8 : 4); - input_units = fsu.fsu_blocksize; - output_units = output_block_size; - total = fsu.fsu_blocks; - available = fsu.fsu_bavail; - negate_available = (fsu.fsu_bavail_top_bit_set - & (available != UINTMAX_MAX)); - available_to_root = fsu.fsu_bfree; } used = UINTMAX_MAX; @@ -447,6 +398,114 @@ show_dev (char const *disk, char const *mount_point, } putchar ('\n'); } + +/* Prepares an filesystem entry for the print_info function and also + does the stuff for the grand total static. + If MOUNT_POINT is non-NULL, it is the name of the root of the + file system on DISK. + If STAT_FILE is non-null, it is the name of a file within the file + system that the user originally asked for; this provides better + diagnostics, and sometimes it provides better results on networked + file systems that give different free-space results depending on + where in the file system you probe. + If FSTYPE is non-NULL, it is the type of the file system on DISK. + If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may + not be able to produce statistics in this case. + ME_DUMMY and ME_REMOTE are the mount entry flags. */ + +static void +show_dev (char const *disk, char const *mount_point, + char const *stat_file, char const *fstype, + bool me_dummy, bool me_remote) +{ + struct fs_usage fsu; + uintmax_t input_units; + uintmax_t output_units; + uintmax_t total; + uintmax_t available; + bool negate_available; + uintmax_t available_to_root; + + if (me_remote & show_local_fs) + return; + + if (me_dummy & !show_all_fs & !show_listed_fs) + return; + + if (!selected_fstype (fstype) || excluded_fstype (fstype)) + return; + + /* If MOUNT_POINT is NULL, then the file system is not mounted, and this + program reports on the file system that the special file is on. + It would be better to report on the unmounted file system, + but statfs doesn't do that on most systems. */ + if (!stat_file) + stat_file = mount_point ? mount_point : disk; + + if (get_fs_usage (stat_file, disk, &fsu)) + { + error (0, errno, "%s", quote (stat_file)); + exit_status = EXIT_FAILURE; + return; + } + + if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs) + return; + + if (! file_systems_processed) + { + file_systems_processed = true; + print_header (); + } + + if (inode_format) + { + input_units = output_units = 1; + total = fsu.fsu_files; + available = fsu.fsu_ffree; + negate_available = false; + available_to_root = available; + } + else + { + input_units = fsu.fsu_blocksize; + output_units = output_block_size; + total = fsu.fsu_blocks; + available = fsu.fsu_bavail; + negate_available = (fsu.fsu_bavail_top_bit_set + & (available != UINTMAX_MAX)); + available_to_root = fsu.fsu_bfree; + } + + print_info (disk, mount_point, fstype, total, available, + negate_available, available_to_root, input_units, output_units); + + if (show_total) + { + total_total += TO_BYTE (total, input_units); + total_available += TO_BYTE (available, input_units); + total_available_to_root += TO_BYTE (available_to_root, input_units); + } +} + +/* Show a grand total statics. */ +static void +show_grand_total (void) +{ + if (inode_format) + print_info ("total", NULL, NULL, total_total, total_available, + false, total_available_to_root, 1, 1); + else + { + bool total_negate_available = false; + if (total_available > TYPE_MAXIMUM(uintmax_t)) + total_negate_available = true; + + print_info ("total", NULL, NULL, total_total, total_available, + total_negate_available, total_available_to_root, + 1, output_block_size); + } +} /* Return the root mountpoint of the file system on which FILE exists, in malloced storage. FILE_STAT should be the result of stating FILE. @@ -744,6 +803,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); fputs (_("\ -a, --all include dummy file systems\n\ + -c, --total produce a grand total\n\ -B, --block-size=SIZE use SIZE-byte blocks\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\ @@ -794,13 +854,14 @@ main (int argc, char **argv) human_output_opts = -1; print_type = false; file_systems_processed = false; + show_total = false; posix_format = false; exit_status = EXIT_SUCCESS; for (;;) { int oi = -1; - int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options, + int c = getopt_long (argc, argv, "acB:iF:hHklmPTt:vx:", long_options, &oi); if (c == -1) break; @@ -810,6 +871,9 @@ main (int argc, char **argv) case 'a': show_all_fs = true; break; + case 'c': + show_total = true; + break; case 'B': { enum strtol_error e = human_options (optarg, &human_output_opts, @@ -961,6 +1025,9 @@ main (int argc, char **argv) else show_all_entries (); + if (show_total && file_systems_processed) + show_grand_total(); + if (! file_systems_processed) error (EXIT_FAILURE, 0, _("no file systems processed")); -- 1.5.3.rc7 _______________________________________________ Bug-coreutils mailing list [email protected] http://lists.gnu.org/mailman/listinfo/bug-coreutils
