1 //
2 // pipe.cpp
3 //
4 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // Defines _pipe(), which creates a pipe.
7 //
8 #include <corecrt_internal_lowio.h>
9 #include <stdlib.h>
10
11
12
13 // Creates a pipe. The phandles pointer must be a pointer to an array of two
14 // int objects. Upon successful return, phandles[0] is the read handle, and
15 // phandles[1] is the write handle for the pipe. On success, 0 is returned; on
16 // failure, -1 is returned and errno is set.
17 //
18 // The psize is the amount of memory, in bytes, to ask the OS to reserve for the
19 // pipe. The textmode is the text mode that will be given to the pipe.
_pipe(int * const phandles,unsigned const psize,int const textmode)20 extern "C" int __cdecl _pipe(int* const phandles, unsigned const psize, int const textmode)
21 {
22 _VALIDATE_CLEAR_OSSERR_RETURN(phandles != nullptr, EINVAL, -1);
23 phandles[0] = phandles[1] = -1;
24
25 _VALIDATE_CLEAR_OSSERR_RETURN((textmode & ~(_O_NOINHERIT | _O_BINARY | _O_TEXT)) == 0, EINVAL, -1);
26 _VALIDATE_CLEAR_OSSERR_RETURN((textmode & (_O_BINARY | _O_TEXT)) != (_O_BINARY | _O_TEXT), EINVAL, -1);
27
28
29 SECURITY_ATTRIBUTES security_attributes;
30 security_attributes.nLength = sizeof(security_attributes);
31 security_attributes.lpSecurityDescriptor = nullptr;
32 security_attributes.bInheritHandle = (textmode & _O_NOINHERIT) == 0;
33
34
35 // Create the pipe:
36 HANDLE read_handle, write_handle;
37 if (!CreatePipe(&read_handle, &write_handle, &security_attributes, psize))
38 {
39 __acrt_errno_map_os_error(GetLastError());
40 return -1;
41 }
42
43 // Create the CRT read handle for the pipe:
44 int const crt_read_handle = _alloc_osfhnd();
45 if (crt_read_handle == -1)
46 {
47 errno = EMFILE;
48 _doserrno = 0;
49 CloseHandle(read_handle);
50 CloseHandle(write_handle);
51 return -1;
52 }
53
54 __try
55 {
56 _osfile(crt_read_handle) = FOPEN | FPIPE | FTEXT;
57 _textmode(crt_read_handle) = __crt_lowio_text_mode::ansi;
58 _tm_unicode(crt_read_handle) = false;
59 }
60 __finally
61 {
62 __acrt_lowio_unlock_fh(crt_read_handle);
63 }
64 __endtry
65
66 // Create the CRT write handle for the pipe:
67 int const crt_write_handle = _alloc_osfhnd();
68 if (crt_write_handle == -1)
69 {
70 _osfile(crt_read_handle) = 0;
71 errno = EMFILE;
72 _doserrno = 0;
73 CloseHandle(read_handle);
74 CloseHandle(write_handle);
75 return -1;
76 }
77
78 __try
79 {
80 _osfile(crt_write_handle) = FOPEN | FPIPE | FTEXT;
81 _textmode(crt_write_handle) = __crt_lowio_text_mode::ansi;
82 _tm_unicode(crt_write_handle) = false;
83 }
84 __finally
85 {
86 __acrt_lowio_unlock_fh(crt_write_handle);
87 }
88 __endtry
89
90 // Figure out which textmode the file gets:
91 int fmode = 0;
92 _ERRCHECK(_get_fmode(&fmode));
93
94 // The pipe gets binary mode if (a) binary was requested or (b) the
95 // global default fmode was changed to binary.
96 if ((textmode & _O_BINARY) || ((textmode & _O_TEXT) == 0 && fmode == _O_BINARY))
97 {
98 _osfile(crt_read_handle) &= ~FTEXT;
99 _osfile(crt_write_handle) &= ~FTEXT;
100 }
101
102 if (textmode & _O_NOINHERIT)
103 {
104 _osfile(crt_read_handle) |= FNOINHERIT;
105 _osfile(crt_write_handle) |= FNOINHERIT;
106 }
107
108 __acrt_lowio_set_os_handle(crt_read_handle, reinterpret_cast<intptr_t>(read_handle));
109 __acrt_lowio_set_os_handle(crt_write_handle, reinterpret_cast<intptr_t>(write_handle));
110
111 phandles[0] = crt_read_handle;
112 phandles[1] = crt_write_handle;
113
114 return 0;
115 }
116