Bug 15772 - Preprocessing fails if an inaccessible directory is on include path
Summary: Preprocessing fails if an inaccessible directory is on include path
Status: RESOLVED WONTFIX
Alias: None
Product: gcc
Classification: Unclassified
Component: preprocessor (show other bugs)
Version: 3.4.0
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-06-02 10:28 UTC by Ed Catmur
Modified: 2008-01-25 20:32 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 3.4.4
Last reconfirmed:


Attachments
Patch to make EACCES non-fatal (314 bytes, patch)
2004-06-02 13:31 UTC, Ed Catmur
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ed Catmur 2004-06-02 10:28:04 UTC
http://linuxfromscratch.org/pipermail/lfs-hackers/2004-May/001096.html
http://bugs.gentoo.org/show_bug.cgi?id=52755
http://forums.gentoo.org/viewtopic.php?t=108718&start=600#1093328

gcc nss_nis/nis-service.c -c -std=gnu99 -O2 -Wall -Winline -Wstrict-prototypes
-Wwrite-strings -fprefetch-loop-arrays -freorder-blocks -march=athlon-xp -pipe
-mpreferred-stack-boundary=2  -fPIC    -I../include -I.
-I/var/tmp/portage/glibc-2.3.3_pre20040420-r1/work/glibc-2.3.2/buildhere/nis
-I.. -I../libio -I../nptl
-I/var/tmp/portage/glibc-2.3.3_pre20040420-r1/work/glibc-2.3.2/buildhere
-I../sysdeps/i386/elf -I../nptl/sysdeps/unix/sysv/linux/i386/i686
-I../nptl/sysdeps/unix/sysv/linux/i386 -I../nptl/sysdeps/unix/sysv/linux
-I../nptl/sysdeps/pthread -I../sysdeps/pthread -I../nptl/sysdeps/unix/sysv
-I../nptl/sysdeps/unix -I../nptl/sysdeps/i386/i686 -I../nptl/sysdeps/i386
-I../sysdeps/unix/sysv/linux/i386 -I../sysdeps/unix/sysv/linux -I../sysdeps/gnu
-I../sysdeps/unix/common -I../sysdeps/unix/mman -I../sysdeps/unix/inet
-I../sysdeps/unix/sysv/i386 -I../sysdeps/unix/sysv -I../sysdeps/unix/i386
-I../sysdeps/unix -I../sysdeps/posix -I../sysdeps/i386/i686/fpu
-I../sysdeps/i386/i686 -I../sysdeps/i386/i486 -I../nptl/sysdeps/i386/i486
-I../sysdeps/i386/fpu -I../sysdeps/i386 -I../sysdeps/wordsize-32
-I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64
-I../sysdeps/ieee754/flt-32 -I../sysdeps/ieee754 -I../sysdeps/generic/elf
-I../sysdeps/generic -nostdinc -isystem
/usr/lib/gcc/i686-pc-linux-gnu/3.4.0/include -isystem //usr/include
-D_LIBC_REENTRANT -D_LIBC_REENTRANT -include ../include/libc-symbols.h  -DPIC
-DSHARED -DNOT_IN_libc=1 -DIS_IN_libnss_nis=1    -o
/var/tmp/portage/glibc-2.3.3_pre20040420-r1/work/glibc-2.3.2/buildhere/nis/nis-service.os
-MD -MP -MF
/var/tmp/portage/glibc-2.3.3_pre20040420-r1/work/glibc-2.3.2/buildhere/nis/nis-service.os.dt
In file included from nss_nis/nis-proto.c:20:
../include/nss.h:1:21: ./nss/nss.h: Permission denied
In file included from nss_nis/nis-service.c:20:
../include/nss.h:1:21: ./nss/nss.h: Permission denied
In file included from ./nss-nis.h:24,
                 from nss_nis/nis-proto.c:29:
../include/nsswitch.h:1:26: ./nss/nsswitch.h: Permission denied
...

Situation: reiser4 filesystem, wd contains an ordinary file mode 0644 named
'nss'. (This is important).

Cause: in gcc/cppfiles.c,
_cpp_find_file() calls find_file_in_dir() on . for nss/nsswitch.h
find_file_in_dir() calls open_file() on ./nss/nsswitch.h
open_file() calls open() on ./nss/nsswitch.h
Instead of failing ENOTDIR, open() fails EACCES. This is because under reiser4
all files are directories so ENOTDIR is unused as an error code; instead it
tries to read 'nss' as a directory but as 'nss' is 0644 its "directory contents"
are not accessible.
On any normal file system, open() fails ENOTDIR, open_file() returns false
converting ENOTDIR to ENOENT, find_file_in_dir() returns false, and
_cpp_find_file() continues to the next node in the include list, eventually
finding nss/nsswitch.h in -I..
On reiser4, open() fails EACCES, open_file() returns false, find_file_in_dir()
calls open_file_failed() and returns true, everything falls apart.

The workaround I suggest for glibc is to make 'nss' 0755 thus causing open() to
fail ENOENT which causes _cpp_find_file_in_dir() to continue to the next node in
the include list.

The fix I suggest for gcc is to make EACCES non-fatal: gcc should instead of
failing print a warning message and continue searching for an include file it
can access. 

