Ondřej Vašík c767e7
diff -urNp coreutils-8.20-orig/doc/coreutils.texi coreutils-8.20/doc/coreutils.texi
Ondřej Vašík c767e7
--- coreutils-8.20-orig/doc/coreutils.texi	2012-10-23 16:14:12.000000000 +0200
Ondřej Vašík c767e7
+++ coreutils-8.20/doc/coreutils.texi	2012-12-10 14:41:33.532650289 +0100
Ondřej Vašík c767e7
@@ -10597,6 +10597,14 @@ Normally the disk space is printed in un
Ondřej Vašík c767e7
 1024 bytes, but this can be overridden (@pxref{Block size}).
Ondřej Vašík c767e7
 Non-integer quantities are rounded up to the next higher unit.
Ondřej Vašík c767e7
 
Ondřej Vašík c767e7
+For bind mounts and without arguments, @command{df} only outputs the statistics
Ondřej Vašík c767e7
+for the first occurence of that device in the list of file systems (@var{mtab}),
Ondřej Vašík c767e7
+i.e., it hides duplicate entries, unless the @option{-a} option is specified.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+By default, @command{df} omits the early-boot pseudo file system type
Ondřej Vašík c767e7
+@samp{rootfs}, unless the @option{-a} option is specified or that file system
Ondřej Vašík c767e7
+type is explicitly to be included by using the @option{-t} option.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
 @cindex disk device file
Ondřej Vašík c767e7
 @cindex device file, disk
Ondřej Vašík c767e7
 If an argument @var{file} is a disk device file containing a mounted
Ondřej Vašík c767e7
diff -urNp coreutils-8.20-orig/src/df.c coreutils-8.20/src/df.c
Ondřej Vašík c767e7
--- coreutils-8.20-orig/src/df.c	2012-10-23 16:14:12.000000000 +0200
Ondřej Vašík c767e7
+++ coreutils-8.20/src/df.c	2012-12-10 14:41:33.534649048 +0100
Ondřej Vašík c767e7
@@ -46,6 +46,17 @@
Ondřej Vašík c767e7
 /* If true, show inode information. */
Ondřej Vašík c767e7
 static bool inode_format;
Ondřej Vašík c767e7
 
Ondřej Vašík c767e7
+/* Filled with device numbers of examined file systems to avoid
Ondřej Vašík c767e7
+   duplicities in output.  */
Ondřej Vašík c767e7
+struct devlist
Ondřej Vašík c767e7
+{
Ondřej Vašík c767e7
+  dev_t dev_num;
Ondřej Vašík c767e7
+  struct devlist *next;
Ondřej Vašík c767e7
+};
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+/* Store of already-processed device numbers.  */
Ondřej Vašík c767e7
+static struct devlist *devlist_head;
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
 /* If true, show even file systems with zero size or
Ondřej Vašík c767e7
    uninteresting types. */
Ondřej Vašík c767e7
 static bool show_all_fs;
Ondřej Vašík c767e7
@@ -57,6 +68,12 @@ static bool show_local_fs;
Ondřej Vašík c767e7
    command line argument -- even if it's a dummy (automounter) entry.  */
Ondřej Vašík c767e7
 static bool show_listed_fs;
Ondřej Vašík c767e7
 
Ondřej Vašík c767e7
+/* If true, include rootfs in the output.  */
Ondřej Vašík c767e7
+static bool show_rootfs;
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+/* The literal name of the initial root file system.  */
Ondřej Vašík c767e7
+static char const *ROOTFS = "rootfs";
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
 /* Human-readable options for output.  */
Ondřej Vašík c767e7
 static int human_output_opts;
Ondřej Vašík c767e7
 
Ondřej Vašík c767e7
@@ -372,6 +389,29 @@ excluded_fstype (const char *fstype)
Ondřej Vašík c767e7
   return false;
Ondřej Vašík c767e7
 }
Ondřej Vašík c767e7
 
Ondřej Vašík c767e7
+/* Check if the device was already examined.  */
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+static bool
Ondřej Vašík c767e7
+dev_examined (char const *mount_dir, char const *devname)
Ondřej Vašík c767e7
+{
Ondřej Vašík c767e7
+  struct stat buf;
Ondřej Vašík c767e7
+  if (-1 == stat (mount_dir, &buf))
Ondřej Vašík c767e7
+    return false;
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+  struct devlist *devlist = devlist_head;
Ondřej Vašík c767e7
+  for ( ; devlist; devlist = devlist->next)
Ondřej Vašík c767e7
+    if (devlist->dev_num == buf.st_dev)
Ondřej Vašík c767e7
+      return true;
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+  /* Add the device number to the global list devlist.  */
Ondřej Vašík c767e7
+  devlist = xmalloc (sizeof *devlist);
Ondřej Vašík c767e7
+  devlist->dev_num = buf.st_dev;
Ondřej Vašík c767e7
+  devlist->next = devlist_head;
Ondřej Vašík c767e7
+  devlist_head = devlist;
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+  return false;
Ondřej Vašík c767e7
+}
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
 /* Return true if N is a known integer value.  On many file systems,
Ondřej Vašík c767e7
    UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
Ondřej Vašík c767e7
    represents unknown.  Use a rule that works on AIX file systems, and
Ondřej Vašík c767e7
@@ -496,6 +536,15 @@ get_dev (char const *disk, char const *m
Ondřej Vašík c767e7
   if (!selected_fstype (fstype) || excluded_fstype (fstype))
Ondřej Vašík c767e7
     return;
Ondřej Vašík c767e7
 
Ondřej Vašík c767e7
+  if (process_all && !show_all_fs && !show_listed_fs)
Ondřej Vašík c767e7
+    {
Ondřej Vašík c767e7
+      /* No arguments nor "df -a", then check if df has to ...  */
Ondřej Vašík c767e7
+      if (!show_rootfs && STREQ (disk, ROOTFS))
Ondřej Vašík c767e7
+        return; /* ... skip rootfs: (unless -trootfs is given.  */
Ondřej Vašík c767e7
+      if (dev_examined (mount_point, disk))
Ondřej Vašík c767e7
+        return; /* ... skip duplicate entries (bind mounts).  */
Ondřej Vašík c767e7
+    }
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
   /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
Ondřej Vašík c767e7
      program reports on the file system that the special file is on.
Ondřej Vašík c767e7
      It would be better to report on the unmounted file system,
Ondřej Vašík c767e7
@@ -1005,6 +1054,7 @@ main (int argc, char **argv)
Ondřej Vašík c767e7
           /* Accept -F as a synonym for -t for compatibility with Solaris.  */
Ondřej Vašík c767e7
         case 't':
Ondřej Vašík c767e7
           add_fs_type (optarg);
Ondřej Vašík c767e7
+          show_rootfs = selected_fstype (ROOTFS);
Ondřej Vašík c767e7
           break;
Ondřej Vašík c767e7
 
Ondřej Vašík c767e7
         case 'v':		/* For SysV compatibility. */
Ondřej Vašík c767e7
@@ -1149,6 +1199,14 @@ main (int argc, char **argv)
Ondřej Vašík c767e7
      diagnostic, e.g., if all have been excluded.  */
Ondřej Vašík c767e7
   if (exit_status == EXIT_SUCCESS && ! file_systems_processed)
Ondřej Vašík c767e7
     error (EXIT_FAILURE, 0, _("no file systems processed"));
Ondřej Vašík c767e7
+  IF_LINT (
Ondřej Vašík c767e7
+    while (devlist_head)
Ondřej Vašík c767e7
+      {
Ondřej Vašík c767e7
+        struct devlist *devlist = devlist_head->next;
Ondřej Vašík c767e7
+        free (devlist_head);
Ondřej Vašík c767e7
+        devlist_head = devlist;
Ondřej Vašík c767e7
+      }
Ondřej Vašík c767e7
+    );
Ondřej Vašík c767e7
 
Ondřej Vašík c767e7
   exit (exit_status);
Ondřej Vašík c767e7
 }
