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