root/maint/gnulib/lib/dup2.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dup2_nothrow
  2. ms_windows_dup2
  3. klibc_dup2dirfd
  4. klibc_dup2
  5. rpl_dup2

   1 /* Duplicate an open file descriptor to a specified file descriptor.
   2 
   3    Copyright (C) 1999, 2004-2007, 2009-2021 Free Software Foundation, Inc.
   4 
   5    This file is free software: you can redistribute it and/or modify
   6    it under the terms of the GNU Lesser General Public License as
   7    published by the Free Software Foundation; either version 2.1 of the
   8    License, or (at your option) any later version.
   9 
  10    This file is distributed in the hope that it will be useful,
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13    GNU Lesser General Public License for more details.
  14 
  15    You should have received a copy of the GNU Lesser General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 /* written by Paul Eggert */
  19 
  20 #include <config.h>
  21 
  22 /* Specification.  */
  23 #include <unistd.h>
  24 
  25 #include <errno.h>
  26 #include <fcntl.h>
  27 
  28 #undef dup2
  29 
  30 #if defined _WIN32 && ! defined __CYGWIN__
  31 
  32 /* Get declarations of the native Windows API functions.  */
  33 # define WIN32_LEAN_AND_MEAN
  34 # include <windows.h>
  35 
  36 # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
  37 #  include "msvc-inval.h"
  38 # endif
  39 
  40 /* Get _get_osfhandle.  */
  41 # if GNULIB_MSVC_NOTHROW
  42 #  include "msvc-nothrow.h"
  43 # else
  44 #  include <io.h>
  45 # endif
  46 
  47 # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
  48 static int
  49 dup2_nothrow (int fd, int desired_fd)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51   int result;
  52 
  53   TRY_MSVC_INVAL
  54     {
  55       result = _dup2 (fd, desired_fd);
  56     }
  57   CATCH_MSVC_INVAL
  58     {
  59       errno = EBADF;
  60       result = -1;
  61     }
  62   DONE_MSVC_INVAL;
  63 
  64   return result;
  65 }
  66 # else
  67 #  define dup2_nothrow _dup2
  68 # endif
  69 
  70 static int
  71 ms_windows_dup2 (int fd, int desired_fd)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73   int result;
  74 
  75   /* If fd is closed, mingw hangs on dup2 (fd, fd).  If fd is open,
  76      dup2 (fd, fd) returns 0, but all further attempts to use fd in
  77      future dup2 calls will hang.  */
  78   if (fd == desired_fd)
  79     {
  80       if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
  81         {
  82           errno = EBADF;
  83           return -1;
  84         }
  85       return fd;
  86     }
  87 
  88   /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
  89      https://bugs.winehq.org/show_bug.cgi?id=21289 */
  90   if (desired_fd < 0)
  91     {
  92       errno = EBADF;
  93       return -1;
  94     }
  95 
  96   result = dup2_nothrow (fd, desired_fd);
  97 
  98   if (result == 0)
  99     result = desired_fd;
 100 
 101   return result;
 102 }
 103 
 104 # define dup2 ms_windows_dup2
 105 
 106 #elif defined __KLIBC__
 107 
 108 # include <InnoTekLIBC/backend.h>
 109 
 110 static int
 111 klibc_dup2dirfd (int fd, int desired_fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 112 {
 113   int tempfd;
 114   int dupfd;
 115 
 116   tempfd = open ("NUL", O_RDONLY);
 117   if (tempfd == -1)
 118     return -1;
 119 
 120   if (tempfd == desired_fd)
 121     {
 122       close (tempfd);
 123 
 124       char path[_MAX_PATH];
 125       if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
 126         return -1;
 127 
 128       return open(path, O_RDONLY);
 129     }
 130 
 131   dupfd = klibc_dup2dirfd (fd, desired_fd);
 132 
 133   close (tempfd);
 134 
 135   return dupfd;
 136 }
 137 
 138 static int
 139 klibc_dup2 (int fd, int desired_fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 140 {
 141   int dupfd;
 142   struct stat sbuf;
 143 
 144   dupfd = dup2 (fd, desired_fd);
 145   if (dupfd == -1 && errno == ENOTSUP \
 146       && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
 147     {
 148       close (desired_fd);
 149 
 150       return klibc_dup2dirfd (fd, desired_fd);
 151     }
 152 
 153   return dupfd;
 154 }
 155 
 156 # define dup2 klibc_dup2
 157 #endif
 158 
 159 int
 160 rpl_dup2 (int fd, int desired_fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162   int result;
 163 
 164 #ifdef F_GETFL
 165   /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
 166      On Cygwin 1.5.x, dup2 (1, 1) returns 0.
 167      On Cygwin 1.7.17, dup2 (1, -1) dumps core.
 168      On Cygwin 1.7.25, dup2 (1, 256) can dump core.
 169      On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC.  */
 170 # if HAVE_SETDTABLESIZE
 171   setdtablesize (desired_fd + 1);
 172 # endif
 173   if (desired_fd < 0)
 174     fd = desired_fd;
 175   if (fd == desired_fd)
 176     return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
 177 #endif
 178 
 179   result = dup2 (fd, desired_fd);
 180 
 181   /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x.  */
 182   if (result == -1 && errno == EMFILE)
 183     errno = EBADF;
 184 #if REPLACE_FCHDIR
 185   if (fd != desired_fd && result != -1)
 186     result = _gl_register_dup (fd, result);
 187 #endif
 188   return result;
 189 }

/* [previous][next][first][last][top][bottom][index][help] */