Hi,
I've written a little fix for this bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=709351 which I think could solve the duplicity output problem. The idea is that df would keep a linked list of device numbers it already went through and not count in (get_dev) those filesystems again
when running into them as bind mounts.
Cheers,
 Ondrej.

>From 68402ab6e31a64dcac5dfed7e7f5d9595209d154 Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <[email protected]>
Date: Wed, 15 Aug 2012 17:30:40 +0200
Subject: [PATCH] df: Fix outputting filesystem duplicities caused by
 bind-mounts

* NEWS: Mention the fix.
* src/df.c (devlist_add): Add another entry to the global
device number list.
(dev_examined): Check if a filesystem has been examined already.
---
 NEWS     |  3 +++
 src/df.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 012a633..d1c84bb 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ GNU coreutils NEWS                                    -*- 
outline -*-
 
 ** Bug fixes
 
+  df now properly outputs filesystem information with bind mounts
+  present on the system.
+
   df now fails when the list of mounted file systems (/etc/mtab) cannot
   be read, yet the file system type information is needed to process
   certain options like -a, -l, -t and -x.
diff --git a/src/df.c b/src/df.c
index 9d956cd..5745a4f 100644
--- a/src/df.c
+++ b/src/df.c
@@ -43,6 +43,20 @@
   proper_name ("David MacKenzie"), \
   proper_name ("Paul Eggert")
 
+/* Filled with device numbers of examined filesystems to avoid
+   duplicities in output.  */
+struct devlist
+{
+  dev_t dev_num;
+  struct devlist *dev_next;
+};
+
+/* Global device number linked list.  */
+static struct devlist *devlist;
+
+/* Help pointer to devlist's first entry.  */
+static struct devlist *devlist_head;
+
 /* If true, show inode information. */
 static bool inode_format;
 
@@ -821,6 +835,44 @@ get_entry (char const *name, struct stat const *statp)
   get_point (name, statp);
 }
 
+/* Add a device number of the soon-to-be examined
+   filesystem to the global list devlist.  */
+
+static void
+devlist_add (dev_t dev_num)
+{
+  devlist->dev_num = dev_num;
+  devlist->dev_next = xmalloc (sizeof *devlist);
+  devlist = devlist->dev_next;
+  devlist->dev_num = 0;
+  devlist->dev_next = NULL;
+  devlist = devlist_head;
+}
+
+/* Check if the device was already examined.  */
+
+static bool
+dev_examined (char *mount_dir)
+{
+  dev_t dev_num;
+  struct stat *buf = alloca (sizeof *buf);
+  stat (mount_dir, buf);
+
+  dev_num = buf->st_dev;
+  while (devlist->dev_num)
+      {
+        if (devlist->dev_num == dev_num)
+          {
+            devlist = devlist_head;
+            return true;
+          }
+        devlist = devlist->dev_next;
+      }
+
+  devlist_add (dev_num);
+  return false;
+}
+
 /* Show all mounted file systems, except perhaps those that are of
    an unselected type or are empty. */
 
@@ -830,8 +882,11 @@ get_all_entries (void)
   struct mount_entry *me;
 
   for (me = mount_list; me; me = me->me_next)
-    get_dev (me->me_devname, me->me_mountdir, NULL, me->me_type,
-             me->me_dummy, me->me_remote, NULL, true);
+    if (!dev_examined (me->me_mountdir))
+      {
+      get_dev (me->me_devname, me->me_mountdir, NULL, me->me_type,
+               me->me_dummy, me->me_remote, NULL, true);
+      }
 }
 
 /* Add FSTYPE to the list of file system types to display. */
@@ -1132,7 +1187,21 @@ main (int argc, char **argv)
           get_entry (argv[i], &stats[i - optind]);
     }
   else
-    get_all_entries ();
+    {
+      devlist = xmalloc (sizeof *devlist);
+      devlist->dev_num = 0;
+      devlist->dev_next = NULL;
+      devlist_head = devlist;
+
+      get_all_entries ();
+
+      while (devlist_head)
+        {
+          devlist = devlist_head->dev_next;
+          free (devlist_head);
+          devlist_head = devlist;
+        }
+    }
 
   if (print_grand_total && file_systems_processed)
     {
-- 
1.7.11.2

Reply via email to