Should fopen() succeed on a directory?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Should fopen() succeed on a directory?

Adam-29
Why does fopen()ing a directory for reading succeed instead of failing
with EISDIR?  This has the possibly unexpected consequence of letting
you pass yyin to yylex() as a fopen()ed directory, which then thinks it
finished successfully because fread() returns 0 immediately.

Adam

Reply | Threaded
Open this post in threaded view
|

Re: Should fopen() succeed on a directory?

Marco S Hyman
Adam writes:
 > Why does fopen()ing a directory for reading succeed instead of failing
 > with EISDIR?  This has the possibly unexpected consequence of letting

I believe it is so things like "grep -r regex *" work.

// marc

Reply | Threaded
Open this post in threaded view
|

Re: Should fopen() succeed on a directory?

Darrin Chandler
In reply to this post by Adam-29
On Thu, Jan 18, 2007 at 05:17:50PM -0500, Adam wrote:
> Why does fopen()ing a directory for reading succeed instead of failing
> with EISDIR?  This has the possibly unexpected consequence of letting
> you pass yyin to yylex() as a fopen()ed directory, which then thinks it
> finished successfully because fread() returns 0 immediately.

Directories are files and can be open(2)ed as such for reading. Trying
the same for writing *should* give EISDIR.
--
Darrin Chandler            |  Phoenix BSD Users Group
[hidden email]   |  http://bsd.phoenix.az.us/
http://www.stilyagin.com/  |

Reply | Threaded
Open this post in threaded view
|

Re: Should fopen() succeed on a directory?

Adam-29
Darrin Chandler <[hidden email]> wrote:

> On Thu, Jan 18, 2007 at 05:17:50PM -0500, Adam wrote:
> > Why does fopen()ing a directory for reading succeed instead of failing
> > with EISDIR?  This has the possibly unexpected consequence of letting
> > you pass yyin to yylex() as a fopen()ed directory, which then thinks it
> > finished successfully because fread() returns 0 immediately.
>
> Directories are files and can be open(2)ed as such for reading.

We're not talking about the low level open() interface, we're talking
about the abstracted fopen() wrapper.  You can't use fread() on a
fopen()ed directory, and when passed a FILE * you can't tell wether its
a directory or just an empty file.  If you can't fread() from a stream
that is associated with a directory, then why associate the stream with
a directory in the first place?

Adam

Reply | Threaded
Open this post in threaded view
|

Re: Should fopen() succeed on a directory?

Matthew R. Dempsky
On Fri, Jan 19, 2007 at 11:07:14AM -0500, Adam wrote:
> If you can't fread() from a stream
> that is associated with a directory, then why associate the stream with
> a directory in the first place?

Does the C (or any) standard say it should fail?  fopen(3) works on
directories under Linux and Solaris, so OpenBSD certainly isn't unique
in this regard.

Reply | Threaded
Open this post in threaded view
|

Re: Should fopen() succeed on a directory?

Tobias Ulmer
In reply to this post by Adam-29
On Fri, Jan 19, 2007 at 11:07:14AM -0500, Adam wrote:

> Darrin Chandler <[hidden email]> wrote:
>
> > On Thu, Jan 18, 2007 at 05:17:50PM -0500, Adam wrote:
> > > Why does fopen()ing a directory for reading succeed instead of failing
> > > with EISDIR?  This has the possibly unexpected consequence of letting
> > > you pass yyin to yylex() as a fopen()ed directory, which then thinks it
> > > finished successfully because fread() returns 0 immediately.
> >
> > Directories are files and can be open(2)ed as such for reading.
>
> We're not talking about the low level open() interface, we're talking
> about the abstracted fopen() wrapper.  You can't use fread() on a
> fopen()ed directory, and when passed a FILE * you can't tell wether its
> a directory or just an empty file.  If you can't fread() from a stream
> that is associated with a directory, then why associate the stream with
> a directory in the first place?
>
> Adam
>
>

C* doesn't know about directories and makes no assumptions about them.
Directories in Unix happen to be implemented as a file, so that's
perfectly legal. Reading and writing from/to the file depends on the
OS, and the C* standard doesn't require that this must succeed/fail.
If and how it fails is implemented by the OS and documented here:
http://www.opengroup.org/onlinepubs/009695399/functions/fopen.html

use stat(2) before you fopen anything to make sure it's not a
dir/device/etc (race condition...).

Tobias

*C89 + C99

Reply | Threaded
Open this post in threaded view
|

Re: Should fopen() succeed on a directory?

Otto Moerbeek
On Fri, 19 Jan 2007, Tobias Ulmer wrote:

> On Fri, Jan 19, 2007 at 11:07:14AM -0500, Adam wrote:
> > Darrin Chandler <[hidden email]> wrote:
> >
> > > On Thu, Jan 18, 2007 at 05:17:50PM -0500, Adam wrote:
> > > > Why does fopen()ing a directory for reading succeed instead of failing
> > > > with EISDIR?  This has the possibly unexpected consequence of letting
> > > > you pass yyin to yylex() as a fopen()ed directory, which then thinks it
> > > > finished successfully because fread() returns 0 immediately.
> > >
> > > Directories are files and can be open(2)ed as such for reading.
> >
> > We're not talking about the low level open() interface, we're talking
> > about the abstracted fopen() wrapper.  You can't use fread() on a
> > fopen()ed directory, and when passed a FILE * you can't tell wether its
> > a directory or just an empty file.  If you can't fread() from a stream
> > that is associated with a directory, then why associate the stream with
> > a directory in the first place?
> >
> > Adam
> >
> >
>
> C* doesn't know about directories and makes no assumptions about them.
> Directories in Unix happen to be implemented as a file, so that's
> perfectly legal. Reading and writing from/to the file depends on the
> OS, and the C* standard doesn't require that this must succeed/fail.
> If and how it fails is implemented by the OS and documented here:
> http://www.opengroup.org/onlinepubs/009695399/functions/fopen.html
>
> use stat(2) before you fopen anything to make sure it's not a
> dir/device/etc (race condition...).

To avoid that race, use fstat(2) after you've opened.

        -Otto