xref: /netbsd-src/external/gpl3/gdb/dist/gnulib/import/dup2.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
18dffb485Schristos /* Duplicate an open file descriptor to a specified file descriptor.
28dffb485Schristos 
3*4b169a6bSchristos    Copyright (C) 1999, 2004-2007, 2009-2022 Free Software Foundation, Inc.
48dffb485Schristos 
5*4b169a6bSchristos    This file is free software: you can redistribute it and/or modify
6*4b169a6bSchristos    it under the terms of the GNU Lesser General Public License as
7*4b169a6bSchristos    published by the Free Software Foundation; either version 2.1 of the
8*4b169a6bSchristos    License, or (at your option) any later version.
98dffb485Schristos 
10*4b169a6bSchristos    This file is distributed in the hope that it will be useful,
118dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
128dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*4b169a6bSchristos    GNU Lesser General Public License for more details.
148dffb485Schristos 
15*4b169a6bSchristos    You should have received a copy of the GNU Lesser General Public License
168dffb485Schristos    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
178dffb485Schristos 
188dffb485Schristos /* written by Paul Eggert */
198dffb485Schristos 
208dffb485Schristos #include <config.h>
218dffb485Schristos 
228dffb485Schristos /* Specification.  */
238dffb485Schristos #include <unistd.h>
248dffb485Schristos 
258dffb485Schristos #include <errno.h>
268dffb485Schristos #include <fcntl.h>
278dffb485Schristos 
288dffb485Schristos #undef dup2
298dffb485Schristos 
308dffb485Schristos #if defined _WIN32 && ! defined __CYGWIN__
318dffb485Schristos 
328dffb485Schristos /* Get declarations of the native Windows API functions.  */
338dffb485Schristos # define WIN32_LEAN_AND_MEAN
348dffb485Schristos # include <windows.h>
358dffb485Schristos 
368dffb485Schristos # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
378dffb485Schristos #  include "msvc-inval.h"
388dffb485Schristos # endif
398dffb485Schristos 
408dffb485Schristos /* Get _get_osfhandle.  */
418dffb485Schristos # if GNULIB_MSVC_NOTHROW
428dffb485Schristos #  include "msvc-nothrow.h"
438dffb485Schristos # else
448dffb485Schristos #  include <io.h>
458dffb485Schristos # endif
468dffb485Schristos 
478dffb485Schristos # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
488dffb485Schristos static int
dup2_nothrow(int fd,int desired_fd)498dffb485Schristos dup2_nothrow (int fd, int desired_fd)
508dffb485Schristos {
518dffb485Schristos   int result;
528dffb485Schristos 
538dffb485Schristos   TRY_MSVC_INVAL
548dffb485Schristos     {
55*4b169a6bSchristos       result = _dup2 (fd, desired_fd);
568dffb485Schristos     }
578dffb485Schristos   CATCH_MSVC_INVAL
588dffb485Schristos     {
598dffb485Schristos       errno = EBADF;
608dffb485Schristos       result = -1;
618dffb485Schristos     }
628dffb485Schristos   DONE_MSVC_INVAL;
638dffb485Schristos 
648dffb485Schristos   return result;
658dffb485Schristos }
668dffb485Schristos # else
67*4b169a6bSchristos #  define dup2_nothrow _dup2
688dffb485Schristos # endif
698dffb485Schristos 
708dffb485Schristos static int
ms_windows_dup2(int fd,int desired_fd)718dffb485Schristos ms_windows_dup2 (int fd, int desired_fd)
728dffb485Schristos {
738dffb485Schristos   int result;
748dffb485Schristos 
758dffb485Schristos   /* If fd is closed, mingw hangs on dup2 (fd, fd).  If fd is open,
768dffb485Schristos      dup2 (fd, fd) returns 0, but all further attempts to use fd in
778dffb485Schristos      future dup2 calls will hang.  */
788dffb485Schristos   if (fd == desired_fd)
798dffb485Schristos     {
808dffb485Schristos       if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
818dffb485Schristos         {
828dffb485Schristos           errno = EBADF;
838dffb485Schristos           return -1;
848dffb485Schristos         }
858dffb485Schristos       return fd;
868dffb485Schristos     }
878dffb485Schristos 
888dffb485Schristos   /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
898dffb485Schristos      https://bugs.winehq.org/show_bug.cgi?id=21289 */
908dffb485Schristos   if (desired_fd < 0)
918dffb485Schristos     {
928dffb485Schristos       errno = EBADF;
938dffb485Schristos       return -1;
948dffb485Schristos     }
958dffb485Schristos 
968dffb485Schristos   result = dup2_nothrow (fd, desired_fd);
978dffb485Schristos 
988dffb485Schristos   if (result == 0)
998dffb485Schristos     result = desired_fd;
1008dffb485Schristos 
1018dffb485Schristos   return result;
1028dffb485Schristos }
1038dffb485Schristos 
1048dffb485Schristos # define dup2 ms_windows_dup2
1058dffb485Schristos 
1068dffb485Schristos #elif defined __KLIBC__
1078dffb485Schristos 
1088dffb485Schristos # include <InnoTekLIBC/backend.h>
1098dffb485Schristos 
1108dffb485Schristos static int
klibc_dup2dirfd(int fd,int desired_fd)1118dffb485Schristos klibc_dup2dirfd (int fd, int desired_fd)
1128dffb485Schristos {
1138dffb485Schristos   int tempfd;
1148dffb485Schristos   int dupfd;
1158dffb485Schristos 
1168dffb485Schristos   tempfd = open ("NUL", O_RDONLY);
1178dffb485Schristos   if (tempfd == -1)
1188dffb485Schristos     return -1;
1198dffb485Schristos 
1208dffb485Schristos   if (tempfd == desired_fd)
1218dffb485Schristos     {
1228dffb485Schristos       close (tempfd);
1238dffb485Schristos 
1248dffb485Schristos       char path[_MAX_PATH];
1258dffb485Schristos       if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
1268dffb485Schristos         return -1;
1278dffb485Schristos 
1288dffb485Schristos       return open(path, O_RDONLY);
1298dffb485Schristos     }
1308dffb485Schristos 
1318dffb485Schristos   dupfd = klibc_dup2dirfd (fd, desired_fd);
1328dffb485Schristos 
1338dffb485Schristos   close (tempfd);
1348dffb485Schristos 
1358dffb485Schristos   return dupfd;
1368dffb485Schristos }
1378dffb485Schristos 
1388dffb485Schristos static int
klibc_dup2(int fd,int desired_fd)1398dffb485Schristos klibc_dup2 (int fd, int desired_fd)
1408dffb485Schristos {
1418dffb485Schristos   int dupfd;
1428dffb485Schristos   struct stat sbuf;
1438dffb485Schristos 
1448dffb485Schristos   dupfd = dup2 (fd, desired_fd);
1458dffb485Schristos   if (dupfd == -1 && errno == ENOTSUP \
1468dffb485Schristos       && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
1478dffb485Schristos     {
1488dffb485Schristos       close (desired_fd);
1498dffb485Schristos 
1508dffb485Schristos       return klibc_dup2dirfd (fd, desired_fd);
1518dffb485Schristos     }
1528dffb485Schristos 
1538dffb485Schristos   return dupfd;
1548dffb485Schristos }
1558dffb485Schristos 
1568dffb485Schristos # define dup2 klibc_dup2
1578dffb485Schristos #endif
1588dffb485Schristos 
1598dffb485Schristos int
rpl_dup2(int fd,int desired_fd)1608dffb485Schristos rpl_dup2 (int fd, int desired_fd)
1618dffb485Schristos {
1628dffb485Schristos   int result;
1638dffb485Schristos 
1648dffb485Schristos #ifdef F_GETFL
1658dffb485Schristos   /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
1668dffb485Schristos      On Cygwin 1.5.x, dup2 (1, 1) returns 0.
1678dffb485Schristos      On Cygwin 1.7.17, dup2 (1, -1) dumps core.
1688dffb485Schristos      On Cygwin 1.7.25, dup2 (1, 256) can dump core.
1698dffb485Schristos      On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC.  */
1708dffb485Schristos # if HAVE_SETDTABLESIZE
1718dffb485Schristos   setdtablesize (desired_fd + 1);
1728dffb485Schristos # endif
1738dffb485Schristos   if (desired_fd < 0)
1748dffb485Schristos     fd = desired_fd;
1758dffb485Schristos   if (fd == desired_fd)
1768dffb485Schristos     return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
1778dffb485Schristos #endif
1788dffb485Schristos 
1798dffb485Schristos   result = dup2 (fd, desired_fd);
1808dffb485Schristos 
1818dffb485Schristos   /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x.  */
1828dffb485Schristos   if (result == -1 && errno == EMFILE)
1838dffb485Schristos     errno = EBADF;
1848dffb485Schristos #if REPLACE_FCHDIR
1858dffb485Schristos   if (fd != desired_fd && result != -1)
1868dffb485Schristos     result = _gl_register_dup (fd, result);
1878dffb485Schristos #endif
1888dffb485Schristos   return result;
1898dffb485Schristos }
190