[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#8154: du: issue with `--files0-from=DIR'
From: |
Jim Meyering |
Subject: |
bug#8154: du: issue with `--files0-from=DIR' |
Date: |
Wed, 02 Mar 2011 16:09:04 +0100 |
Eric Blake wrote:
> [adding bug-gnulib]
>
> On 03/02/2011 06:28 AM, Stefan Vargyas wrote:
>> Dear maintainers,
>>
>> While building and running coreutils v8.9, I came across the
>> following issue of 'du':
>>
>> $ mkdir /tmp/foo
>> $ du --files0-from=/tmp/foo
>> du: `/tmp/foo': read error: Is a directory
>> ...
>>
>> The program enters an infinite loop
Thanks! That affects the latest (coreutils-8.10), too.
> Thanks for the report. This is indeed a bug.
>
> I wonder if the better fix would be to modify the gnulib argv-iter
> module to make argv_iter_init_stream to fail if fileno(fp) is a
> directory, since not all platforms reliably fail with EISDIR when doing
> read() on a directory (some, like BSD, successfully return EOF, and some
> older systems even read raw directory contents).
That's just what I've done.
Here's a tentative patch, both for du.c and argv-iter.c in gnulib.
A probably-identical change to the du.c part will be required for wc.c.
I'll add tests and update NEWS, too.
diff --git a/src/du.c b/src/du.c
index 671cac7..e205cd5 100644
--- a/src/du.c
+++ b/src/du.c
@@ -889,6 +889,8 @@ main (int argc, char **argv)
quote (files_from));
ai = argv_iter_init_stream (stdin);
+ if (ai == NULL && errno == EISDIR)
+ error (EXIT_FAILURE, errno, _("invalid file: %s"), quote (files_from));
/* It's not easy here to count the arguments, so assume the
worst. */
diff --git a/lib/argv-iter.c b/lib/argv-iter.c
index 340e588..f0445f1 100644
--- a/lib/argv-iter.c
+++ b/lib/argv-iter.c
@@ -21,6 +21,8 @@
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
struct argv_iterator
{
@@ -49,11 +51,21 @@ argv_iter_init_argv (char **argv)
}
/* Initialize to read from the stream, FP.
- The input is expected to contain a list of NUL-delimited tokens. */
+ The input is expected to contain a list of NUL-delimited tokens.
+ If FP refers to a directory, set errno to EISDIR and return NULL. */
struct argv_iterator *
argv_iter_init_stream (FILE *fp)
{
- struct argv_iterator *ai = malloc (sizeof *ai);
+ struct argv_iterator *ai;
+ struct stat st;
+
+ if (fstat (fileno (fp), &st) == 0 && S_ISDIR (st.st_mode))
+ {
+ errno = EISDIR;
+ return NULL;
+ }
+
+ ai = malloc (sizeof *ai);
if (!ai)
return NULL;
ai->fp = fp;