root/maint/gnulib/lib/pipe2.c

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

DEFINITIONS

This source file includes following definitions.
  1. pipe2

   1 /* Create a pipe, with specific opening flags.
   2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
   3 
   4    This file is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU Lesser General Public License as
   6    published by the Free Software Foundation; either version 2.1 of the
   7    License, or (at your option) any later version.
   8 
   9    This file 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 Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 #include <config.h>
  18 
  19 /* Specification.  */
  20 #include <unistd.h>
  21 
  22 #include <errno.h>
  23 #include <fcntl.h>
  24 
  25 #include "binary-io.h"
  26 #include "verify.h"
  27 
  28 #if GNULIB_defined_O_NONBLOCK
  29 # include "nonblocking.h"
  30 #endif
  31 
  32 #if defined _WIN32 && ! defined __CYGWIN__
  33 /* Native Windows API.  */
  34 
  35 # include <io.h>
  36 
  37 #endif
  38 
  39 int
  40 pipe2 (int fd[2], int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42   /* Mingw _pipe() corrupts fd on failure; also, if we succeed at
  43      creating the pipe but later fail at changing fcntl, we want
  44      to leave fd unchanged: http://austingroupbugs.net/view.php?id=467  */
  45   int tmp[2];
  46   tmp[0] = fd[0];
  47   tmp[1] = fd[1];
  48 
  49 #if HAVE_PIPE2
  50 # undef pipe2
  51   /* Try the system call first, if it exists.  (We may be running with a glibc
  52      that has the function but with an older kernel that lacks it.)  */
  53   {
  54     /* Cache the information whether the system call really exists.  */
  55     static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */
  56     if (have_pipe2_really >= 0)
  57       {
  58         int result = pipe2 (fd, flags);
  59         if (!(result < 0 && errno == ENOSYS))
  60           {
  61             have_pipe2_really = 1;
  62             return result;
  63           }
  64         have_pipe2_really = -1;
  65       }
  66   }
  67 #endif
  68 
  69   /* Check the supported flags.  */
  70   if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0)
  71     {
  72       errno = EINVAL;
  73       return -1;
  74     }
  75 
  76 #if defined _WIN32 && ! defined __CYGWIN__
  77 /* Native Windows API.  */
  78 
  79   if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0)
  80     {
  81       fd[0] = tmp[0];
  82       fd[1] = tmp[1];
  83       return -1;
  84     }
  85 
  86   /* O_NONBLOCK handling.
  87      On native Windows platforms, O_NONBLOCK is defined by gnulib.  Use the
  88      functions defined by the gnulib module 'nonblocking'.  */
  89 # if GNULIB_defined_O_NONBLOCK
  90   if (flags & O_NONBLOCK)
  91     {
  92       if (set_nonblocking_flag (fd[0], true) != 0
  93           || set_nonblocking_flag (fd[1], true) != 0)
  94         goto fail;
  95     }
  96 # else
  97   {
  98     verify (O_NONBLOCK == 0);
  99   }
 100 # endif
 101 
 102   return 0;
 103 
 104 #else
 105 /* Unix API.  */
 106 
 107   if (pipe (fd) < 0)
 108     return -1;
 109 
 110   /* POSIX <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
 111      says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on
 112      both fd[0] and fd[1].  */
 113 
 114   /* O_NONBLOCK handling.
 115      On Unix platforms, O_NONBLOCK is defined by the system.  Use fcntl().  */
 116   if (flags & O_NONBLOCK)
 117     {
 118       int fcntl_flags;
 119 
 120       if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0
 121           || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1
 122           || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0
 123           || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1)
 124         goto fail;
 125     }
 126 
 127   if (flags & O_CLOEXEC)
 128     {
 129       int fcntl_flags;
 130 
 131       if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0
 132           || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1
 133           || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0
 134           || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1)
 135         goto fail;
 136     }
 137 
 138 # if O_BINARY
 139   if (flags & O_BINARY)
 140     {
 141       set_binary_mode (fd[1], O_BINARY);
 142       set_binary_mode (fd[0], O_BINARY);
 143     }
 144   else if (flags & O_TEXT)
 145     {
 146       set_binary_mode (fd[1], O_TEXT);
 147       set_binary_mode (fd[0], O_TEXT);
 148     }
 149 # endif
 150 
 151   return 0;
 152 
 153 #endif
 154 
 155 #if GNULIB_defined_O_NONBLOCK || !(defined _WIN32 && ! defined __CYGWIN__)
 156  fail:
 157   {
 158     int saved_errno = errno;
 159     close (fd[0]);
 160     close (fd[1]);
 161     fd[0] = tmp[0];
 162     fd[1] = tmp[1];
 163     errno = saved_errno;
 164     return -1;
 165   }
 166 #endif
 167 }

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