Hi, maybe this solution would be more suitable then. Cheers, Ondrej.
From cb99b2d28470f95386312edbd926c14da1cffa47 Mon Sep 17 00:00:00 2001 From: Ondrej Oprala <oopr...@redhat.com> 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 | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 2 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..ec6b7a5 100644 --- a/src/df.c +++ b/src/df.c @@ -43,6 +43,17 @@ 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; +}; + +/* Device list help pointer. */ +struct devlist *devlist_head; + /* If true, show inode information. */ static bool inode_format; @@ -821,6 +832,48 @@ 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) +{ + struct devlist *devlist = devlist_head; + while(devlist->dev_next) + devlist = devlist->dev_next; + + if (!devlist->dev_num) + devlist->dev_num = dev_num; + else + { + devlist->dev_next = xmalloc (sizeof *devlist); + devlist = devlist->dev_next; + devlist->dev_num = dev_num; + devlist->dev_next = NULL; + } +} + +/* Check if the device was already examined. */ + +static bool +dev_examined (struct devlist *devlist, char *mount_dir) +{ + dev_t dev_num; + struct stat buf; + stat (mount_dir, &buf); + + dev_num = buf.st_dev; + while (devlist) + { + if (devlist->dev_num == dev_num) + 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. */ @@ -828,10 +881,23 @@ static void get_all_entries (void) { struct mount_entry *me; + struct devlist *devlist = xmalloc (sizeof *devlist); + devlist_head = devlist; + + devlist->dev_num = 0; + devlist->dev_next = NULL; 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 (devlist, me->me_mountdir)) + get_dev (me->me_devname, me->me_mountdir, NULL, me->me_type, + me->me_dummy, me->me_remote, NULL, true); + + while (devlist) + { + devlist = devlist->dev_next; + free (devlist_head); + devlist_head = devlist; + } } /* Add FSTYPE to the list of file system types to display. */ -- 1.7.11.2