Ondřej Vašík c767e7
diff -urNp coreutils-8.20-orig/tests/df/skip-duplicates.sh coreutils-8.20/tests/df/skip-duplicates.sh
Ondřej Vašík c767e7
--- coreutils-8.20-orig/tests/df/skip-duplicates.sh	1970-01-01 01:00:00.000000000 +0100
Ondřej Vašík c767e7
+++ coreutils-8.20/tests/df/skip-duplicates.sh	2012-12-10 14:41:33.535280173 +0100
Ondřej Vašík c767e7
@@ -0,0 +1,77 @@
Ondřej Vašík c767e7
+#!/bin/sh
Ondřej Vašík c767e7
+# Test df's behavior when the mount list contains duplicate entries.
Ondřej Vašík c767e7
+# This test is skipped on systems that lack LD_PRELOAD support; that's fine.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Copyright (C) 2012 Free Software Foundation, Inc.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# This program is free software: you can redistribute it and/or modify
Ondřej Vašík c767e7
+# it under the terms of the GNU General Public License as published by
Ondřej Vašík c767e7
+# the Free Software Foundation, either version 3 of the License, or
Ondřej Vašík c767e7
+# (at your option) any later version.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# This program is distributed in the hope that it will be useful,
Ondřej Vašík c767e7
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
Ondřej Vašík c767e7
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ondřej Vašík c767e7
+# GNU General Public License for more details.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# You should have received a copy of the GNU General Public License
Ondřej Vašík c767e7
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
Ondřej Vašík c767e7
+print_ver_ df
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+df || skip_ "df fails"
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Simulate an mtab file with two entries of the same device number.
Ondřej Vašík c767e7
+cat > k.c <<'EOF' || framework_failure_
Ondřej Vašík c767e7
+#include <stdio.h>
Ondřej Vašík c767e7
+#include <mntent.h>
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+struct mntent *getmntent (FILE *fp)
Ondřej Vašík c767e7
+{
Ondřej Vašík c767e7
+  /* Prove that LD_PRELOAD works. */
Ondřej Vašík c767e7
+  static int done = 0;
Ondřej Vašík c767e7
+  if (!done)
Ondřej Vašík c767e7
+    {
Ondřej Vašík c767e7
+      fclose (fopen ("x", "w"));
Ondřej Vašík c767e7
+      ++done;
Ondřej Vašík c767e7
+    }
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+  static struct mntent mntent;
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+  while (done++ < 3)
Ondřej Vašík c767e7
+    {
Ondřej Vašík c767e7
+      mntent.mnt_fsname = "fsname";
Ondřej Vašík c767e7
+      mntent.mnt_dir = "/";
Ondřej Vašík c767e7
+      mntent.mnt_type = "-";
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+      return &mntent;
Ondřej Vašík c767e7
+    }
Ondřej Vašík c767e7
+  return NULL;
Ondřej Vašík c767e7
+}
Ondřej Vašík c767e7
+EOF
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Then compile/link it:
Ondřej Vašík c767e7
+gcc --std=gnu99 -shared -fPIC -ldl -O2 k.c -o k.so \
Ondřej Vašík c767e7
+  || skip_ "getmntent hack does not work on this platform"
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Test if LD_PRELOAD works:
Ondřej Vašík c767e7
+LD_PRELOAD=./k.so df
Ondřej Vašík c767e7
+test -f x || skip_ "internal test failure: maybe LD_PRELOAD doesn't work?"
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# The fake mtab file should only contain 2 entries, both
Ondřej Vašík c767e7
+# having the same device number; thus the output should
Ondřej Vašík c767e7
+# consist of a header and one entry.
Ondřej Vašík c767e7
+LD_PRELOAD=./k.so df >out || fail=1
Ondřej Vašík c767e7
+test $(wc -l 
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Ensure that filtering duplicates does not affect -a processing.
Ondřej Vašík c767e7
+LD_PRELOAD=./k.so df -a >out || fail=1
Ondřej Vašík c767e7
+test $(wc -l 
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Ensure that filtering duplcates does not affect
Ondřej Vašík c767e7
+# argument processing (now without the fake getmntent()).
Ondřej Vašík c767e7
+df '.' '.' >out || fail=1
Ondřej Vašík c767e7
+test $(wc -l 
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+Exit $fail
Ondřej Vašík c767e7
diff -urNp coreutils-8.20-orig/tests/df/skip-rootfs.sh coreutils-8.20/tests/df/skip-rootfs.sh
Ondřej Vašík c767e7
--- coreutils-8.20-orig/tests/df/skip-rootfs.sh	1970-01-01 01:00:00.000000000 +0100
Ondřej Vašík c767e7
+++ coreutils-8.20/tests/df/skip-rootfs.sh	2012-12-10 14:41:33.536310753 +0100
Ondřej Vašík c767e7
@@ -0,0 +1,46 @@
Ondřej Vašík c767e7
+#!/bin/sh
Ondřej Vašík c767e7
+# Test df's behavior for skipping the pseudo "rootfs" file system.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Copyright (C) 2012 Free Software Foundation, Inc.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# This program is free software: you can redistribute it and/or modify
Ondřej Vašík c767e7
+# it under the terms of the GNU General Public License as published by
Ondřej Vašík c767e7
+# the Free Software Foundation, either version 3 of the License, or
Ondřej Vašík c767e7
+# (at your option) any later version.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# This program is distributed in the hope that it will be useful,
Ondřej Vašík c767e7
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
Ondřej Vašík c767e7
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ondřej Vašík c767e7
+# GNU General Public License for more details.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# You should have received a copy of the GNU General Public License
Ondřej Vašík c767e7
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
Ondřej Vašík c767e7
+print_ver_ df
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+df || skip_ "df fails"
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Verify that rootfs is in mtab (and shown when the -a option is specified).
Ondřej Vašík c767e7
+df -a >out || fail=1
Ondřej Vašík c767e7
+grep '^rootfs' out || skip_ "no rootfs in mtab"
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Ensure that rootfs is supressed when no options is specified.
Ondřej Vašík c767e7
+df >out || fail=1
Ondřej Vašík c767e7
+grep '^rootfs' out && { fail=1; cat out; }
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Ensure that the rootfs is shown when explicitly specifying "-t rootfs".
Ondřej Vašík c767e7
+df -t rootfs >out || fail=1
Ondřej Vašík c767e7
+grep '^rootfs' out || { fail=1; cat out; }
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Ensure that the rootfs is shown when explicitly specifying "-t rootfs",
Ondřej Vašík c767e7
+# even when the -a option is specified.
Ondřej Vašík c767e7
+df -t rootfs -a >out || fail=1
Ondřej Vašík c767e7
+grep '^rootfs' out || { fail=1; cat out; }
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+# Ensure that the rootfs is omitted in all_fs mode when it is explicitly
Ondřej Vašík c767e7
+# black-listed.
Ondřej Vašík c767e7
+df -a -x rootfs >out || fail=1
Ondřej Vašík c767e7
+grep '^rootfs' out && { fail=1; cat out; }
Ondřej Vašík c767e7
+
Ondřej Vašík c767e7
+Exit $fail
Ondřej Vašík c767e7
diff -urNp coreutils-8.20-orig/tests/local.mk coreutils-8.20/tests/local.mk
Ondřej Vašík c767e7
--- coreutils-8.20-orig/tests/local.mk	2012-10-23 16:14:12.000000000 +0200
Ondřej Vašík c767e7
+++ coreutils-8.20/tests/local.mk	2012-12-10 14:41:33.536310753 +0100
Ondřej Vašík c767e7
@@ -456,6 +456,8 @@ all_tests =					\
Ondřej Vašík c767e7
   tests/df/unreadable.sh			\
Ondřej Vašík c767e7
   tests/df/total-unprocessed.sh			\
Ondřej Vašík c767e7
   tests/df/no-mtab-status.sh			\
Ondřej Vašík c767e7
+  tests/df/skip-duplicates.sh			\
Ondřej Vašík c767e7
+  tests/df/skip-rootfs.sh			\
Ondřej Vašík c767e7
   tests/dd/direct.sh				\
Ondřej Vašík c767e7
   tests/dd/misc.sh				\
Ondřej Vašík c767e7
   tests/dd/nocache.sh				\