The patch is obvious and I will attach it as soon as I have tested it properly.
Comment 1 Danny Smith 2004-06-02 11:16:34 UTC
This is a duplicate of 11242 which was (incorrectly) closed.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11242

There is a patch there too, which has been bootstrapped and regtested.

Danny
Comment 2 Ed Catmur 2004-06-02 12:18:20 UTC
Interesting, but... no, this isn't a duplicate.

The error on mingw32 is caused by attempting to open a directory as a file.

The error on reiser4 is caused by attempting to open a file as a directory (as a
component in the path to an include file).

The patch on bug 11242 will not fix the reiser4 bug as stat() fails in the
reiser4 scenario.
Comment 3 Andrew Pinski 2004-06-02 12:40:48 UTC
Isn't this a bug in reiser4 which is inconsistent with any other file system?
Comment 4 Ed Catmur 2004-06-02 13:25:49 UTC
"It's not a bug, it's a feature". Files-as-directories is part of what reiser4 is.

I see two issues here.

First, reiser4 giving an EACCES or ENOENT where classically an ENOTDIR would be
expected. So this is different behaviour. That doesn't mean that it's wrong;
Hans has made it clear that files-as-directories is the direction reiser4 is taking.

Second, even if a reiser4-specific patch were possible the situation remains
that (on any filesystem) an inaccessible directory somewhere along the include
path breaks that #include statement. I have tried but I can't think of a good
reason for this behaviour. I can file it as a separate bug blocking this bug if
you want.
Comment 5 Ed Catmur 2004-06-02 13:31:29 UTC
Created attachment 6451 [details]
Patch to make EACCES non-fatal

For #include <foo/bar.h>, causes a warning:

foo.c:1:27: warning: ./foo/bar.h: Permission denied

to be issued when foo is a non-readable directory or on a reiser4 filesystem,
but keeps searching for <foo/bar.h> in the include path.
Comment 6 Ed Catmur 2004-06-02 13:41:53 UTC
Here's an test case for the underlying bug on any filesystem:

$ cat > foo.c
#include <include/stdio.h>
main() { printf("Hello world\n"); }
$ mkdir include
$ chmod 000 include
$ gcc foo.c -I. -I/usr && ./a.out
foo.c:1:27: ./include/stdio.h: Permission denied
$ gcc foo.c -I/usr -I. && ./a.out
Hello world
Comment 7 Neil Booth 2004-06-02 17:23:37 UTC
Despite all said in this PR I can't see why this is a GCC bug.  Isn't it a glibc
bug?
Comment 8 Ed Catmur 2004-06-05 21:42:23 UTC
Sorry, missed your response.

This is not a glibc although glibc would be well advised to work around the bug
e.g. by making the file nss executable.

I regard this as a gcc bug on the grounds that raising an error (as opposed to a
warning), when an inaccessible path is encountered while searching for includes,
is incorrect behaviour.
Comment 9 Andrew Benton 2004-08-24 01:11:26 UTC
Thanks for the patch.
Comment 10 Andrew Pinski 2005-11-29 23:23:37 UTC
(In reply to comment #1)
> This is a duplicate of 11242 which was (incorrectly) closed.
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11242
That is because it was not reported against mingw32 but a GNU/Linux OS.  Anyways the mingw32 issue is a different problem and should get its own bug.

The reiser4 issue is not a GCC bug but rather a bug in how things are being returned from either the kernel (reiser4's module) or glibc.  And don't say it should not return NOTDIR because that really does not make sense.  I should note that even HFS+ does the correct thing for access failures when accessing named forks.
Comment 11 Ed Catmur 2005-11-29 23:55:35 UTC
This is not invalid. Yes, reiser4 is broken, but so is gcc.

gcc (3.4.4, I haven't used 4.x yet) dies when it encounters an inaccessible directory as a subdirectory of a member of the include path. See comment 6.
Comment 12 Tom Tromey 2007-01-21 03:23:25 UTC
One odd thing here is that if -Werror is given, then an inaccessible
directory will cause a compilation failure.

I would prefer we not check this patch in.  I don't think there is
any "obviously correct" behavior on EACCES, but in general it seems
to me that EACCES during the search for include files probably represents
a problem with the user's setup -- something the user would want to
be notified about.
Comment 13 Manuel López-Ibáñez 2007-11-14 02:02:11 UTC
Ed,

I don't see why this is different from the case where the header file cannot be opened. And in that case, as Tom says, it seems like there is some problem with the filesystem setup that the user should be aware of.
Comment 14 Ed Catmur 2007-11-14 21:16:38 UTC
(In reply to comment #13)
> I don't see why this is different from the case where the header file cannot be
> opened.
It isn't, I guess - is there a bug about that?

> And in that case, as Tom says, it seems like there is some problem with
> the filesystem setup that the user should be aware of.
And if the user /is/ aware of the problem and isn't in a position to fix it?  Better to warn the user, and error out if -Werror is given.
Comment 15 Richard Biener 2008-01-25 20:32:53 UTC
Closing as of comment #12; the issue can be worked around by re-shuffling include
paths to put those that work first.