Lely core libraries  2.2.5
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 
39 static int pipe(HANDLE fildes[2]);
40 #endif
41 
42 static 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 
49 int
50 io_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__)) && defined(_GNU_SOURCE)
63  if (pipe2(fd, O_CLOEXEC) == -1) {
64 #else
65  if (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 (fcntl(fd[0], F_SETFD, FD_CLOEXEC) == -1) {
73  errc = get_errc();
74  goto error_fcntl;
75  }
76  if (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 (!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 (!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 
101 error_alloc_handle_vector_1:
102  handle_vector[1] = IO_HANDLE_ERROR;
103  io_handle_free(handle_vector[0]);
104 error_alloc_handle_vector_0:
105  handle_vector[0] = IO_HANDLE_ERROR;
106 #if _POSIX_C_SOURCE >= 200112L && !defined(__CYGINW__) && !defined(__linux__)
107 error_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
116 error_pipe:
117  set_errc(errc);
118  return -1;
119 }
120 
121 #ifdef _WIN32
122 static int
123 pipe(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 (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 (fildes[1] == INVALID_HANDLE_VALUE) {
147  dwErrCode = GetLastError();
148  goto error_CreateFileA;
149  }
150 
151  return 0;
152 
153 error_CreateFileA:
154  CloseHandle(fildes[0]);
155  fildes[0] = INVALID_HANDLE_VALUE;
156 error_CreateNamedPipeA:
157  SetLastError(dwErrCode);
158  return -1;
159 }
160 #endif
161 
162 #endif // _WIN32 || _POSIX_C_SOURCE >= 200112L
io_handle_vtab::type
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
get_errc
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
io_handle
An I/O device handle.
Definition: handle.h:41
io_handle_acquire
io_handle_t io_handle_acquire(io_handle_t handle)
Increments the reference count of an I/O device handle.
Definition: handle.c:32
pipe.h
io_handle_alloc
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
set_errc
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
io.h
IO_HANDLE_ERROR
#define IO_HANDLE_ERROR
The value of an invalid I/O device handle.
Definition: io.h:34
stdio.h
default.h
io_handle_vtab
The virtual table of an I/O device handle.
Definition: handle.h:74
io_open_pipe
int io_open_pipe(io_handle_t handle_vector[2])
Opens a pipe.
Definition: pipe.c:50
io_handle::fd
int fd
The native file descriptor.
Definition: handle.h:56
IO_TYPE_PIPE
@ IO_TYPE_PIPE
A pipe.
Definition: io.h:51
io_handle_free
void io_handle_free(struct io_handle *handle)
Frees an I/O device handle.
Definition: handle.c:116