annotate DEPENDENCIES/generic/include/boost/asio/detail/impl/descriptor_ops.ipp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // detail/impl/descriptor_ops.ipp
Chris@16 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Chris@16 4 //
Chris@101 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 //
Chris@16 10
Chris@16 11 #ifndef BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
Chris@16 12 #define BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
Chris@16 13
Chris@16 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 15 # pragma once
Chris@16 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 17
Chris@16 18 #include <boost/asio/detail/config.hpp>
Chris@16 19 #include <cerrno>
Chris@16 20 #include <boost/asio/detail/descriptor_ops.hpp>
Chris@16 21 #include <boost/asio/error.hpp>
Chris@16 22
Chris@16 23 #if !defined(BOOST_ASIO_WINDOWS) \
Chris@16 24 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
Chris@16 25 && !defined(__CYGWIN__)
Chris@16 26
Chris@16 27 #include <boost/asio/detail/push_options.hpp>
Chris@16 28
Chris@16 29 namespace boost {
Chris@16 30 namespace asio {
Chris@16 31 namespace detail {
Chris@16 32 namespace descriptor_ops {
Chris@16 33
Chris@16 34 int open(const char* path, int flags, boost::system::error_code& ec)
Chris@16 35 {
Chris@16 36 errno = 0;
Chris@16 37 int result = error_wrapper(::open(path, flags), ec);
Chris@16 38 if (result >= 0)
Chris@16 39 ec = boost::system::error_code();
Chris@16 40 return result;
Chris@16 41 }
Chris@16 42
Chris@16 43 int close(int d, state_type& state, boost::system::error_code& ec)
Chris@16 44 {
Chris@16 45 int result = 0;
Chris@16 46 if (d != -1)
Chris@16 47 {
Chris@16 48 errno = 0;
Chris@16 49 result = error_wrapper(::close(d), ec);
Chris@16 50
Chris@16 51 if (result != 0
Chris@16 52 && (ec == boost::asio::error::would_block
Chris@16 53 || ec == boost::asio::error::try_again))
Chris@16 54 {
Chris@16 55 // According to UNIX Network Programming Vol. 1, it is possible for
Chris@16 56 // close() to fail with EWOULDBLOCK under certain circumstances. What
Chris@16 57 // isn't clear is the state of the descriptor after this error. The one
Chris@16 58 // current OS where this behaviour is seen, Windows, says that the socket
Chris@16 59 // remains open. Therefore we'll put the descriptor back into blocking
Chris@16 60 // mode and have another attempt at closing it.
Chris@16 61 #if defined(__SYMBIAN32__)
Chris@16 62 int flags = ::fcntl(d, F_GETFL, 0);
Chris@16 63 if (flags >= 0)
Chris@16 64 ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
Chris@16 65 #else // defined(__SYMBIAN32__)
Chris@16 66 ioctl_arg_type arg = 0;
Chris@16 67 ::ioctl(d, FIONBIO, &arg);
Chris@16 68 #endif // defined(__SYMBIAN32__)
Chris@16 69 state &= ~non_blocking;
Chris@16 70
Chris@16 71 errno = 0;
Chris@16 72 result = error_wrapper(::close(d), ec);
Chris@16 73 }
Chris@16 74 }
Chris@16 75
Chris@16 76 if (result == 0)
Chris@16 77 ec = boost::system::error_code();
Chris@16 78 return result;
Chris@16 79 }
Chris@16 80
Chris@16 81 bool set_user_non_blocking(int d, state_type& state,
Chris@16 82 bool value, boost::system::error_code& ec)
Chris@16 83 {
Chris@16 84 if (d == -1)
Chris@16 85 {
Chris@16 86 ec = boost::asio::error::bad_descriptor;
Chris@16 87 return false;
Chris@16 88 }
Chris@16 89
Chris@16 90 errno = 0;
Chris@16 91 #if defined(__SYMBIAN32__)
Chris@16 92 int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
Chris@16 93 if (result >= 0)
Chris@16 94 {
Chris@16 95 errno = 0;
Chris@16 96 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
Chris@16 97 result = error_wrapper(::fcntl(d, F_SETFL, flag), ec);
Chris@16 98 }
Chris@16 99 #else // defined(__SYMBIAN32__)
Chris@16 100 ioctl_arg_type arg = (value ? 1 : 0);
Chris@16 101 int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
Chris@16 102 #endif // defined(__SYMBIAN32__)
Chris@16 103
Chris@16 104 if (result >= 0)
Chris@16 105 {
Chris@16 106 ec = boost::system::error_code();
Chris@16 107 if (value)
Chris@16 108 state |= user_set_non_blocking;
Chris@16 109 else
Chris@16 110 {
Chris@16 111 // Clearing the user-set non-blocking mode always overrides any
Chris@16 112 // internally-set non-blocking flag. Any subsequent asynchronous
Chris@16 113 // operations will need to re-enable non-blocking I/O.
Chris@16 114 state &= ~(user_set_non_blocking | internal_non_blocking);
Chris@16 115 }
Chris@16 116 return true;
Chris@16 117 }
Chris@16 118
Chris@16 119 return false;
Chris@16 120 }
Chris@16 121
Chris@16 122 bool set_internal_non_blocking(int d, state_type& state,
Chris@16 123 bool value, boost::system::error_code& ec)
Chris@16 124 {
Chris@16 125 if (d == -1)
Chris@16 126 {
Chris@16 127 ec = boost::asio::error::bad_descriptor;
Chris@16 128 return false;
Chris@16 129 }
Chris@16 130
Chris@16 131 if (!value && (state & user_set_non_blocking))
Chris@16 132 {
Chris@16 133 // It does not make sense to clear the internal non-blocking flag if the
Chris@16 134 // user still wants non-blocking behaviour. Return an error and let the
Chris@16 135 // caller figure out whether to update the user-set non-blocking flag.
Chris@16 136 ec = boost::asio::error::invalid_argument;
Chris@16 137 return false;
Chris@16 138 }
Chris@16 139
Chris@16 140 errno = 0;
Chris@16 141 #if defined(__SYMBIAN32__)
Chris@16 142 int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
Chris@16 143 if (result >= 0)
Chris@16 144 {
Chris@16 145 errno = 0;
Chris@16 146 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
Chris@16 147 result = error_wrapper(::fcntl(d, F_SETFL, flag), ec);
Chris@16 148 }
Chris@16 149 #else // defined(__SYMBIAN32__)
Chris@16 150 ioctl_arg_type arg = (value ? 1 : 0);
Chris@16 151 int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
Chris@16 152 #endif // defined(__SYMBIAN32__)
Chris@16 153
Chris@16 154 if (result >= 0)
Chris@16 155 {
Chris@16 156 ec = boost::system::error_code();
Chris@16 157 if (value)
Chris@16 158 state |= internal_non_blocking;
Chris@16 159 else
Chris@16 160 state &= ~internal_non_blocking;
Chris@16 161 return true;
Chris@16 162 }
Chris@16 163
Chris@16 164 return false;
Chris@16 165 }
Chris@16 166
Chris@16 167 std::size_t sync_read(int d, state_type state, buf* bufs,
Chris@16 168 std::size_t count, bool all_empty, boost::system::error_code& ec)
Chris@16 169 {
Chris@16 170 if (d == -1)
Chris@16 171 {
Chris@16 172 ec = boost::asio::error::bad_descriptor;
Chris@16 173 return 0;
Chris@16 174 }
Chris@16 175
Chris@16 176 // A request to read 0 bytes on a stream is a no-op.
Chris@16 177 if (all_empty)
Chris@16 178 {
Chris@16 179 ec = boost::system::error_code();
Chris@16 180 return 0;
Chris@16 181 }
Chris@16 182
Chris@16 183 // Read some data.
Chris@16 184 for (;;)
Chris@16 185 {
Chris@16 186 // Try to complete the operation without blocking.
Chris@16 187 errno = 0;
Chris@16 188 signed_size_type bytes = error_wrapper(::readv(
Chris@16 189 d, bufs, static_cast<int>(count)), ec);
Chris@16 190
Chris@16 191 // Check if operation succeeded.
Chris@16 192 if (bytes > 0)
Chris@16 193 return bytes;
Chris@16 194
Chris@16 195 // Check for EOF.
Chris@16 196 if (bytes == 0)
Chris@16 197 {
Chris@16 198 ec = boost::asio::error::eof;
Chris@16 199 return 0;
Chris@16 200 }
Chris@16 201
Chris@16 202 // Operation failed.
Chris@16 203 if ((state & user_set_non_blocking)
Chris@16 204 || (ec != boost::asio::error::would_block
Chris@16 205 && ec != boost::asio::error::try_again))
Chris@16 206 return 0;
Chris@16 207
Chris@16 208 // Wait for descriptor to become ready.
Chris@16 209 if (descriptor_ops::poll_read(d, 0, ec) < 0)
Chris@16 210 return 0;
Chris@16 211 }
Chris@16 212 }
Chris@16 213
Chris@16 214 bool non_blocking_read(int d, buf* bufs, std::size_t count,
Chris@16 215 boost::system::error_code& ec, std::size_t& bytes_transferred)
Chris@16 216 {
Chris@16 217 for (;;)
Chris@16 218 {
Chris@16 219 // Read some data.
Chris@16 220 errno = 0;
Chris@16 221 signed_size_type bytes = error_wrapper(::readv(
Chris@16 222 d, bufs, static_cast<int>(count)), ec);
Chris@16 223
Chris@16 224 // Check for end of stream.
Chris@16 225 if (bytes == 0)
Chris@16 226 {
Chris@16 227 ec = boost::asio::error::eof;
Chris@16 228 return true;
Chris@16 229 }
Chris@16 230
Chris@16 231 // Retry operation if interrupted by signal.
Chris@16 232 if (ec == boost::asio::error::interrupted)
Chris@16 233 continue;
Chris@16 234
Chris@16 235 // Check if we need to run the operation again.
Chris@16 236 if (ec == boost::asio::error::would_block
Chris@16 237 || ec == boost::asio::error::try_again)
Chris@16 238 return false;
Chris@16 239
Chris@16 240 // Operation is complete.
Chris@16 241 if (bytes > 0)
Chris@16 242 {
Chris@16 243 ec = boost::system::error_code();
Chris@16 244 bytes_transferred = bytes;
Chris@16 245 }
Chris@16 246 else
Chris@16 247 bytes_transferred = 0;
Chris@16 248
Chris@16 249 return true;
Chris@16 250 }
Chris@16 251 }
Chris@16 252
Chris@16 253 std::size_t sync_write(int d, state_type state, const buf* bufs,
Chris@16 254 std::size_t count, bool all_empty, boost::system::error_code& ec)
Chris@16 255 {
Chris@16 256 if (d == -1)
Chris@16 257 {
Chris@16 258 ec = boost::asio::error::bad_descriptor;
Chris@16 259 return 0;
Chris@16 260 }
Chris@16 261
Chris@16 262 // A request to write 0 bytes on a stream is a no-op.
Chris@16 263 if (all_empty)
Chris@16 264 {
Chris@16 265 ec = boost::system::error_code();
Chris@16 266 return 0;
Chris@16 267 }
Chris@16 268
Chris@16 269 // Write some data.
Chris@16 270 for (;;)
Chris@16 271 {
Chris@16 272 // Try to complete the operation without blocking.
Chris@16 273 errno = 0;
Chris@16 274 signed_size_type bytes = error_wrapper(::writev(
Chris@16 275 d, bufs, static_cast<int>(count)), ec);
Chris@16 276
Chris@16 277 // Check if operation succeeded.
Chris@16 278 if (bytes > 0)
Chris@16 279 return bytes;
Chris@16 280
Chris@16 281 // Operation failed.
Chris@16 282 if ((state & user_set_non_blocking)
Chris@16 283 || (ec != boost::asio::error::would_block
Chris@16 284 && ec != boost::asio::error::try_again))
Chris@16 285 return 0;
Chris@16 286
Chris@16 287 // Wait for descriptor to become ready.
Chris@16 288 if (descriptor_ops::poll_write(d, 0, ec) < 0)
Chris@16 289 return 0;
Chris@16 290 }
Chris@16 291 }
Chris@16 292
Chris@16 293 bool non_blocking_write(int d, const buf* bufs, std::size_t count,
Chris@16 294 boost::system::error_code& ec, std::size_t& bytes_transferred)
Chris@16 295 {
Chris@16 296 for (;;)
Chris@16 297 {
Chris@16 298 // Write some data.
Chris@16 299 errno = 0;
Chris@16 300 signed_size_type bytes = error_wrapper(::writev(
Chris@16 301 d, bufs, static_cast<int>(count)), ec);
Chris@16 302
Chris@16 303 // Retry operation if interrupted by signal.
Chris@16 304 if (ec == boost::asio::error::interrupted)
Chris@16 305 continue;
Chris@16 306
Chris@16 307 // Check if we need to run the operation again.
Chris@16 308 if (ec == boost::asio::error::would_block
Chris@16 309 || ec == boost::asio::error::try_again)
Chris@16 310 return false;
Chris@16 311
Chris@16 312 // Operation is complete.
Chris@16 313 if (bytes >= 0)
Chris@16 314 {
Chris@16 315 ec = boost::system::error_code();
Chris@16 316 bytes_transferred = bytes;
Chris@16 317 }
Chris@16 318 else
Chris@16 319 bytes_transferred = 0;
Chris@16 320
Chris@16 321 return true;
Chris@16 322 }
Chris@16 323 }
Chris@16 324
Chris@16 325 int ioctl(int d, state_type& state, long cmd,
Chris@16 326 ioctl_arg_type* arg, boost::system::error_code& ec)
Chris@16 327 {
Chris@16 328 if (d == -1)
Chris@16 329 {
Chris@16 330 ec = boost::asio::error::bad_descriptor;
Chris@16 331 return -1;
Chris@16 332 }
Chris@16 333
Chris@16 334 errno = 0;
Chris@16 335 int result = error_wrapper(::ioctl(d, cmd, arg), ec);
Chris@16 336
Chris@16 337 if (result >= 0)
Chris@16 338 {
Chris@16 339 ec = boost::system::error_code();
Chris@16 340
Chris@16 341 // When updating the non-blocking mode we always perform the ioctl syscall,
Chris@16 342 // even if the flags would otherwise indicate that the descriptor is
Chris@16 343 // already in the correct state. This ensures that the underlying
Chris@16 344 // descriptor is put into the state that has been requested by the user. If
Chris@16 345 // the ioctl syscall was successful then we need to update the flags to
Chris@16 346 // match.
Chris@16 347 if (cmd == static_cast<long>(FIONBIO))
Chris@16 348 {
Chris@16 349 if (*arg)
Chris@16 350 {
Chris@16 351 state |= user_set_non_blocking;
Chris@16 352 }
Chris@16 353 else
Chris@16 354 {
Chris@16 355 // Clearing the non-blocking mode always overrides any internally-set
Chris@16 356 // non-blocking flag. Any subsequent asynchronous operations will need
Chris@16 357 // to re-enable non-blocking I/O.
Chris@16 358 state &= ~(user_set_non_blocking | internal_non_blocking);
Chris@16 359 }
Chris@16 360 }
Chris@16 361 }
Chris@16 362
Chris@16 363 return result;
Chris@16 364 }
Chris@16 365
Chris@16 366 int fcntl(int d, int cmd, boost::system::error_code& ec)
Chris@16 367 {
Chris@16 368 if (d == -1)
Chris@16 369 {
Chris@16 370 ec = boost::asio::error::bad_descriptor;
Chris@16 371 return -1;
Chris@16 372 }
Chris@16 373
Chris@16 374 errno = 0;
Chris@16 375 int result = error_wrapper(::fcntl(d, cmd), ec);
Chris@16 376 if (result != -1)
Chris@16 377 ec = boost::system::error_code();
Chris@16 378 return result;
Chris@16 379 }
Chris@16 380
Chris@16 381 int fcntl(int d, int cmd, long arg, boost::system::error_code& ec)
Chris@16 382 {
Chris@16 383 if (d == -1)
Chris@16 384 {
Chris@16 385 ec = boost::asio::error::bad_descriptor;
Chris@16 386 return -1;
Chris@16 387 }
Chris@16 388
Chris@16 389 errno = 0;
Chris@16 390 int result = error_wrapper(::fcntl(d, cmd, arg), ec);
Chris@16 391 if (result != -1)
Chris@16 392 ec = boost::system::error_code();
Chris@16 393 return result;
Chris@16 394 }
Chris@16 395
Chris@16 396 int poll_read(int d, state_type state, boost::system::error_code& ec)
Chris@16 397 {
Chris@16 398 if (d == -1)
Chris@16 399 {
Chris@16 400 ec = boost::asio::error::bad_descriptor;
Chris@16 401 return -1;
Chris@16 402 }
Chris@16 403
Chris@16 404 pollfd fds;
Chris@16 405 fds.fd = d;
Chris@16 406 fds.events = POLLIN;
Chris@16 407 fds.revents = 0;
Chris@16 408 int timeout = (state & user_set_non_blocking) ? 0 : -1;
Chris@16 409 errno = 0;
Chris@16 410 int result = error_wrapper(::poll(&fds, 1, timeout), ec);
Chris@16 411 if (result == 0)
Chris@16 412 ec = (state & user_set_non_blocking)
Chris@16 413 ? boost::asio::error::would_block : boost::system::error_code();
Chris@16 414 else if (result > 0)
Chris@16 415 ec = boost::system::error_code();
Chris@16 416 return result;
Chris@16 417 }
Chris@16 418
Chris@16 419 int poll_write(int d, state_type state, boost::system::error_code& ec)
Chris@16 420 {
Chris@16 421 if (d == -1)
Chris@16 422 {
Chris@16 423 ec = boost::asio::error::bad_descriptor;
Chris@16 424 return -1;
Chris@16 425 }
Chris@16 426
Chris@16 427 pollfd fds;
Chris@16 428 fds.fd = d;
Chris@16 429 fds.events = POLLOUT;
Chris@16 430 fds.revents = 0;
Chris@16 431 int timeout = (state & user_set_non_blocking) ? 0 : -1;
Chris@16 432 errno = 0;
Chris@16 433 int result = error_wrapper(::poll(&fds, 1, timeout), ec);
Chris@16 434 if (result == 0)
Chris@16 435 ec = (state & user_set_non_blocking)
Chris@16 436 ? boost::asio::error::would_block : boost::system::error_code();
Chris@16 437 else if (result > 0)
Chris@16 438 ec = boost::system::error_code();
Chris@16 439 return result;
Chris@16 440 }
Chris@16 441
Chris@16 442 } // namespace descriptor_ops
Chris@16 443 } // namespace detail
Chris@16 444 } // namespace asio
Chris@16 445 } // namespace boost
Chris@16 446
Chris@16 447 #include <boost/asio/detail/pop_options.hpp>
Chris@16 448
Chris@16 449 #endif // !defined(BOOST_ASIO_WINDOWS)
Chris@16 450 // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
Chris@16 451 // && !defined(__CYGWIN__)
Chris@16 452
Chris@16 453 #endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP