]> Savannah Git Hosting - gnulib.git/commitdiff
openat: port lowest-fd to native MS-Windows
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 12 Nov 2024 00:25:50 +0000 (16:25 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 12 Nov 2024 00:26:13 +0000 (16:26 -0800)
Problem reported by Bruno Haible in:
https://lists.gnu.org/r/bug-gnulib/2024-11/msg00081.html
* lib/openat.c (openat_permissive): When save_cwd allocates an FD,
allocate another one DFD and then close FD so that the later
open returns FD (the lowest available fd), as POSIX requires.

ChangeLog
lib/openat.c

index 29e63351b58059ba351f6f98fbf364017e9260e8..348fd1d27ddaecf862fb9af6ee2cad4065ea1d46 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2024-11-11  Paul Eggert  <eggert@cs.ucla.edu>
+
+       openat: port lowest-fd to native MS-Windows
+       Problem reported by Bruno Haible in:
+       https://lists.gnu.org/r/bug-gnulib/2024-11/msg00081.html
+       * lib/openat.c (openat_permissive): When save_cwd allocates an FD,
+       allocate another one DFD and then close FD so that the later
+       open returns FD (the lowest available fd), as POSIX requires.
+
 2024-11-11  Bruno Haible  <bruno@clisp.org>
 
        fts: Fix dependencies (regression 2024-11-06).
index 65cfc5ede42214447681347b03fac57bbc21d3d8..698874427b6aaeba7e4b48a2bd1cf09c7a9ced62 100644 (file)
@@ -220,7 +220,6 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode,
   struct saved_cwd saved_cwd;
   int saved_errno;
   int err;
-  bool save_ok;
 
   if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
     return open (file, flags, mode);
@@ -245,23 +244,35 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode,
       }
   }
 
-  save_ok = (save_cwd (&saved_cwd) == 0);
-  if (! save_ok)
+  bool save_failed = save_cwd (&saved_cwd) < 0;
+
+  /* If save_cwd allocated a descriptor DFD other than FD, do another
+     save_cwd and then close DFD, so that the later open (if successful)
+     returns DFD (the lowest-numbered descriptor) as POSIX requires.  */
+  int dfd = saved_cwd.desc;
+  if (0 <= dfd && dfd != fd)
     {
-      if (! cwd_errno)
-        openat_save_fail (errno);
-      *cwd_errno = errno;
+      save_failed = save_cwd (&saved_cwd) < 0;
+      close (dfd);
+      dfd = saved_cwd.desc;
     }
-  if (0 <= fd && fd == saved_cwd.desc)
+
+  /* If saving the working directory collides with the user's requested fd,
+     then the user's fd must have been closed to begin with.  */
+  if (0 <= dfd && dfd == fd)
     {
-      /* If saving the working directory collides with the user's
-         requested fd, then the user's fd must have been closed to
-         begin with.  */
       free_cwd (&saved_cwd);
       errno = EBADF;
       return -1;
     }
 
+  if (save_failed)
+    {
+      if (! cwd_errno)
+        openat_save_fail (errno);
+      *cwd_errno = errno;
+    }
+
   err = fchdir (fd);
   saved_errno = errno;
 
@@ -269,7 +280,7 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode,
     {
       err = open (file, flags, mode);
       saved_errno = errno;
-      if (save_ok && restore_cwd (&saved_cwd) != 0)
+      if (!save_failed && restore_cwd (&saved_cwd) != 0)
         {
           if (! cwd_errno)
             {