summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2021-08-11 11:16:05 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2021-08-11 11:22:40 -0700
commita3c04f8da14f0fe2a0561bf5562032b8ce5dafa9 (patch)
tree261005ed8e9463709e3caa9933f1284f8bb0a5e6
parentcat: with -E fix handling of \r\n spanning buffers (diff)
downloadcoreutils-a3c04f8da14f0fe2a0561bf5562032b8ce5dafa9.tar.gz
coreutils-a3c04f8da14f0fe2a0561bf5562032b8ce5dafa9.zip
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.
-rw-r--r--NEWS3
-rw-r--r--src/df.c34
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);
- }
}
}