summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2023-03-04 16:51:11 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2023-03-04 16:57:16 -0800
commit110bcd28386b1f47a4cd876098acb708fdcbbb25 (patch)
tree8ed76d8b3e55d094e37a9ccb5d5c386d44abe3df
parent8022874d1242f3b094b6bd001e83845e289d2bb1 (diff)
downloadcoreutils-110bcd28386b1f47a4cd876098acb708fdcbbb25.tar.gz
du: --apparent counts only symlinks and regular
Problem reported by Christoph Anton Mitterer (Bug#61884). * src/du.c (process_file): When counting apparent sizes, count only usable st_size members. * tests/du/apparent.sh: New file. * tests/local.mk (all_root_tests): Add it.
-rw-r--r--NEWS5
-rw-r--r--doc/coreutils.texi3
-rw-r--r--src/du.c8
-rwxr-xr-xtests/du/apparent.sh33
-rw-r--r--tests/local.mk1
5 files changed, 46 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index 568994ff5..5b0dc939c 100644
--- a/NEWS
+++ b/NEWS
@@ -98,6 +98,11 @@ GNU coreutils NEWS -*- outline -*-
to support unusual devices that may have this constraint.
[behavior inadvertently changed in coreutils-7.2]
+ du --apparent now counts apparent sizes only of regular files and
+ symbolic links. POSIX does not specify the meaning of apparent
+ sizes (i.e., st_size) for other file types, and counting those sizes
+ could cause confusing and unwanted size mismatches.
+
'ls -v' and 'sort -V' go back to sorting ".0" before ".A",
reverting to the behavior in coreutils-9.0 and earlier.
This behavior is now documented.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index b07a330eb..f0e46b9ee 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -12429,6 +12429,9 @@ dd bs=1 seek=2GiB if=/dev/null of=big
has an apparent size of 2 GiB, yet on most modern
file systems, it actually uses almost no space.
+Apparent sizes are meaningful only for regular files and symbolic links.
+Other file types do not contribute to apparent size.
+
@item -B @var{size}
@itemx --block-size=@var{size}
@opindex -B
diff --git a/src/du.c b/src/du.c
index 8bffc1aa7..025a587d7 100644
--- a/src/du.c
+++ b/src/du.c
@@ -131,7 +131,7 @@ struct dulevel
static bool opt_all = false;
/* If true, rather than using the device usage of each file,
- use the apparent size (a la stat.st_size). */
+ use the apparent size (stat.st_size if usable, 0 otherwise). */
static bool apparent_size = false;
/* If true, count each hard link of files with multiple links. */
@@ -494,8 +494,8 @@ process_file (FTS *fts, FTSENT *ent)
size_t level;
static size_t n_alloc;
/* First element of the structure contains:
- The sum of the st_size values of all entries in the single directory
- at the corresponding level. Although this does include the st_size
+ The sum of the sizes of all entries in the single directory
+ at the corresponding level. Although this does include the sizes
corresponding to each subdirectory, it does not include the size of
any file in a subdirectory. Also corresponding last modified date.
Second element of the structure contains:
@@ -588,7 +588,7 @@ process_file (FTS *fts, FTSENT *ent)
duinfo_set (&dui,
(apparent_size
- ? MAX (0, sb->st_size)
+ ? (usable_st_size (sb) ? MAX (0, sb->st_size) : 0)
: (uintmax_t) ST_NBLOCKS (*sb) * ST_NBLOCKSIZE),
(time_type == time_mtime ? get_stat_mtime (sb)
: time_type == time_atime ? get_stat_atime (sb)
diff --git a/tests/du/apparent.sh b/tests/du/apparent.sh
new file mode 100755
index 000000000..dba3031d4
--- /dev/null
+++ b/tests/du/apparent.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Exercise du's --apparent-size option.
+
+# Copyright 2023 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ du
+
+mkdir -p d || framework_failure_
+for f in $(seq 100); do
+ echo foo >d/$f || framework_failure_
+done
+
+du -b d/* >separate || fail=1
+du -b d >together || fail=1
+separate_sum=$($AWK '{sum+=$1}END{print sum}' separate) || framework_failure_
+together_sum=$($AWK '{sum+=$1}END{print sum}' together) || framework_failure_
+test $separate_sum -eq $together_sum || fail=1
+
+Exit $fail
diff --git a/tests/local.mk b/tests/local.mk
index c8db95e99..1fe04235d 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -118,6 +118,7 @@ all_root_tests = \
tests/dd/skip-seek-past-dev.sh \
tests/df/problematic-chars.sh \
tests/df/over-mount-device.sh \
+ tests/du/apparent.sh \
tests/du/bind-mount-dir-cycle.sh \
tests/du/bind-mount-dir-cycle-v2.sh \
tests/id/setgid.sh \