]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/detail/impl/descriptor_ops.ipp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / asio / detail / impl / descriptor_ops.ipp
CommitLineData
7c673cae
FG
1//
2// detail/impl/descriptor_ops.ipp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
f67539c2 5// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7c673cae
FG
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
12#define BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19#include <cerrno>
20#include <boost/asio/detail/descriptor_ops.hpp>
21#include <boost/asio/error.hpp>
22
23#if !defined(BOOST_ASIO_WINDOWS) \
24 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
25 && !defined(__CYGWIN__)
26
27#include <boost/asio/detail/push_options.hpp>
28
29namespace boost {
30namespace asio {
31namespace detail {
32namespace descriptor_ops {
33
34int open(const char* path, int flags, boost::system::error_code& ec)
35{
20effc67
TL
36 int result = ::open(path, flags);
37 get_last_error(ec, result < 0);
7c673cae
FG
38 return result;
39}
40
41int close(int d, state_type& state, boost::system::error_code& ec)
42{
43 int result = 0;
44 if (d != -1)
45 {
20effc67
TL
46 result = ::close(d);
47 get_last_error(ec, result < 0);
7c673cae
FG
48
49 if (result != 0
50 && (ec == boost::asio::error::would_block
51 || ec == boost::asio::error::try_again))
52 {
53 // According to UNIX Network Programming Vol. 1, it is possible for
54 // close() to fail with EWOULDBLOCK under certain circumstances. What
55 // isn't clear is the state of the descriptor after this error. The one
56 // current OS where this behaviour is seen, Windows, says that the socket
57 // remains open. Therefore we'll put the descriptor back into blocking
58 // mode and have another attempt at closing it.
f67539c2 59#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
7c673cae
FG
60 int flags = ::fcntl(d, F_GETFL, 0);
61 if (flags >= 0)
62 ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
f67539c2 63#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
7c673cae
FG
64 ioctl_arg_type arg = 0;
65 ::ioctl(d, FIONBIO, &arg);
f67539c2 66#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
7c673cae
FG
67 state &= ~non_blocking;
68
20effc67
TL
69 result = ::close(d);
70 get_last_error(ec, result < 0);
7c673cae
FG
71 }
72 }
73
7c673cae
FG
74 return result;
75}
76
77bool set_user_non_blocking(int d, state_type& state,
78 bool value, boost::system::error_code& ec)
79{
80 if (d == -1)
81 {
82 ec = boost::asio::error::bad_descriptor;
83 return false;
84 }
85
f67539c2 86#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
20effc67
TL
87 int result = ::fcntl(d, F_GETFL, 0);
88 get_last_error(ec, result < 0);
7c673cae
FG
89 if (result >= 0)
90 {
7c673cae 91 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
20effc67
TL
92 result = ::fcntl(d, F_SETFL, flag);
93 get_last_error(ec, result < 0);
7c673cae 94 }
f67539c2 95#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
7c673cae 96 ioctl_arg_type arg = (value ? 1 : 0);
20effc67
TL
97 int result = ::ioctl(d, FIONBIO, &arg);
98 get_last_error(ec, result < 0);
f67539c2 99#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
7c673cae
FG
100
101 if (result >= 0)
102 {
7c673cae
FG
103 if (value)
104 state |= user_set_non_blocking;
105 else
106 {
107 // Clearing the user-set non-blocking mode always overrides any
108 // internally-set non-blocking flag. Any subsequent asynchronous
109 // operations will need to re-enable non-blocking I/O.
110 state &= ~(user_set_non_blocking | internal_non_blocking);
111 }
112 return true;
113 }
114
115 return false;
116}
117
118bool set_internal_non_blocking(int d, state_type& state,
119 bool value, boost::system::error_code& ec)
120{
121 if (d == -1)
122 {
123 ec = boost::asio::error::bad_descriptor;
124 return false;
125 }
126
127 if (!value && (state & user_set_non_blocking))
128 {
129 // It does not make sense to clear the internal non-blocking flag if the
130 // user still wants non-blocking behaviour. Return an error and let the
131 // caller figure out whether to update the user-set non-blocking flag.
132 ec = boost::asio::error::invalid_argument;
133 return false;
134 }
135
f67539c2 136#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
20effc67
TL
137 int result = ::fcntl(d, F_GETFL, 0);
138 get_last_error(ec, result < 0);
7c673cae
FG
139 if (result >= 0)
140 {
7c673cae 141 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
20effc67
TL
142 result = ::fcntl(d, F_SETFL, flag);
143 get_last_error(ec, result < 0);
7c673cae 144 }
f67539c2 145#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
7c673cae 146 ioctl_arg_type arg = (value ? 1 : 0);
20effc67
TL
147 int result = ::ioctl(d, FIONBIO, &arg);
148 get_last_error(ec, result < 0);
f67539c2 149#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
7c673cae
FG
150
151 if (result >= 0)
152 {
7c673cae
FG
153 if (value)
154 state |= internal_non_blocking;
155 else
156 state &= ~internal_non_blocking;
157 return true;
158 }
159
160 return false;
161}
162
163std::size_t sync_read(int d, state_type state, buf* bufs,
164 std::size_t count, bool all_empty, boost::system::error_code& ec)
165{
166 if (d == -1)
167 {
168 ec = boost::asio::error::bad_descriptor;
169 return 0;
170 }
171
172 // A request to read 0 bytes on a stream is a no-op.
173 if (all_empty)
174 {
20effc67 175 ec.assign(0, ec.category());
7c673cae
FG
176 return 0;
177 }
178
179 // Read some data.
180 for (;;)
181 {
182 // Try to complete the operation without blocking.
20effc67
TL
183 signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count));
184 get_last_error(ec, bytes < 0);
185
186 // Check if operation succeeded.
187 if (bytes > 0)
188 return bytes;
189
190 // Check for EOF.
191 if (bytes == 0)
192 {
193 ec = boost::asio::error::eof;
194 return 0;
195 }
196
197 // Operation failed.
198 if ((state & user_set_non_blocking)
199 || (ec != boost::asio::error::would_block
200 && ec != boost::asio::error::try_again))
201 return 0;
202
203 // Wait for descriptor to become ready.
204 if (descriptor_ops::poll_read(d, 0, ec) < 0)
205 return 0;
206 }
207}
208
209std::size_t sync_read1(int d, state_type state, void* data,
210 std::size_t size, boost::system::error_code& ec)
211{
212 if (d == -1)
213 {
214 ec = boost::asio::error::bad_descriptor;
215 return 0;
216 }
217
218 // A request to read 0 bytes on a stream is a no-op.
219 if (size == 0)
220 {
221 ec.assign(0, ec.category());
222 return 0;
223 }
224
225 // Read some data.
226 for (;;)
227 {
228 // Try to complete the operation without blocking.
229 signed_size_type bytes = ::read(d, data, size);
230 get_last_error(ec, bytes < 0);
7c673cae
FG
231
232 // Check if operation succeeded.
233 if (bytes > 0)
234 return bytes;
235
236 // Check for EOF.
237 if (bytes == 0)
238 {
239 ec = boost::asio::error::eof;
240 return 0;
241 }
242
243 // Operation failed.
244 if ((state & user_set_non_blocking)
245 || (ec != boost::asio::error::would_block
246 && ec != boost::asio::error::try_again))
247 return 0;
248
249 // Wait for descriptor to become ready.
250 if (descriptor_ops::poll_read(d, 0, ec) < 0)
251 return 0;
252 }
253}
254
255bool non_blocking_read(int d, buf* bufs, std::size_t count,
256 boost::system::error_code& ec, std::size_t& bytes_transferred)
257{
258 for (;;)
259 {
260 // Read some data.
20effc67
TL
261 signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count));
262 get_last_error(ec, bytes < 0);
7c673cae
FG
263
264 // Check for end of stream.
265 if (bytes == 0)
266 {
267 ec = boost::asio::error::eof;
268 return true;
269 }
270
20effc67
TL
271 // Check if operation succeeded.
272 if (bytes > 0)
273 {
274 bytes_transferred = bytes;
275 return true;
276 }
277
7c673cae
FG
278 // Retry operation if interrupted by signal.
279 if (ec == boost::asio::error::interrupted)
280 continue;
281
282 // Check if we need to run the operation again.
283 if (ec == boost::asio::error::would_block
284 || ec == boost::asio::error::try_again)
285 return false;
286
20effc67
TL
287 // Operation failed.
288 bytes_transferred = 0;
289 return true;
290 }
291}
292
293bool non_blocking_read1(int d, void* data, std::size_t size,
294 boost::system::error_code& ec, std::size_t& bytes_transferred)
295{
296 for (;;)
297 {
298 // Read some data.
299 signed_size_type bytes = ::read(d, data, size);
300 get_last_error(ec, bytes < 0);
301
302 // Check for end of stream.
303 if (bytes == 0)
304 {
305 ec = boost::asio::error::eof;
306 return true;
307 }
308
309 // Check if operation succeeded.
7c673cae
FG
310 if (bytes > 0)
311 {
7c673cae 312 bytes_transferred = bytes;
20effc67 313 return true;
7c673cae 314 }
7c673cae 315
20effc67
TL
316 // Retry operation if interrupted by signal.
317 if (ec == boost::asio::error::interrupted)
318 continue;
319
320 // Check if we need to run the operation again.
321 if (ec == boost::asio::error::would_block
322 || ec == boost::asio::error::try_again)
323 return false;
324
325 // Operation failed.
326 bytes_transferred = 0;
7c673cae
FG
327 return true;
328 }
329}
330
331std::size_t sync_write(int d, state_type state, const buf* bufs,
332 std::size_t count, bool all_empty, boost::system::error_code& ec)
333{
334 if (d == -1)
335 {
336 ec = boost::asio::error::bad_descriptor;
337 return 0;
338 }
339
340 // A request to write 0 bytes on a stream is a no-op.
341 if (all_empty)
342 {
20effc67
TL
343 ec.assign(0, ec.category());
344 return 0;
345 }
346
347 // Write some data.
348 for (;;)
349 {
350 // Try to complete the operation without blocking.
351 signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count));
352 get_last_error(ec, bytes < 0);
353
354 // Check if operation succeeded.
355 if (bytes > 0)
356 return bytes;
357
358 // Operation failed.
359 if ((state & user_set_non_blocking)
360 || (ec != boost::asio::error::would_block
361 && ec != boost::asio::error::try_again))
362 return 0;
363
364 // Wait for descriptor to become ready.
365 if (descriptor_ops::poll_write(d, 0, ec) < 0)
366 return 0;
367 }
368}
369
370std::size_t sync_write1(int d, state_type state, const void* data,
371 std::size_t size, boost::system::error_code& ec)
372{
373 if (d == -1)
374 {
375 ec = boost::asio::error::bad_descriptor;
376 return 0;
377 }
378
379 // A request to write 0 bytes on a stream is a no-op.
380 if (size == 0)
381 {
382 ec.assign(0, ec.category());
7c673cae
FG
383 return 0;
384 }
385
386 // Write some data.
387 for (;;)
388 {
389 // Try to complete the operation without blocking.
20effc67
TL
390 signed_size_type bytes = ::write(d, data, size);
391 get_last_error(ec, bytes < 0);
7c673cae
FG
392
393 // Check if operation succeeded.
394 if (bytes > 0)
395 return bytes;
396
397 // Operation failed.
398 if ((state & user_set_non_blocking)
399 || (ec != boost::asio::error::would_block
400 && ec != boost::asio::error::try_again))
401 return 0;
402
403 // Wait for descriptor to become ready.
404 if (descriptor_ops::poll_write(d, 0, ec) < 0)
405 return 0;
406 }
407}
408
409bool non_blocking_write(int d, const buf* bufs, std::size_t count,
410 boost::system::error_code& ec, std::size_t& bytes_transferred)
411{
412 for (;;)
413 {
414 // Write some data.
20effc67
TL
415 signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count));
416 get_last_error(ec, bytes < 0);
417
418 // Check if operation succeeded.
419 if (bytes >= 0)
420 {
421 bytes_transferred = bytes;
422 return true;
423 }
7c673cae
FG
424
425 // Retry operation if interrupted by signal.
426 if (ec == boost::asio::error::interrupted)
427 continue;
428
429 // Check if we need to run the operation again.
430 if (ec == boost::asio::error::would_block
431 || ec == boost::asio::error::try_again)
432 return false;
433
20effc67
TL
434 // Operation failed.
435 bytes_transferred = 0;
436 return true;
437 }
438}
439
440bool non_blocking_write1(int d, const void* data, std::size_t size,
441 boost::system::error_code& ec, std::size_t& bytes_transferred)
442{
443 for (;;)
444 {
445 // Write some data.
446 signed_size_type bytes = ::write(d, data, size);
447 get_last_error(ec, bytes < 0);
448
449 // Check if operation succeeded.
7c673cae
FG
450 if (bytes >= 0)
451 {
7c673cae 452 bytes_transferred = bytes;
20effc67 453 return true;
7c673cae 454 }
7c673cae 455
20effc67
TL
456 // Retry operation if interrupted by signal.
457 if (ec == boost::asio::error::interrupted)
458 continue;
459
460 // Check if we need to run the operation again.
461 if (ec == boost::asio::error::would_block
462 || ec == boost::asio::error::try_again)
463 return false;
464
465 // Operation failed.
466 bytes_transferred = 0;
7c673cae
FG
467 return true;
468 }
469}
470
471int ioctl(int d, state_type& state, long cmd,
472 ioctl_arg_type* arg, boost::system::error_code& ec)
473{
474 if (d == -1)
475 {
476 ec = boost::asio::error::bad_descriptor;
477 return -1;
478 }
479
20effc67
TL
480 int result = ::ioctl(d, cmd, arg);
481 get_last_error(ec, result < 0);
7c673cae
FG
482
483 if (result >= 0)
484 {
7c673cae
FG
485 // When updating the non-blocking mode we always perform the ioctl syscall,
486 // even if the flags would otherwise indicate that the descriptor is
487 // already in the correct state. This ensures that the underlying
488 // descriptor is put into the state that has been requested by the user. If
489 // the ioctl syscall was successful then we need to update the flags to
490 // match.
491 if (cmd == static_cast<long>(FIONBIO))
492 {
493 if (*arg)
494 {
495 state |= user_set_non_blocking;
496 }
497 else
498 {
499 // Clearing the non-blocking mode always overrides any internally-set
500 // non-blocking flag. Any subsequent asynchronous operations will need
501 // to re-enable non-blocking I/O.
502 state &= ~(user_set_non_blocking | internal_non_blocking);
503 }
504 }
505 }
506
507 return result;
508}
509
510int fcntl(int d, int cmd, boost::system::error_code& ec)
511{
512 if (d == -1)
513 {
514 ec = boost::asio::error::bad_descriptor;
515 return -1;
516 }
517
20effc67
TL
518 int result = ::fcntl(d, cmd);
519 get_last_error(ec, result < 0);
7c673cae
FG
520 return result;
521}
522
523int fcntl(int d, int cmd, long arg, boost::system::error_code& ec)
524{
525 if (d == -1)
526 {
527 ec = boost::asio::error::bad_descriptor;
528 return -1;
529 }
530
20effc67
TL
531 int result = ::fcntl(d, cmd, arg);
532 get_last_error(ec, result < 0);
7c673cae
FG
533 return result;
534}
535
536int poll_read(int d, state_type state, boost::system::error_code& ec)
537{
538 if (d == -1)
539 {
540 ec = boost::asio::error::bad_descriptor;
541 return -1;
542 }
543
544 pollfd fds;
545 fds.fd = d;
546 fds.events = POLLIN;
547 fds.revents = 0;
548 int timeout = (state & user_set_non_blocking) ? 0 : -1;
20effc67
TL
549 int result = ::poll(&fds, 1, timeout);
550 get_last_error(ec, result < 0);
7c673cae 551 if (result == 0)
20effc67
TL
552 if (state & user_set_non_blocking)
553 ec = boost::asio::error::would_block;
7c673cae
FG
554 return result;
555}
556
557int poll_write(int d, state_type state, boost::system::error_code& ec)
558{
559 if (d == -1)
560 {
561 ec = boost::asio::error::bad_descriptor;
562 return -1;
563 }
564
565 pollfd fds;
566 fds.fd = d;
567 fds.events = POLLOUT;
568 fds.revents = 0;
569 int timeout = (state & user_set_non_blocking) ? 0 : -1;
20effc67
TL
570 int result = ::poll(&fds, 1, timeout);
571 get_last_error(ec, result < 0);
7c673cae 572 if (result == 0)
20effc67
TL
573 if (state & user_set_non_blocking)
574 ec = boost::asio::error::would_block;
7c673cae
FG
575 return result;
576}
577
b32b8144
FG
578int poll_error(int d, state_type state, boost::system::error_code& ec)
579{
580 if (d == -1)
581 {
582 ec = boost::asio::error::bad_descriptor;
583 return -1;
584 }
585
586 pollfd fds;
587 fds.fd = d;
588 fds.events = POLLPRI | POLLERR | POLLHUP;
589 fds.revents = 0;
590 int timeout = (state & user_set_non_blocking) ? 0 : -1;
20effc67
TL
591 int result = ::poll(&fds, 1, timeout);
592 get_last_error(ec, result < 0);
b32b8144 593 if (result == 0)
20effc67
TL
594 if (state & user_set_non_blocking)
595 ec = boost::asio::error::would_block;
b32b8144
FG
596 return result;
597}
598
7c673cae
FG
599} // namespace descriptor_ops
600} // namespace detail
601} // namespace asio
602} // namespace boost
603
604#include <boost/asio/detail/pop_options.hpp>
605
606#endif // !defined(BOOST_ASIO_WINDOWS)
607 // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
608 // && !defined(__CYGWIN__)
609
610#endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP