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

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

DEFINITIONS

This source file includes following definitions.
  1. is_inheritable
  2. zero
  3. is_mode
  4. main

   1 /* Test duplicating non-inheritable 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 
  19 #include <config.h>
  20 
  21 #include "cloexec.h"
  22 
  23 #include <errno.h>
  24 #include <fcntl.h>
  25 #include <unistd.h>
  26 
  27 #if defined _WIN32 && ! defined __CYGWIN__
  28 /* Get declarations of the native Windows API functions.  */
  29 # define WIN32_LEAN_AND_MEAN
  30 # include <windows.h>
  31 /* Get _get_osfhandle.  */
  32 # if GNULIB_MSVC_NOTHROW
  33 #  include "msvc-nothrow.h"
  34 # else
  35 #  include <io.h>
  36 # endif
  37 #endif
  38 
  39 #include "binary-io.h"
  40 #include "macros.h"
  41 
  42 /* Return non-zero if FD is open and inheritable across exec/spawn.  */
  43 static int
  44 is_inheritable (int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46 #if defined _WIN32 && ! defined __CYGWIN__
  47   /* On native Windows, the initial state of unassigned standard file
  48      descriptors is that they are open but point to an
  49      INVALID_HANDLE_VALUE, and there is no fcntl.  */
  50   HANDLE h = (HANDLE) _get_osfhandle (fd);
  51   DWORD flags;
  52   if (h == INVALID_HANDLE_VALUE || GetHandleInformation (h, &flags) == 0)
  53     return 0;
  54   return (flags & HANDLE_FLAG_INHERIT) != 0;
  55 #else
  56 # ifndef F_GETFD
  57 #  error Please port fcntl to your platform
  58 # endif
  59   int i = fcntl (fd, F_GETFD);
  60   return 0 <= i && (i & FD_CLOEXEC) == 0;
  61 #endif
  62 }
  63 
  64 #if !O_BINARY
  65 # define set_binary_mode(f,m) zero ()
  66 static int zero (void) { return 0; }
     /* [previous][next][first][last][top][bottom][index][help] */
  67 #endif
  68 
  69 /* Return non-zero if FD is open in the given MODE, which is either
  70    O_TEXT or O_BINARY.  */
  71 static int
  72 is_mode (int fd, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74   int value = set_binary_mode (fd, O_BINARY);
  75   set_binary_mode (fd, value);
  76   return mode == value;
  77 }
  78 
  79 int
  80 main (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82   const char *file = "test-cloexec.tmp";
  83   int fd = creat (file, 0600);
  84   int fd2;
  85   int bad_fd = getdtablesize ();
  86 
  87   /* Assume std descriptors were provided by invoker.  */
  88   ASSERT (STDERR_FILENO < fd);
  89   ASSERT (is_inheritable (fd));
  90 
  91   /* Normal use of set_cloexec_flag.  */
  92   ASSERT (set_cloexec_flag (fd, true) == 0);
  93 #if !(defined _WIN32 && ! defined __CYGWIN__)
  94   ASSERT (!is_inheritable (fd));
  95 #endif
  96   ASSERT (set_cloexec_flag (fd, false) == 0);
  97   ASSERT (is_inheritable (fd));
  98 
  99   /* Normal use of dup_cloexec.  */
 100   fd2 = dup_cloexec (fd);
 101   ASSERT (fd < fd2);
 102   ASSERT (!is_inheritable (fd2));
 103   ASSERT (close (fd) == 0);
 104   ASSERT (dup_cloexec (fd2) == fd);
 105   ASSERT (!is_inheritable (fd));
 106   ASSERT (close (fd2) == 0);
 107 
 108   /* On systems that distinguish between text and binary mode,
 109      dup_cloexec reuses the mode of the source.  */
 110   set_binary_mode (fd, O_BINARY);
 111   ASSERT (is_mode (fd, O_BINARY));
 112   fd2 = dup_cloexec (fd);
 113   ASSERT (fd < fd2);
 114   ASSERT (is_mode (fd2, O_BINARY));
 115   ASSERT (close (fd2) == 0);
 116   set_binary_mode (fd, O_TEXT);
 117   ASSERT (is_mode (fd, O_TEXT));
 118   fd2 = dup_cloexec (fd);
 119   ASSERT (fd < fd2);
 120   ASSERT (is_mode (fd2, O_TEXT));
 121   ASSERT (close (fd2) == 0);
 122 
 123   /* Test error handling.  */
 124   errno = 0;
 125   ASSERT (set_cloexec_flag (-1, false) == -1);
 126   ASSERT (errno == EBADF);
 127   errno = 0;
 128   ASSERT (set_cloexec_flag (bad_fd, false) == -1);
 129   ASSERT (errno == EBADF);
 130   errno = 0;
 131   ASSERT (set_cloexec_flag (fd2, false) == -1);
 132   ASSERT (errno == EBADF);
 133   errno = 0;
 134   ASSERT (dup_cloexec (-1) == -1);
 135   ASSERT (errno == EBADF);
 136   errno = 0;
 137   ASSERT (dup_cloexec (bad_fd) == -1);
 138   ASSERT (errno == EBADF);
 139   errno = 0;
 140   ASSERT (dup_cloexec (fd2) == -1);
 141   ASSERT (errno == EBADF);
 142 
 143   /* Clean up.  */
 144   ASSERT (close (fd) == 0);
 145   ASSERT (unlink (file) == 0);
 146 
 147   return 0;
 148 }

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