I had a glance at the TODO list and saw that df -mP had an alignment bug so i fixed that. Also i saw that an --total option was requested so did that as well.
I hope i did it alright, if not please make me know so that i can improve my work. Also i would like to do some more work on df or possibly other things. ChangeLog: * src/df.c (print_header): fixt alignment for `df -mP'. (main): added support for -c --total. (show_grand_total): added function to show the grand total. (show_information): added function splitted this from show_dev so the grand_total can use the same entry displaying function. (convert_blocksize): added function that converts the blocksize for the grandtotal so that only the same blocksize amounts are added to each other. Is this function right ? (took from human_readable). (show_dev): splitted out the show_information part and added support for grand total option. PATCH: --- df.c 2003-11-07 07:18:30.000000000 +0100 +++ df_new.c 2003-11-07 23:28:24.000000000 +0100 @@ -17,7 +17,8 @@ /* Written by David MacKenzie <[EMAIL PROTECTED]>. --human-readable and --megabyte options added by [EMAIL PROTECTED] - --si and large file support added by [EMAIL PROTECTED] */ + --si and large file support added by [EMAIL PROTECTED] + --total added by [EMAIL PROTECTED] */ #include <config.h> #include <stdio.h> @@ -57,6 +58,9 @@ /* If nonzero, show only local filesystems. */ static int show_local_fs; +/* If nonzero, show a grand total. */ +static int show_total; + /* If nonzero, output data for each filesystem corresponding to a command line argument -- even if it's a dummy (automounter) entry. */ static int show_listed_fs; @@ -111,6 +115,12 @@ /* If nonzero, print filesystem type as well. */ static int print_type; +/* The following variables are used for generating a total static. */ +static uintmax_t total_total; +static uintmax_t total_available; +static uintmax_t total_negate_available; +static uintmax_t total_available_to_root; + /* For long options that have no equivalent short option, use a non-character as a pseudo short option, starting with CHAR_MAX + 1. */ enum @@ -128,6 +138,7 @@ {"si", no_argument, NULL, 'H'}, {"kilobytes", no_argument, NULL, 'k'}, /* long form is obsolescent */ {"local", no_argument, NULL, 'l'}, + {"total", no_argument, NULL, 'c'}, {"megabytes", no_argument, NULL, 'm'}, /* obsolescent */ {"portability", no_argument, NULL, 'P'}, {"print-type", no_argument, NULL, 'T'}, @@ -160,7 +171,7 @@ printf (_(" Size Used Avail Use%%")); } else if (posix_format) - printf (_(" %4s-blocks Used Available Capacity"), + printf (_(" %3s-blocks Used Available Capacity"), umaxtostr (output_block_size, buf)); else { @@ -253,62 +264,85 @@ } } -/* Display a space listing for the disk device with absolute path DISK. +/* This function is used to convert data from one blocksize to another */ +uintmax_t convert_blocksize (uintmax_t n, uintmax_t from_block_size, + uintmax_t to_block_size) +{ + if (from_block_size >= to_block_size && + from_block_size % to_block_size) + { + uintmax_t multiplier = from_block_size / to_block_size; + return n * multiplier; + } + else if (from_block_size != 0 && to_block_size % from_block_size == 0) + { + uintmax_t divisor = to_block_size / from_block_size; + return n / divisor; + } + else + { + /* Either the result cannot be computed easily using uintmax_t, + or from_block_size is zero. Fall back on floating point. + This can yield answers that are slightly off. */ + return n * (from_block_size / (long double) to_block_size); + } +} + +/* This function handles the printing of an filesystem entry. + The reason for the split between show_information and + show_dev is so that the -c --total option can make use + of this function to print it's information like the + filesystem entries. If MOUNT_POINT is non-NULL, it is the path of the root of the filesystem on DISK. If FSTYPE is non-NULL, it is the type of the filesystem 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. */ + not be able to produce statistics in this case. */ static void -show_dev (const char *disk, const char *mount_point, const char *fstype, - int me_dummy, int me_remote) +show_information (const char *disk, const char *mount_point, + const char *fstype, uintmax_t total, + uintmax_t available, uintmax_t negate_available, + uintmax_t available_to_root, + uintmax_t input_units, uintmax_t output_units) { - struct fs_usage fsu; - const char *stat_file; char buf[3][LONGEST_HUMAN_READABLE + 2]; int width; int use_width; - uintmax_t input_units; - uintmax_t output_units; - uintmax_t total; - uintmax_t available; - int negate_available; - uintmax_t available_to_root; - uintmax_t used; - int negate_used; + int negate_used = 0; + uintmax_t used = -1; double pct = -1; - if (me_remote && show_local_fs) - return; - - if (me_dummy && show_all_fs == 0 && !show_listed_fs) - return; - - if (!selected_fstype (fstype) || excluded_fstype (fstype)) - return; + if (inode_format) + { + width = 7; + use_width = 5; + } + else + { + width = (human_output_opts & human_autoscale + ? 5 + ! (human_output_opts & human_base_1024) + : 9); - /* If MOUNT_POINT is NULL, then the filesystem is not mounted, and this - program reports on the filesystem that the special file is on. - It would be better to report on the unmounted filesystem, - but statfs doesn't do that on most systems. */ - stat_file = mount_point ? mount_point : disk; + use_width = ((posix_format + && ! (human_output_opts & human_autoscale)) + ? 8 : 4); + } - if (get_fs_usage (stat_file, disk, &fsu)) + if (total != -1 && available_to_root != -1) { - error (0, errno, "%s", quote (stat_file)); - exit_status = 1; - return; + used = total - available_to_root; + if (total < available_to_root) + { + negate_used = 1; + used = - used; + } } - if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs) - return; - if (! disk) - disk = "-"; /* unknown */ + disk = "-"; /* unknown */ if (! fstype) - fstype = "-"; /* unknown */ + fstype = "-"; /* unknown */ /* df.c reserved 5 positions for fstype, but that does not suffice for type iso9660 */ @@ -316,6 +350,7 @@ { int disk_name_len = (int) strlen (disk); int fstype_len = (int) strlen (fstype); + if (disk_name_len + fstype_len + 2 < 20) printf ("%s%*s ", disk, 18 - disk_name_len, fstype); else if (!posix_format) @@ -331,46 +366,8 @@ printf ("%-20s", disk); } - if (inode_format) - { - width = 7; - use_width = 5; - input_units = output_units = 1; - total = fsu.fsu_files; - available = fsu.fsu_ffree; - negate_available = 0; - available_to_root = available; - } - 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); - 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_to_root = fsu.fsu_bfree; - } - - used = -1; - negate_used = 0; - if (total != -1 && available_to_root != -1) - { - used = total - available_to_root; - if (total < available_to_root) - { - negate_used = 1; - used = - used; - } - } - printf (" %*s %*s %*s ", - width, df_readable (0, total, + width, df_readable (0, total, buf[0], input_units, output_units), width, df_readable (negate_used, used, buf[1], input_units, output_units), @@ -391,13 +388,14 @@ else { /* The calculation cannot be done easily with integer - arithmetic. Fall back on floating point. This can suffer - from minor rounding errors, but doing it exactly requires - multiple precision arithmetic, and it's not worth the - aggravation. */ + arithmetic. Fall back on floating point. This can suffer + from minor rounding errors, but doing it exactly requires + multiple precision arithmetic, and it's not worth the + aggravation. */ double u = negate_used ? - (double) - used : used; double a = negate_available ? - (double) - available : available; double nonroot_total = u + a; + if (nonroot_total) { double ipct; @@ -406,8 +404,9 @@ /* 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); + pct = ipct + (ipct < pct); } } @@ -415,13 +414,12 @@ printf ("%*.0f%%", use_width - 1, pct); else printf ("%*s", use_width, "- "); - if (mount_point) { #ifdef HIDE_AUTOMOUNT_PREFIX /* Don't print the first directory name in MOUNT_POINT if it's an - artifact of an automounter. This is a bit too aggressive to be - the default. */ + artifact of an automounter. This is a bit too aggressive to be + the default. */ if (strncmp ("/auto/", mount_point, 6) == 0) mount_point += 5; else if (strncmp ("/tmp_mnt/", mount_point, 9) == 0) @@ -432,6 +430,81 @@ putchar ('\n'); } +/* Prepares an filesystem entry for the show_information function and also + does the stuff for the grand total static */ + +static void +show_dev (const char *disk, const char *mount_point, const char *fstype, + int me_dummy, int me_remote) +{ + struct fs_usage fsu; + const char *stat_file; + uintmax_t input_units; + uintmax_t total; + uintmax_t available; + uintmax_t negate_available; + uintmax_t available_to_root; + + if (me_remote && show_local_fs) + return; + + if (me_dummy && show_all_fs == 0 && !show_listed_fs) + return; + + if (!selected_fstype (fstype) || excluded_fstype (fstype)) + return; + + /* If MOUNT_POINT is NULL, then the filesystem is not mounted, and this + program reports on the filesystem that the special file is on. + It would be better to report on the unmounted filesystem, + but statfs doesn't do that on most systems. */ + stat_file = mount_point ? mount_point : disk; + + if (get_fs_usage (stat_file, disk, &fsu)) + { + error (0, errno, "%s", quote (stat_file)); + exit_status = 1; + return; + } + + if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs) + return; + + if (inode_format) + { + total = fsu.fsu_files; + available = fsu.fsu_ffree; + negate_available = 0; + available_to_root = available; + input_units = 1; + } + else + { + input_units = fsu.fsu_blocksize; + total = fsu.fsu_blocks; + available = fsu.fsu_bavail; + negate_available = fsu.fsu_bavail_top_bit_set; + available_to_root = fsu.fsu_bfree; + } + + /* Show entry information. */ + show_information (disk, mount_point, fstype, total, + available, negate_available, available_to_root, + input_units, output_block_size); + + /* Convert blocksize to output_block_size so that no different blocksized + entries are added to each other. */ + total_total += convert_blocksize (total, input_units, output_block_size); + total_available += convert_blocksize (available, input_units, + output_block_size); + total_negate_available += convert_blocksize (negate_available, + input_units, + output_block_size); + total_available_to_root += convert_blocksize (available_to_root, + input_units, + output_block_size); +} + /* Return the root mountpoint of the filesystem on which FILE exists, in malloced storage. FILE_STAT should be the result of stating FILE. Give a diagnostic and return NULL if unable to determine the mount point. @@ -690,6 +763,17 @@ me->me_dummy, me->me_remote); } +/* Show a grand total statics. */ + +static void +show_grand_total (void) +{ + show_information ("total", NULL, NULL, total_total, + total_available, total_negate_available, + total_available_to_root, + output_block_size, output_block_size); +} + /* Add FSTYPE to the list of filesystem types to display. */ static void @@ -743,6 +827,7 @@ -i, --inodes list inode information instead of block usage\n\ -k like --block-size=1K\n\ -l, --local limit listing to local filesystems\n\ + -c, --total produce a grand total\n\ --no-sync do not invoke sync before getting usage info (default)\n\ "), stdout); fputs (_("\ @@ -792,7 +877,7 @@ posix_format = 0; exit_status = 0; - while ((c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options, NULL)) + while ((c = getopt_long (argc, argv, "aB:icF:hHklmPTt:vx:", long_options, NULL)) != -1) { switch (c) @@ -823,6 +908,9 @@ case 'l': show_local_fs = 1; break; + case 'c': + show_total = 1; + break; case 'm': /* obsolescent */ human_output_opts = 0; output_block_size = 1024 * 1024; @@ -926,6 +1014,9 @@ if (require_sync) sync (); + if (inode_format) + output_block_size = 1; + if (optind < argc) { int i; @@ -945,6 +1036,9 @@ print_header (); show_all_entries (); } - + + if (show_total) + show_grand_total (); + exit (exit_status); } _______________________________________________ Bug-coreutils mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/bug-coreutils