On 8/11/21 8:59 AM, Thimo Emmerich wrote:
Since the stat in [2]/df.c, line 1775 is necessary for the following fifo evaluation, it seems to be necessary to update the stat information after a successful open.
Thanks for reporting the bug. I installed the attached. It differs a bit from what you proposed in that it prefers fstat to stat, as fstat should be a bit faster and should avoid some unlikely races (there are many more races, but one fix at a time).
>From 48f59e058b4347172496bede193ade9fbf94d58e Mon Sep 17 00:00:00 2001 From: Paul Eggert <egg...@cs.ucla.edu> Date: Wed, 11 Aug 2021 11:16:05 -0700 Subject: [PATCH] df: fix bug with automounted If the command-line argument is automounted, df would use stat info that became wrong after the following open. * NEWS: Mention the fix (bug#50012). * src/df.c (automount_stat_err): New function. This fixes the hang on fifos in a better way, by using O_NONBLOCK. (main): Use it. --- NEWS | 3 +++ src/df.c | 34 +++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 49ee083e4..e14de1397 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,9 @@ GNU coreutils NEWS -*- outline -*- df no longer outputs duplicate remote mounts in the presence of bind mounts. [bug introduced in coreutils-8.26] + df no longer mishandles command-line args that it pre-mounts + [bug introduced in coreutils-8.29] + du no longer crashes on XFS file systems when the directory hierarchy is heavily changed during the run. [bug introduced in coreutils-8.25] diff --git a/src/df.c b/src/df.c index 4534935f5..48025b9fc 100644 --- a/src/df.c +++ b/src/df.c @@ -276,6 +276,28 @@ static struct option const long_options[] = {NULL, 0, NULL, 0} }; +/* Stat FILE and put the results into *ST. Return 0 if successful, an + error number otherwise. Try to open FILE before statting, to + trigger automounts. */ + +static int +automount_stat_err (char const *file, struct stat *st) +{ + int fd = open (file, O_RDONLY | O_NOCTTY | O_NONBLOCK); + if (fd < 0) + { + if (errno == ENOENT || errno == ENOTDIR) + return errno; + return stat (file, st) == 0 ? 0 : errno; + } + else + { + int err = fstat (fd, st) == 0 ? 0 : errno; + close (fd); + return err; + } +} + /* Replace problematic chars with '?'. Since only control characters are currently considered, this should work in all encodings. */ @@ -1772,19 +1794,13 @@ main (int argc, char **argv) stats = xnmalloc (argc - optind, sizeof *stats); for (int i = optind; i < argc; ++i) { - if (stat (argv[i], &stats[i - optind])) + int err = automount_stat_err (argv[i], &stats[i - optind]); + if (err != 0) { - error (0, errno, "%s", quotef (argv[i])); + error (0, err, "%s", quotef (argv[i])); exit_status = EXIT_FAILURE; argv[i] = NULL; } - else if (! S_ISFIFO (stats[i - optind].st_mode)) - { - /* open() is needed to automount in some cases. */ - int fd = open (argv[i], O_RDONLY | O_NOCTTY); - if (0 <= fd) - close (fd); - } } } -- 2.30.2