bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fdopendir closes the file descriptor on MinGW


From: Eli Zaretskii
Subject: Re: fdopendir closes the file descriptor on MinGW
Date: Thu, 19 Mar 2015 18:19:39 +0200

> Date: Wed, 18 Mar 2015 13:40:29 -0700
> From: Paul Eggert <address@hidden>
> CC: address@hidden, address@hidden
> 
> On 03/18/2015 01:26 PM, Eli Zaretskii wrote:
> >> Many POSIX systems do that, but POSIX doesn't require it
> > OK, but fdopendir's implementation clearly intends for this to happen,
> > doesn't it?
> 
> On Unix-like systems yes.  I don' t know about Mingw or other platforms 
> where REPLACE_FCHDIR is nonzero.

Well, this bug report clearly indicates that fdopendir's callers
expect the file descriptor to remain valid after fdopendir returns.
And the only way for that to become true is if the call to opendir
will cause a file descriptor to be allocated.

I tried to see if this can be done inside Gnulib's opendir.  However,
doing that would require a change in the database of file descriptors
allocated for directories, which are maintained in fchdir.c, so that
dirfd would be able to identify the directory slot by its DIR pointer.

That seemed too excessive to me, so I suggest the following simpler
change instead:

--- lib/fdopendir.c~0   2015-03-15 22:24:30 +0200
+++ lib/fdopendir.c     2015-03-19 15:06:51 +0200
@@ -156,7 +156,18 @@
       if (! dir && EXPECTED_ERRNO (saved_errno))
         {
           char const *name = _gl_directory_name (fd);
-          return (name ? opendir (name) : NULL);
+          DIR *dp = name ? opendir (name) : NULL;
+          /* The caller expects us to consume a file descriptor, which
+             should be identical to the descriptor on which the
+             directory was open when fdopendir was called.  But if
+             dirfd doesn't return a valid descriptor, it means opendir
+             did not consume a file descriptor (this happens on
+             MS-Windows), so we have to call 'open' by hand.  If we
+             don't do that, the descriptor with which fdopendir was
+             called will no longer be valid when fdopendir returns.  */
+          if (dp && dirfd (dp) < 0)
+            dup (fd);
+          return dp;
         }
 # endif
       errno = saved_errno;

(Instead of 'dup', we could call 'open' here, since we have the
directory name.  But I think using 'dup' is slightly cleaner, since we
don't need to worry about the flags to pass to 'open'.)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]