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

Reply via email to