~ubuntu-branches/ubuntu/utopic/coreutils/utopic-proposed

« back to all changes in this revision

Viewing changes to lib/pipe2.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-11-28 03:03:42 UTC
  • mfrom: (8.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20121128030342-21zanj8354gas5gr
Tags: 8.20-3ubuntu1
* Resynchronise with Debian.  Remaining changes:
  - Make 'uname -i -p' return the real processor/hardware, instead of
    unknown.
  - Build-depend on gettext:any instead of on gettext, so that apt-get can
    properly resolve build-dependencies on the tool when cross-building.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Create a pipe, with specific opening flags.
 
2
   Copyright (C) 2009-2012 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, or (at your option)
 
7
   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 along
 
15
   with this program; if not, see <http://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 __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)
 
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 __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 <http://www.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
      setmode (fd[1], O_BINARY);
 
142
      setmode (fd[0], O_BINARY);
 
143
    }
 
144
  else if (flags & O_TEXT)
 
145
    {
 
146
      setmode (fd[1], O_TEXT);
 
147
      setmode (fd[0], O_TEXT);
 
148
    }
 
149
# endif
 
150
 
 
151
  return 0;
 
152
 
 
153
#endif
 
154
 
 
155
#if GNULIB_defined_O_NONBLOCK || \
 
156
  !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
 
157
 fail:
 
158
  {
 
159
    int saved_errno = errno;
 
160
    close (fd[0]);
 
161
    close (fd[1]);
 
162
    fd[0] = tmp[0];
 
163
    fd[1] = tmp[1];
 
164
    errno = saved_errno;
 
165
    return -1;
 
166
  }
 
167
#endif
 
168
}