bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/2] df: introduce option '--total'


From: Li Zefan
Subject: [PATCH 2/2] df: introduce option '--total'
Date: Thu, 29 Nov 2007 13:46:31 +0800
User-agent: Thunderbird 2.0.0.0 (X11/20070419)

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.


Signed-off-by: Shan Wei <address@hidden>
Signed-off-by: Li Yucai <address@hidden>
Signed-off-by: Xu Wanchao <address@hidden>
Signed-off-by: Li Zefan <address@hidden>

---
 TODO     |    2 -
 src/df.c |  215 ++++++++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 145 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..f6c486d 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,15 @@ 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;
+static bool total_negate_available;
+
 /* 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 +133,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 +262,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 +308,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 +327,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 +399,121 @@ 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)
+    {
+      uintmax_t bytes_avail = TO_BYTE (available, input_units);
+
+      total_total += TO_BYTE (total, input_units);
+
+      if (total_negate_available == negate_available)
+       total_available += bytes_avail;
+      else if (total_available > bytes_avail)
+       total_available -= bytes_avail;
+      else
+       {
+         total_available = bytes_avail - total_available;
+         total_negate_available = 
+               total_available == 0 ? false : negate_available;
+       }
+
+      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,
+               total_negate_available, total_available_to_root, 1, 1);
+  else
+    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 +811,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 +862,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 +879,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 +1033,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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]