root/lib/pipe2.c

/* [<][>][^][v][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-2023 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 
    27 #if GNULIB_defined_O_NONBLOCK
    28 # include "nonblocking.h"
    29 #endif
    30 
    31 #if defined _WIN32 && ! defined __CYGWIN__
    32 /* Native Windows API.  */
    33 
    34 # include <io.h>
    35 
    36 #endif
    37 
    38 int
    39 pipe2 (int fd[2], int flags)
    40 {
    41   /* Mingw _pipe() corrupts fd on failure; also, if we succeed at
    42      creating the pipe but later fail at changing fcntl, we want
    43      to leave fd unchanged: http://austingroupbugs.net/view.php?id=467  */
    44   int tmp[2];
    45   tmp[0] = fd[0];
    46   tmp[1] = fd[1];
    47 
    48 #if HAVE_PIPE2
    49 # undef pipe2
    50   /* Try the system call first, if it exists.  (We may be running with a glibc
    51      that has the function but with an older kernel that lacks it.)  */
    52   {
    53     /* Cache the information whether the system call really exists.  */
    54     static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */
    55     if (have_pipe2_really >= 0)
    56       {
    57         int result = pipe2 (fd, flags);
    58         if (!(result < 0 && errno == ENOSYS))
    59           {
    60             have_pipe2_really = 1;
    61             return result;
    62           }
    63         have_pipe2_really = -1;
    64       }
    65   }
    66 #endif
    67 
    68   /* Check the supported flags.  */
    69   if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0)
    70     {
    71       errno = EINVAL;
    72       return -1;
    73     }
    74 
    75 #if defined _WIN32 && ! defined __CYGWIN__
    76 /* Native Windows API.  */
    77 
    78   if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0)
    79     {
    80       fd[0] = tmp[0];
    81       fd[1] = tmp[1];
    82       return -1;
    83     }
    84 
    85   /* O_NONBLOCK handling.
    86      On native Windows platforms, O_NONBLOCK is defined by gnulib.  Use the
    87      functions defined by the gnulib module 'nonblocking'.  */
    88 # if GNULIB_defined_O_NONBLOCK
    89   if (flags & O_NONBLOCK)
    90     {
    91       if (set_nonblocking_flag (fd[0], true) != 0
    92           || set_nonblocking_flag (fd[1], true) != 0)
    93         goto fail;
    94     }
    95 # else
    96   {
    97     static_assert (O_NONBLOCK == 0);
    98   }
    99 # endif
   100 
   101   return 0;
   102 
   103 #else
   104 /* Unix API.  */
   105 
   106   if (pipe (fd) < 0)
   107     return -1;
   108 
   109   /* POSIX <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
   110      says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on
   111      both fd[0] and fd[1].  */
   112 
   113   /* O_NONBLOCK handling.
   114      On Unix platforms, O_NONBLOCK is defined by the system.  Use fcntl().  */
   115   if (flags & O_NONBLOCK)
   116     {
   117       int fcntl_flags;
   118 
   119       if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0
   120           || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1
   121           || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0
   122           || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1)
   123         goto fail;
   124     }
   125 
   126   if (flags & O_CLOEXEC)
   127     {
   128       int fcntl_flags;
   129 
   130       if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0
   131           || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1
   132           || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0
   133           || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1)
   134         goto fail;
   135     }
   136 
   137 # if O_BINARY
   138   if (flags & O_BINARY)
   139     {
   140       set_binary_mode (fd[1], O_BINARY);
   141       set_binary_mode (fd[0], O_BINARY);
   142     }
   143   else if (flags & O_TEXT)
   144     {
   145       set_binary_mode (fd[1], O_TEXT);
   146       set_binary_mode (fd[0], O_TEXT);
   147     }
   148 # endif
   149 
   150   return 0;
   151 
   152 #endif
   153 
   154 #if GNULIB_defined_O_NONBLOCK || !(defined _WIN32 && ! defined __CYGWIN__)
   155  fail:
   156   {
   157     int saved_errno = errno;
   158     close (fd[0]);
   159     close (fd[1]);
   160     fd[0] = tmp[0];
   161     fd[1] = tmp[1];
   162     errno = saved_errno;
   163     return -1;
   164   }
   165 #endif
   166 }

/* [<][>][^][v][top][bottom][index][help] */