Subject: [PATCH] du -x should not count files in other file systems
From: Paul Eggert <[email-masked]>
To: Bug-coreutils <[email-masked]>
Date: Tue, 13 Dec 2011 11:19:27 -0800
List-Id: <debbugs-submit.debbugs.gnu.org>

While looking into Bug#10282 I noticed that 'du' is mishandling
the -x option.  It relies on FTS_XDEV to not cross file system boundaries,
but FTS_XDEV visits the root of the other file system, causing
'du' to output a line "0 X" where X is the mount point of the
other file system.  This doesn't sound right, since X is in a
different file system and du -x is supposed to ignore files in
other file systems.  Also, it disagrees with Solaris 10 du
(at least).

Here's a proposed patch.  The bug is absent from coreutils 5.0
and present in 5.2.0.  I'm guessing from the NEWS files that
it was introduced in 5.1.0 but 5.1.0 is no longer available
at ftp.gnu.org so this isn't trivial for me to check.

du: -x should not count files in other file systems
* NEWS: Document fix.
* src/du.c (process_file): Don't count files in different file
systems if -x is given.
* tests/du/one-file-system: Test for this bug.
diff --git a/NEWS b/NEWS
index 0d4c83b..51c44c7 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ GNU coreutils NEWS                                    -*- outline -*-

 ** Bug fixes

+  du -x no longer counts root directories of other file systems.
+  [bug introduced in coreutils-5.1.0]
+
   ls --color many-entry-directory was uninterruptible for too long
   [bug introduced in coreutils-5.2.1]

diff --git a/src/du.c b/src/du.c
index fba7f7d..a8dfd28 100644
--- a/src/du.c
+++ b/src/du.c
@@ -443,6 +443,9 @@ process_file (FTS *fts, FTSENT *ent)
               error (0, ent->fts_errno, _("cannot access %s"), quote (file));
               return false;
             }
+
+          if (fts->fts_options & FTS_XDEV && fts->fts_dev != sb->st_dev)
+            excluded = true;
         }

       if (excluded
diff --git a/tests/du/one-file-system b/tests/du/one-file-system
index 7195838..2ec9865 100755
--- a/tests/du/one-file-system
+++ b/tests/du/one-file-system
@@ -1,6 +1,5 @@
 #!/bin/sh
-# Test for a bug in fts's handling of FTS_XDEV, the flag behind
-# du's --one-file-system (-x) option.
+# Test for bugs in du's --one-file-system (-x) option.

 # Copyright (C) 2006-2011 Free Software Foundation, Inc.

@@ -19,9 +18,11 @@

 . "${srcdir=.}/init.sh"; path_prepend_ ../src
 print_ver_ du
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/other-fs-tmpdir"

-mkdir -p b/c y/z || framework_failure_
-
+mkdir -p b/c y/z d "$other_partition_tmpdir/x" || framework_failure_
+ln -s "$other_partition_tmpdir/x" d || framework_failure_

 # Due to a used-uninitialized variable, the "du -x" from coreutils-6.6
 # would not traverse into second and subsequent directories listed
@@ -37,4 +38,14 @@ EOF

 compare exp out || fail=1

+# "du -xL" reported a zero count for a file in a different file system,
+# instead of ignoring it.
+du -xL d > u || fail=1
+sed 's/^[0-9][0-9]*	//' u > out1
+cat <<\EOF > exp1 || fail=1
+d
+EOF
+
+compare exp1 out1 || fail=1
+
 Exit $fail