du: fix -x: don't ignore non-directory arguments
authorJim Meyering <meyering@redhat.com>
Thu, 8 Mar 2012 09:33:50 +0000 (10:33 +0100)
committerJim Meyering <meyering@redhat.com>
Thu, 8 Mar 2012 12:04:09 +0000 (13:04 +0100)
Surprise!  "du -x non-DIR" would print nothing.
Note that the problem arises only when processing a non-directory
specified on the command line.  Not surprisingly, "du -x" still
works as expected for any directory argument.

When performing its same-file-system check, du may skip an entry
only if it is at fts_level 1 or greater.  Command-line arguments
are at fts_level == 0 (FTS_ROOTLEVEL).

* src/du.c (process_file): Don't use the top-level FTS->fts_dev
when testing for --one-file-system (-x).  It happens to be valid
for directories, but it is always 0 for a non-directory.
* tests/du/one-file-system: Add tests for this.
* NEWS (Bug fixes): Mention it.
Reported by Daniel Stavrovski in http://bugs.gnu.org/10967.
Introduced by commit v8.14-95-gcfe1040.

NEWS
THANKS.in
src/du.c
tests/du/one-file-system

diff --git a/NEWS b/NEWS
index 04c911f..3224b30 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,10 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** Bug fixes
 
+  du --one-file-system (-x) would ignore any non-directory specified on
+  the command line.  For example, "touch f; du -x f" would print nothing.
+  [bug introduced in coreutils-8.14]
+
   mv now lets you move a symlink onto a same-inode destination file that
   has two or more hard links.  Before, it would reject that, saying that
   they are the same, implicitly warning you that the move would result in
index c8dd75f..d23f7b3 100644 (file)
--- a/THANKS.in
+++ b/THANKS.in
@@ -134,6 +134,7 @@ Dan Hagerty                         hag@gnu.ai.it.edu
 Dan Pascu                           dan@services.iiruc.ro
 Daniel Bergstrom                    noa@melody.se
 Daniel P. BerrangĂ©                  berrange@redhat.com
+Daniel Stavrovski                   d@stavrovski.net
 Dániel Varga                        danielv@axelero.hu
 Danny Levinson                      danny.levinson@overture.com
 Darrel Francis                      d.francis@cheerful.com
index e4e36df..41c9535 100644 (file)
--- a/src/du.c
+++ b/src/du.c
@@ -443,7 +443,14 @@ process_file (FTS *fts, FTSENT *ent)
               return false;
             }
 
-          if (fts->fts_options & FTS_XDEV && fts->fts_dev != sb->st_dev)
+          /* The --one-file-system (-x) option cannot exclude anything
+             specified on the command-line.  By definition, it can exclude
+             a file or directory only when its device number is different
+             from that of its just-processed parent directory, and du does
+             not process the parent of a command-line argument.  */
+          if (fts->fts_options & FTS_XDEV
+              && FTS_ROOTLEVEL < ent->fts_level
+              && fts->fts_dev != sb->st_dev)
             excluded = true;
         }
 
index f0d264a..110080f 100755 (executable)
@@ -43,7 +43,15 @@ compare exp out || fail=1
 du -xL d > u || fail=1
 sed 's/^[0-9][0-9]*    //' u > out1
 echo d > exp1 || fail=1
-
 compare exp1 out1 || fail=1
 
+# With coreutils-8.15, "du -xs FILE" would print no output.
+touch f
+for opt in -x -xs; do
+  du $opt f > u || fail=1
+  sed 's/^[0-9][0-9]*  //' u > out2
+  echo f > exp2 || fail=1
+  compare exp2 out2 || fail=1
+done
+
 Exit $fail