root/maint/gnulib/tests/test-dup3.c

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

DEFINITIONS

This source file includes following definitions.
  1. is_open
  2. is_cloexec
  3. main

   1 /* Test duplicating file descriptors.
   2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Eric Blake <ebb9@byu.net>, 2009,
  18    and Bruno Haible <bruno@clisp.org>, 2009.  */
  19 
  20 #include <config.h>
  21 
  22 #include <unistd.h>
  23 
  24 #include "signature.h"
  25 SIGNATURE_CHECK (dup3, int, (int, int, int));
  26 
  27 #include <errno.h>
  28 #include <fcntl.h>
  29 #include <stdbool.h>
  30 
  31 #if defined _WIN32 && ! defined __CYGWIN__
  32 /* Get declarations of the native Windows API functions.  */
  33 # define WIN32_LEAN_AND_MEAN
  34 # include <windows.h>
  35 /* Get _get_osfhandle.  */
  36 # if GNULIB_MSVC_NOTHROW
  37 #  include "msvc-nothrow.h"
  38 # else
  39 #  include <io.h>
  40 # endif
  41 #endif
  42 
  43 #include "binary-io.h"
  44 #include "macros.h"
  45 
  46 /* Return true if FD is open.  */
  47 static bool
  48 is_open (int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
  49 {
  50 #if defined _WIN32 && ! defined __CYGWIN__
  51   /* On native Windows, the initial state of unassigned standard file
  52      descriptors is that they are open but point to an
  53      INVALID_HANDLE_VALUE, and there is no fcntl.  */
  54   return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
  55 #else
  56 # ifndef F_GETFL
  57 #  error Please port fcntl to your platform
  58 # endif
  59   return 0 <= fcntl (fd, F_GETFL);
  60 #endif
  61 }
  62 
  63 /* Return true if FD is not inherited to child processes.  */
  64 static bool
  65 is_cloexec (int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67 #if defined _WIN32 && ! defined __CYGWIN__
  68   HANDLE h = (HANDLE) _get_osfhandle (fd);
  69   DWORD flags;
  70   ASSERT (GetHandleInformation (h, &flags));
  71   return (flags & HANDLE_FLAG_INHERIT) == 0;
  72 #else
  73   int flags;
  74   ASSERT ((flags = fcntl (fd, F_GETFD)) >= 0);
  75   return (flags & FD_CLOEXEC) != 0;
  76 #endif
  77 }
  78 
  79 int
  80 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82   int use_cloexec;
  83   int bad_fd = getdtablesize ();
  84 
  85 #if O_CLOEXEC
  86   for (use_cloexec = 0; use_cloexec <= 1; use_cloexec++)
  87 #else
  88   use_cloexec = 0;
  89 #endif
  90     {
  91       const char *file = "test-dup3.tmp";
  92       int fd = open (file, O_CREAT | O_TRUNC | O_RDWR, 0600);
  93       int o_flags;
  94       char buffer[1];
  95 
  96       o_flags = 0;
  97 #if O_CLOEXEC
  98       if (use_cloexec)
  99         o_flags |= O_CLOEXEC;
 100 #endif
 101 
 102       /* Assume std descriptors were provided by invoker.  */
 103       ASSERT (STDERR_FILENO < fd);
 104       ASSERT (is_open (fd));
 105       /* Ignore any other fd's leaked into this process.  */
 106       close (fd + 1);
 107       close (fd + 2);
 108       ASSERT (!is_open (fd + 1));
 109       ASSERT (!is_open (fd + 2));
 110 
 111       /* Assigning to self is invalid.  */
 112       errno = 0;
 113       ASSERT (dup3 (fd, fd, o_flags) == -1);
 114       ASSERT (errno == EINVAL);
 115       ASSERT (is_open (fd));
 116 
 117       /* If the source is not open, then the destination is unaffected.  */
 118       errno = 0;
 119       ASSERT (dup3 (fd + 1, fd + 2, o_flags) == -1);
 120       ASSERT (errno == EBADF);
 121       ASSERT (!is_open (fd + 2));
 122       errno = 0;
 123       ASSERT (dup3 (fd + 1, fd, o_flags) == -1);
 124       ASSERT (errno == EBADF);
 125       ASSERT (is_open (fd));
 126 
 127       /* The destination must be valid.  */
 128       errno = 0;
 129       ASSERT (dup3 (fd, -2, o_flags) == -1);
 130       ASSERT (errno == EBADF);
 131       if (bad_fd > 256)
 132         {
 133           ASSERT (dup3 (fd, 255, 0) == 255);
 134           ASSERT (dup3 (fd, 256, 0) == 256);
 135           ASSERT (close (255) == 0);
 136           ASSERT (close (256) == 0);
 137         }
 138       ASSERT (dup3 (fd, bad_fd - 1, 0) == bad_fd - 1);
 139       ASSERT (close (bad_fd - 1) == 0);
 140       errno = 0;
 141       ASSERT (dup3 (fd, bad_fd, o_flags) == -1);
 142       ASSERT (errno == EBADF);
 143 
 144       /* Using dup3 can skip fds.  */
 145       ASSERT (dup3 (fd, fd + 2, o_flags) == fd + 2);
 146       ASSERT (is_open (fd));
 147       ASSERT (!is_open (fd + 1));
 148       ASSERT (is_open (fd + 2));
 149       if (use_cloexec)
 150         ASSERT (is_cloexec (fd + 2));
 151       else
 152         ASSERT (!is_cloexec (fd + 2));
 153 
 154       /* Verify that dup3 closes the previous occupant of a fd.  */
 155       ASSERT (open ("/dev/null", O_WRONLY, 0600) == fd + 1);
 156       ASSERT (dup3 (fd + 1, fd, o_flags) == fd);
 157       ASSERT (close (fd + 1) == 0);
 158       ASSERT (write (fd, "1", 1) == 1);
 159       ASSERT (dup3 (fd + 2, fd, o_flags) == fd);
 160       ASSERT (lseek (fd, 0, SEEK_END) == 0);
 161       ASSERT (write (fd + 2, "2", 1) == 1);
 162       ASSERT (lseek (fd, 0, SEEK_SET) == 0);
 163       ASSERT (read (fd, buffer, 1) == 1);
 164       ASSERT (*buffer == '2');
 165 
 166       /* Clean up.  */
 167       ASSERT (close (fd + 2) == 0);
 168       ASSERT (close (fd) == 0);
 169       ASSERT (unlink (file) == 0);
 170     }
 171 
 172   return 0;
 173 }

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