Lely core libraries 2.3.4
pipe.c
Go to the documentation of this file.
1
24#include "io.h"
25
26#if !LELY_NO_STDIO
27
28#include <lely/io/pipe.h>
29
30#include "default.h"
31
32#if _WIN32 || _POSIX_C_SOURCE >= 200112L
33
34#if _WIN32
35#include <lely/libc/stdio.h>
36
37#ifdef __MINGW32__
38// Ignore complaints that "I64" is not a valid ISO C length modifier.
39#pragma GCC diagnostic ignored "-Wformat"
40#pragma GCC diagnostic ignored "-Wformat-extra-args"
41#endif
42
43static int pipe(HANDLE fildes[2]);
44#endif
45
46static const struct io_handle_vtab pipe_vtab = { .type = IO_TYPE_PIPE,
47 .size = sizeof(struct io_handle),
48 .fini = &default_fini,
49 .flags = &default_flags,
50 .read = &default_read,
51 .write = &default_write };
52
53int
54io_open_pipe(io_handle_t handle_vector[2])
55{
56 assert(handle_vector);
57 handle_vector[0] = handle_vector[1] = IO_HANDLE_ERROR;
58
59 int errc = 0;
60
61#if _WIN32
62 HANDLE fd[2];
63#else
64 int fd[2];
65#endif
66#if (defined(__CYGWIN__) || defined(__linux__)) && defined(_GNU_SOURCE)
67 if (pipe2(fd, O_CLOEXEC) == -1) {
68#else
69 if (pipe(fd) == -1) {
70#endif
71 errc = get_errc();
72 goto error_pipe;
73 }
74
75#if _POSIX_C_SOURCE >= 200112L && !defined(__CYGINW__) && !defined(__linux__)
76 if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) == -1) {
77 errc = get_errc();
78 goto error_fcntl;
79 }
80 if (fcntl(fd[1], F_SETFD, FD_CLOEXEC) == -1) {
81 errc = get_errc();
82 goto error_fcntl;
83 }
84#endif
85
86 handle_vector[0] = io_handle_alloc(&pipe_vtab);
87 if (!handle_vector[0]) {
88 errc = get_errc();
89 goto error_alloc_handle_vector_0;
90 }
91 handle_vector[0]->fd = fd[0];
92
93 handle_vector[1] = io_handle_alloc(&pipe_vtab);
94 if (!handle_vector[1]) {
95 errc = get_errc();
96 goto error_alloc_handle_vector_1;
97 }
98 handle_vector[1]->fd = fd[1];
99
100 io_handle_acquire(handle_vector[0]);
101 io_handle_acquire(handle_vector[1]);
102
103 return 0;
104
105error_alloc_handle_vector_1:
106 handle_vector[1] = IO_HANDLE_ERROR;
107 io_handle_free(handle_vector[0]);
108error_alloc_handle_vector_0:
109 handle_vector[0] = IO_HANDLE_ERROR;
110#if _POSIX_C_SOURCE >= 200112L && !defined(__CYGINW__) && !defined(__linux__)
111error_fcntl:
112#endif
113#if _WIN32
114 CloseHandle(fd[1]);
115 CloseHandle(fd[0]);
116#else
117 close(fd[1]);
118 close(fd[0]);
119#endif
120error_pipe:
121 set_errc(errc);
122 return -1;
123}
124
125#if _WIN32
126static int
127pipe(HANDLE fildes[2])
128{
129 assert(fildes);
130 fildes[0] = fildes[1] = INVALID_HANDLE_VALUE;
131
132 DWORD dwErrCode = 0;
133
134 CHAR Name[MAX_PATH] = { 0 };
135 static LONGLONG cnt;
136 snprintf(Name, sizeof(Name) - 1,
137 "\\\\.\\pipe\\lely-io-pipe-%04lx-%08I64x",
138 GetCurrentProcessId(), InterlockedIncrement64(&cnt));
139
140 fildes[0] = CreateNamedPipeA(Name,
141 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
142 PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1, 1, 0, NULL);
143 if (fildes[0] == INVALID_HANDLE_VALUE) {
144 dwErrCode = GetLastError();
145 goto error_CreateNamedPipeA;
146 }
147
148 fildes[1] = CreateFileA(Name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
149 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
150 if (fildes[1] == INVALID_HANDLE_VALUE) {
151 dwErrCode = GetLastError();
152 goto error_CreateFileA;
153 }
154
155 return 0;
156
157error_CreateFileA:
158 CloseHandle(fildes[0]);
159 fildes[0] = INVALID_HANDLE_VALUE;
160error_CreateNamedPipeA:
161 SetLastError(dwErrCode);
162 return -1;
163}
164#endif
165
166#endif // _WIN32 || _POSIX_C_SOURCE >= 200112L
167
168#endif // !LELY_NO_STDIO
This is the internal header file of the default implementation of the I/O device handle methods.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition errnum.c:932
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition errnum.c:944
void io_handle_free(struct io_handle *handle)
Frees an I/O device handle.
Definition handle.c:120
struct io_handle * io_handle_alloc(const struct io_handle_vtab *vtab)
Allocates a new I/O device handle from a virtual table.
Definition handle.c:81
@ IO_TYPE_PIPE
A pipe.
Definition io.h:51
io_handle_t io_handle_acquire(io_handle_t handle)
Increments the reference count of an I/O device handle.
Definition handle.c:36
#define IO_HANDLE_ERROR
The value of an invalid I/O device handle.
Definition io.h:34
int io_open_pipe(io_handle_t handle_vector[2])
Opens a pipe.
Definition pipe.c:54
This header file is part of the I/O library; it contains the pipe declarations.
This is the internal header file of the Windows-specific I/O declarations.
This header file is part of the C11 and POSIX compatibility library; it includes <stdio....
The virtual table of an I/O device handle.
Definition handle.h:66
int type
The type of the device (one of IO_TYPE_CAN, IO_TYPE_FILE, IO_TYPE_PIPE, IO_TYPE_SERIAL or IO_TYPE_SOC...
Definition handle.h:71
An I/O device handle.
Definition handle.h:33
int fd
The native file descriptor.
Definition handle.h:48