summaryrefslogtreecommitdiff
path: root/src/du.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@CS.UCLA.EDU>2010-07-02 23:41:08 -0700
committerJim Meyering <meyering@redhat.com>2010-07-03 10:28:08 +0200
commitefe53cc72b599979ea292754ecfe8abf7c839d22 (patch)
tree4041993405c58203ccad79280dd9aed419e06ec2 /src/du.c
parentd27d6d371f3f7ede14b6bde79ddd45307d30fa47 (diff)
downloadcoreutils-efe53cc72b599979ea292754ecfe8abf7c839d22.tar.xz
du: don't miscount duplicate directories or link-count-1 files
* NEWS: Mention this. * src/du.c (hash_all): New static var. (process_file): Use it. (main): Set it. * tests/du/hard-link: Add a couple of test cases to help make sure this bug stays squashed. * tests/du/files0-from: Adjust existing tests to reflect change in semantics with duplicate arguments.
Diffstat (limited to 'src/du.c')
-rw-r--r--src/du.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/du.c b/src/du.c
index a90568ee8..4d6e03ae9 100644
--- a/src/du.c
+++ b/src/du.c
@@ -132,6 +132,9 @@ static bool apparent_size = false;
/* If true, count each hard link of files with multiple links. */
static bool opt_count_all = false;
+/* If true, hash all files to look for hard links. */
+static bool hash_all;
+
/* If true, output the NUL byte instead of a newline at the end of each line. */
static bool opt_nul_terminate_output = false;
@@ -518,8 +521,7 @@ process_file (FTS *fts, FTSENT *ent)
via a hard link, then don't let it contribute to the sums. */
if (skip
|| (!opt_count_all
- && ! S_ISDIR (sb->st_mode)
- && 1 < sb->st_nlink
+ && (hash_all || (! S_ISDIR (sb->st_mode) && 1 < sb->st_nlink))
&& ! hash_ins (sb->st_ino, sb->st_dev)))
{
/* Note that we must not simply return here.
@@ -937,11 +939,20 @@ main (int argc, char **argv)
quote (files_from));
ai = argv_iter_init_stream (stdin);
+
+ /* It's not easy here to count the arguments, so assume the
+ worst. */
+ hash_all = true;
}
else
{
char **files = (optind < argc ? argv + optind : cwd_only);
ai = argv_iter_init_argv (files);
+
+ /* Hash all dev,ino pairs if there are multiple arguments, or if
+ following non-command-line symlinks, because in either case a
+ file with just one hard link might be seen more than once. */
+ hash_all = (optind + 1 < argc || symlink_deref_bits == FTS_LOGICAL);
}
if (!ai)