Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/asio/detail/impl/descriptor_ops.ipp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // detail/impl/descriptor_ops.ipp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
0012 #define BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <cerrno>
0020 #include <boost/asio/detail/descriptor_ops.hpp>
0021 #include <boost/asio/error.hpp>
0022 
0023 #if !defined(BOOST_ASIO_WINDOWS) \
0024   && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0025   && !defined(__CYGWIN__)
0026 
0027 #include <boost/asio/detail/push_options.hpp>
0028 
0029 namespace boost {
0030 namespace asio {
0031 namespace detail {
0032 namespace descriptor_ops {
0033 
0034 int open(const char* path, int flags, boost::system::error_code& ec)
0035 {
0036   int result = ::open(path, flags);
0037   get_last_error(ec, result < 0);
0038   return result;
0039 }
0040 
0041 int open(const char* path, int flags,
0042     unsigned mode, boost::system::error_code& ec)
0043 {
0044   int result = ::open(path, flags, mode);
0045   get_last_error(ec, result < 0);
0046   return result;
0047 }
0048 
0049 int close(int d, state_type& state, boost::system::error_code& ec)
0050 {
0051   int result = 0;
0052   if (d != -1)
0053   {
0054     result = ::close(d);
0055     get_last_error(ec, result < 0);
0056 
0057     if (result != 0
0058         && (ec == boost::asio::error::would_block
0059           || ec == boost::asio::error::try_again))
0060     {
0061       // According to UNIX Network Programming Vol. 1, it is possible for
0062       // close() to fail with EWOULDBLOCK under certain circumstances. What
0063       // isn't clear is the state of the descriptor after this error. The one
0064       // current OS where this behaviour is seen, Windows, says that the socket
0065       // remains open. Therefore we'll put the descriptor back into blocking
0066       // mode and have another attempt at closing it.
0067 #if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0068       int flags = ::fcntl(d, F_GETFL, 0);
0069       if (flags >= 0)
0070         ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
0071 #else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0072       ioctl_arg_type arg = 0;
0073       if ((state & possible_dup) == 0)
0074       {
0075         result = ::ioctl(d, FIONBIO, &arg);
0076         get_last_error(ec, result < 0);
0077       }
0078       if ((state & possible_dup) != 0
0079 # if defined(ENOTTY)
0080           || ec.value() == ENOTTY
0081 # endif // defined(ENOTTY)
0082 # if defined(ENOTCAPABLE)
0083           || ec.value() == ENOTCAPABLE
0084 # endif // defined(ENOTCAPABLE)
0085         )
0086       {
0087         int flags = ::fcntl(d, F_GETFL, 0);
0088         if (flags >= 0)
0089           ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
0090       }
0091 #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0092       state &= ~non_blocking;
0093 
0094       result = ::close(d);
0095       get_last_error(ec, result < 0);
0096     }
0097   }
0098 
0099   return result;
0100 }
0101 
0102 bool set_user_non_blocking(int d, state_type& state,
0103     bool value, boost::system::error_code& ec)
0104 {
0105   if (d == -1)
0106   {
0107     ec = boost::asio::error::bad_descriptor;
0108     return false;
0109   }
0110 
0111 #if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0112   int result = ::fcntl(d, F_GETFL, 0);
0113   get_last_error(ec, result < 0);
0114   if (result >= 0)
0115   {
0116     int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
0117     result = (flag != result) ? ::fcntl(d, F_SETFL, flag) : 0;
0118     get_last_error(ec, result < 0);
0119   }
0120 #else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0121   ioctl_arg_type arg = (value ? 1 : 0);
0122   int result = 0;
0123   if ((state & possible_dup) == 0)
0124   {
0125     result = ::ioctl(d, FIONBIO, &arg);
0126     get_last_error(ec, result < 0);
0127   }
0128   if ((state & possible_dup) != 0
0129 # if defined(ENOTTY)
0130       || ec.value() == ENOTTY
0131 # endif // defined(ENOTTY)
0132 # if defined(ENOTCAPABLE)
0133       || ec.value() == ENOTCAPABLE
0134 # endif // defined(ENOTCAPABLE)
0135     )
0136   {
0137     result = ::fcntl(d, F_GETFL, 0);
0138     get_last_error(ec, result < 0);
0139     if (result >= 0)
0140     {
0141       int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
0142       result = (flag != result) ? ::fcntl(d, F_SETFL, flag) : 0;
0143       get_last_error(ec, result < 0);
0144     }
0145   }
0146 #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0147 
0148   if (result >= 0)
0149   {
0150     if (value)
0151       state |= user_set_non_blocking;
0152     else
0153     {
0154       // Clearing the user-set non-blocking mode always overrides any
0155       // internally-set non-blocking flag. Any subsequent asynchronous
0156       // operations will need to re-enable non-blocking I/O.
0157       state &= ~(user_set_non_blocking | internal_non_blocking);
0158     }
0159     return true;
0160   }
0161 
0162   return false;
0163 }
0164 
0165 bool set_internal_non_blocking(int d, state_type& state,
0166     bool value, boost::system::error_code& ec)
0167 {
0168   if (d == -1)
0169   {
0170     ec = boost::asio::error::bad_descriptor;
0171     return false;
0172   }
0173 
0174   if (!value && (state & user_set_non_blocking))
0175   {
0176     // It does not make sense to clear the internal non-blocking flag if the
0177     // user still wants non-blocking behaviour. Return an error and let the
0178     // caller figure out whether to update the user-set non-blocking flag.
0179     ec = boost::asio::error::invalid_argument;
0180     return false;
0181   }
0182 
0183 #if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0184   int result = ::fcntl(d, F_GETFL, 0);
0185   get_last_error(ec, result < 0);
0186   if (result >= 0)
0187   {
0188     int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
0189     result = (flag != result) ? ::fcntl(d, F_SETFL, flag) : 0;
0190     get_last_error(ec, result < 0);
0191   }
0192 #else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0193   ioctl_arg_type arg = (value ? 1 : 0);
0194   int result = 0;
0195   if ((state & possible_dup) == 0)
0196   {
0197     result = ::ioctl(d, FIONBIO, &arg);
0198     get_last_error(ec, result < 0);
0199   }
0200   if ((state & possible_dup) != 0
0201 # if defined(ENOTTY)
0202       || ec.value() == ENOTTY
0203 # endif // defined(ENOTTY)
0204 # if defined(ENOTCAPABLE)
0205       || ec.value() == ENOTCAPABLE
0206 # endif // defined(ENOTCAPABLE)
0207     )
0208   {
0209     result = ::fcntl(d, F_GETFL, 0);
0210     get_last_error(ec, result < 0);
0211     if (result >= 0)
0212     {
0213       int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
0214       result = (flag != result) ? ::fcntl(d, F_SETFL, flag) : 0;
0215       get_last_error(ec, result < 0);
0216     }
0217   }
0218 #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
0219 
0220   if (result >= 0)
0221   {
0222     if (value)
0223       state |= internal_non_blocking;
0224     else
0225       state &= ~internal_non_blocking;
0226     return true;
0227   }
0228 
0229   return false;
0230 }
0231 
0232 std::size_t sync_read(int d, state_type state, buf* bufs,
0233     std::size_t count, bool all_empty, boost::system::error_code& ec)
0234 {
0235   if (d == -1)
0236   {
0237     ec = boost::asio::error::bad_descriptor;
0238     return 0;
0239   }
0240 
0241   // A request to read 0 bytes on a stream is a no-op.
0242   if (all_empty)
0243   {
0244     boost::asio::error::clear(ec);
0245     return 0;
0246   }
0247 
0248   // Read some data.
0249   for (;;)
0250   {
0251     // Try to complete the operation without blocking.
0252     signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count));
0253     get_last_error(ec, bytes < 0);
0254 
0255     // Check if operation succeeded.
0256     if (bytes > 0)
0257       return bytes;
0258 
0259     // Check for EOF.
0260     if (bytes == 0)
0261     {
0262       ec = boost::asio::error::eof;
0263       return 0;
0264     }
0265 
0266     // Operation failed.
0267     if ((state & user_set_non_blocking)
0268         || (ec != boost::asio::error::would_block
0269           && ec != boost::asio::error::try_again))
0270       return 0;
0271 
0272     // Wait for descriptor to become ready.
0273     if (descriptor_ops::poll_read(d, 0, ec) < 0)
0274       return 0;
0275   }
0276 }
0277 
0278 std::size_t sync_read1(int d, state_type state, void* data,
0279     std::size_t size, boost::system::error_code& ec)
0280 {
0281   if (d == -1)
0282   {
0283     ec = boost::asio::error::bad_descriptor;
0284     return 0;
0285   }
0286 
0287   // A request to read 0 bytes on a stream is a no-op.
0288   if (size == 0)
0289   {
0290     boost::asio::error::clear(ec);
0291     return 0;
0292   }
0293 
0294   // Read some data.
0295   for (;;)
0296   {
0297     // Try to complete the operation without blocking.
0298     signed_size_type bytes = ::read(d, data, size);
0299     get_last_error(ec, bytes < 0);
0300 
0301     // Check if operation succeeded.
0302     if (bytes > 0)
0303       return bytes;
0304 
0305     // Check for EOF.
0306     if (bytes == 0)
0307     {
0308       ec = boost::asio::error::eof;
0309       return 0;
0310     }
0311 
0312     // Operation failed.
0313     if ((state & user_set_non_blocking)
0314         || (ec != boost::asio::error::would_block
0315           && ec != boost::asio::error::try_again))
0316       return 0;
0317 
0318     // Wait for descriptor to become ready.
0319     if (descriptor_ops::poll_read(d, 0, ec) < 0)
0320       return 0;
0321   }
0322 }
0323 
0324 bool non_blocking_read(int d, buf* bufs, std::size_t count,
0325     boost::system::error_code& ec, std::size_t& bytes_transferred)
0326 {
0327   for (;;)
0328   {
0329     // Read some data.
0330     signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count));
0331     get_last_error(ec, bytes < 0);
0332 
0333     // Check for end of stream.
0334     if (bytes == 0)
0335     {
0336       ec = boost::asio::error::eof;
0337       return true;
0338     }
0339 
0340     // Check if operation succeeded.
0341     if (bytes > 0)
0342     {
0343       bytes_transferred = bytes;
0344       return true;
0345     }
0346 
0347     // Retry operation if interrupted by signal.
0348     if (ec == boost::asio::error::interrupted)
0349       continue;
0350 
0351     // Check if we need to run the operation again.
0352     if (ec == boost::asio::error::would_block
0353         || ec == boost::asio::error::try_again)
0354       return false;
0355 
0356     // Operation failed.
0357     bytes_transferred = 0;
0358     return true;
0359   }
0360 }
0361 
0362 bool non_blocking_read1(int d, void* data, std::size_t size,
0363     boost::system::error_code& ec, std::size_t& bytes_transferred)
0364 {
0365   for (;;)
0366   {
0367     // Read some data.
0368     signed_size_type bytes = ::read(d, data, size);
0369     get_last_error(ec, bytes < 0);
0370 
0371     // Check for end of stream.
0372     if (bytes == 0)
0373     {
0374       ec = boost::asio::error::eof;
0375       return true;
0376     }
0377 
0378     // Check if operation succeeded.
0379     if (bytes > 0)
0380     {
0381       bytes_transferred = bytes;
0382       return true;
0383     }
0384 
0385     // Retry operation if interrupted by signal.
0386     if (ec == boost::asio::error::interrupted)
0387       continue;
0388 
0389     // Check if we need to run the operation again.
0390     if (ec == boost::asio::error::would_block
0391         || ec == boost::asio::error::try_again)
0392       return false;
0393 
0394     // Operation failed.
0395     bytes_transferred = 0;
0396     return true;
0397   }
0398 }
0399 
0400 std::size_t sync_write(int d, state_type state, const buf* bufs,
0401     std::size_t count, bool all_empty, boost::system::error_code& ec)
0402 {
0403   if (d == -1)
0404   {
0405     ec = boost::asio::error::bad_descriptor;
0406     return 0;
0407   }
0408 
0409   // A request to write 0 bytes on a stream is a no-op.
0410   if (all_empty)
0411   {
0412     boost::asio::error::clear(ec);
0413     return 0;
0414   }
0415 
0416   // Write some data.
0417   for (;;)
0418   {
0419     // Try to complete the operation without blocking.
0420     signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count));
0421     get_last_error(ec, bytes < 0);
0422 
0423     // Check if operation succeeded.
0424     if (bytes > 0)
0425       return bytes;
0426 
0427     // Operation failed.
0428     if ((state & user_set_non_blocking)
0429         || (ec != boost::asio::error::would_block
0430           && ec != boost::asio::error::try_again))
0431       return 0;
0432 
0433     // Wait for descriptor to become ready.
0434     if (descriptor_ops::poll_write(d, 0, ec) < 0)
0435       return 0;
0436   }
0437 }
0438 
0439 std::size_t sync_write1(int d, state_type state, const void* data,
0440     std::size_t size, boost::system::error_code& ec)
0441 {
0442   if (d == -1)
0443   {
0444     ec = boost::asio::error::bad_descriptor;
0445     return 0;
0446   }
0447 
0448   // A request to write 0 bytes on a stream is a no-op.
0449   if (size == 0)
0450   {
0451     boost::asio::error::clear(ec);
0452     return 0;
0453   }
0454 
0455   // Write some data.
0456   for (;;)
0457   {
0458     // Try to complete the operation without blocking.
0459     signed_size_type bytes = ::write(d, data, size);
0460     get_last_error(ec, bytes < 0);
0461 
0462     // Check if operation succeeded.
0463     if (bytes > 0)
0464       return bytes;
0465 
0466     // Operation failed.
0467     if ((state & user_set_non_blocking)
0468         || (ec != boost::asio::error::would_block
0469           && ec != boost::asio::error::try_again))
0470       return 0;
0471 
0472     // Wait for descriptor to become ready.
0473     if (descriptor_ops::poll_write(d, 0, ec) < 0)
0474       return 0;
0475   }
0476 }
0477 
0478 bool non_blocking_write(int d, const buf* bufs, std::size_t count,
0479     boost::system::error_code& ec, std::size_t& bytes_transferred)
0480 {
0481   for (;;)
0482   {
0483     // Write some data.
0484     signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count));
0485     get_last_error(ec, bytes < 0);
0486 
0487     // Check if operation succeeded.
0488     if (bytes >= 0)
0489     {
0490       bytes_transferred = bytes;
0491       return true;
0492     }
0493 
0494     // Retry operation if interrupted by signal.
0495     if (ec == boost::asio::error::interrupted)
0496       continue;
0497 
0498     // Check if we need to run the operation again.
0499     if (ec == boost::asio::error::would_block
0500         || ec == boost::asio::error::try_again)
0501       return false;
0502 
0503     // Operation failed.
0504     bytes_transferred = 0;
0505     return true;
0506   }
0507 }
0508 
0509 bool non_blocking_write1(int d, const void* data, std::size_t size,
0510     boost::system::error_code& ec, std::size_t& bytes_transferred)
0511 {
0512   for (;;)
0513   {
0514     // Write some data.
0515     signed_size_type bytes = ::write(d, data, size);
0516     get_last_error(ec, bytes < 0);
0517 
0518     // Check if operation succeeded.
0519     if (bytes >= 0)
0520     {
0521       bytes_transferred = bytes;
0522       return true;
0523     }
0524 
0525     // Retry operation if interrupted by signal.
0526     if (ec == boost::asio::error::interrupted)
0527       continue;
0528 
0529     // Check if we need to run the operation again.
0530     if (ec == boost::asio::error::would_block
0531         || ec == boost::asio::error::try_again)
0532       return false;
0533 
0534     // Operation failed.
0535     bytes_transferred = 0;
0536     return true;
0537   }
0538 }
0539 
0540 #if defined(BOOST_ASIO_HAS_FILE)
0541 
0542 std::size_t sync_read_at(int d, state_type state, uint64_t offset,
0543     buf* bufs, std::size_t count, bool all_empty, boost::system::error_code& ec)
0544 {
0545   if (d == -1)
0546   {
0547     ec = boost::asio::error::bad_descriptor;
0548     return 0;
0549   }
0550 
0551   // A request to read 0 bytes on a stream is a no-op.
0552   if (all_empty)
0553   {
0554     boost::asio::error::clear(ec);
0555     return 0;
0556   }
0557 
0558   // Read some data.
0559   for (;;)
0560   {
0561     // Try to complete the operation without blocking.
0562     signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset);
0563     get_last_error(ec, bytes < 0);
0564 
0565     // Check if operation succeeded.
0566     if (bytes > 0)
0567       return bytes;
0568 
0569     // Check for EOF.
0570     if (bytes == 0)
0571     {
0572       ec = boost::asio::error::eof;
0573       return 0;
0574     }
0575 
0576     // Operation failed.
0577     if ((state & user_set_non_blocking)
0578         || (ec != boost::asio::error::would_block
0579           && ec != boost::asio::error::try_again))
0580       return 0;
0581 
0582     // Wait for descriptor to become ready.
0583     if (descriptor_ops::poll_read(d, 0, ec) < 0)
0584       return 0;
0585   }
0586 }
0587 
0588 std::size_t sync_read_at1(int d, state_type state, uint64_t offset,
0589     void* data, std::size_t size, boost::system::error_code& ec)
0590 {
0591   if (d == -1)
0592   {
0593     ec = boost::asio::error::bad_descriptor;
0594     return 0;
0595   }
0596 
0597   // A request to read 0 bytes on a stream is a no-op.
0598   if (size == 0)
0599   {
0600     boost::asio::error::clear(ec);
0601     return 0;
0602   }
0603 
0604   // Read some data.
0605   for (;;)
0606   {
0607     // Try to complete the operation without blocking.
0608     signed_size_type bytes = ::pread(d, data, size, offset);
0609     get_last_error(ec, bytes < 0);
0610 
0611     // Check if operation succeeded.
0612     if (bytes > 0)
0613       return bytes;
0614 
0615     // Check for EOF.
0616     if (bytes == 0)
0617     {
0618       ec = boost::asio::error::eof;
0619       return 0;
0620     }
0621 
0622     // Operation failed.
0623     if ((state & user_set_non_blocking)
0624         || (ec != boost::asio::error::would_block
0625           && ec != boost::asio::error::try_again))
0626       return 0;
0627 
0628     // Wait for descriptor to become ready.
0629     if (descriptor_ops::poll_read(d, 0, ec) < 0)
0630       return 0;
0631   }
0632 }
0633 
0634 bool non_blocking_read_at(int d, uint64_t offset, buf* bufs, std::size_t count,
0635     boost::system::error_code& ec, std::size_t& bytes_transferred)
0636 {
0637   for (;;)
0638   {
0639     // Read some data.
0640     signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset);
0641     get_last_error(ec, bytes < 0);
0642 
0643     // Check for EOF.
0644     if (bytes == 0)
0645     {
0646       ec = boost::asio::error::eof;
0647       return true;
0648     }
0649 
0650     // Check if operation succeeded.
0651     if (bytes > 0)
0652     {
0653       bytes_transferred = bytes;
0654       return true;
0655     }
0656 
0657     // Retry operation if interrupted by signal.
0658     if (ec == boost::asio::error::interrupted)
0659       continue;
0660 
0661     // Check if we need to run the operation again.
0662     if (ec == boost::asio::error::would_block
0663         || ec == boost::asio::error::try_again)
0664       return false;
0665 
0666     // Operation failed.
0667     bytes_transferred = 0;
0668     return true;
0669   }
0670 }
0671 
0672 bool non_blocking_read_at1(int d, uint64_t offset, void* data, std::size_t size,
0673     boost::system::error_code& ec, std::size_t& bytes_transferred)
0674 {
0675   for (;;)
0676   {
0677     // Read some data.
0678     signed_size_type bytes = ::pread(d, data, size, offset);
0679     get_last_error(ec, bytes < 0);
0680 
0681     // Check for EOF.
0682     if (bytes == 0)
0683     {
0684       ec = boost::asio::error::eof;
0685       return true;
0686     }
0687 
0688     // Check if operation succeeded.
0689     if (bytes > 0)
0690     {
0691       bytes_transferred = bytes;
0692       return true;
0693     }
0694 
0695     // Retry operation if interrupted by signal.
0696     if (ec == boost::asio::error::interrupted)
0697       continue;
0698 
0699     // Check if we need to run the operation again.
0700     if (ec == boost::asio::error::would_block
0701         || ec == boost::asio::error::try_again)
0702       return false;
0703 
0704     // Operation failed.
0705     bytes_transferred = 0;
0706     return true;
0707   }
0708 }
0709 
0710 std::size_t sync_write_at(int d, state_type state, uint64_t offset,
0711     const buf* bufs, std::size_t count, bool all_empty,
0712     boost::system::error_code& ec)
0713 {
0714   if (d == -1)
0715   {
0716     ec = boost::asio::error::bad_descriptor;
0717     return 0;
0718   }
0719 
0720   // A request to write 0 bytes on a stream is a no-op.
0721   if (all_empty)
0722   {
0723     boost::asio::error::clear(ec);
0724     return 0;
0725   }
0726 
0727   // Write some data.
0728   for (;;)
0729   {
0730     // Try to complete the operation without blocking.
0731     signed_size_type bytes = ::pwritev(d,
0732         bufs, static_cast<int>(count), offset);
0733     get_last_error(ec, bytes < 0);
0734 
0735     // Check if operation succeeded.
0736     if (bytes > 0)
0737       return bytes;
0738 
0739     // Operation failed.
0740     if ((state & user_set_non_blocking)
0741         || (ec != boost::asio::error::would_block
0742           && ec != boost::asio::error::try_again))
0743       return 0;
0744 
0745     // Wait for descriptor to become ready.
0746     if (descriptor_ops::poll_write(d, 0, ec) < 0)
0747       return 0;
0748   }
0749 }
0750 
0751 std::size_t sync_write_at1(int d, state_type state, uint64_t offset,
0752     const void* data, std::size_t size, boost::system::error_code& ec)
0753 {
0754   if (d == -1)
0755   {
0756     ec = boost::asio::error::bad_descriptor;
0757     return 0;
0758   }
0759 
0760   // A request to write 0 bytes on a stream is a no-op.
0761   if (size == 0)
0762   {
0763     boost::asio::error::clear(ec);
0764     return 0;
0765   }
0766 
0767   // Write some data.
0768   for (;;)
0769   {
0770     // Try to complete the operation without blocking.
0771     signed_size_type bytes = ::pwrite(d, data, size, offset);
0772     get_last_error(ec, bytes < 0);
0773 
0774     // Check if operation succeeded.
0775     if (bytes > 0)
0776       return bytes;
0777 
0778     // Operation failed.
0779     if ((state & user_set_non_blocking)
0780         || (ec != boost::asio::error::would_block
0781           && ec != boost::asio::error::try_again))
0782       return 0;
0783 
0784     // Wait for descriptor to become ready.
0785     if (descriptor_ops::poll_write(d, 0, ec) < 0)
0786       return 0;
0787   }
0788 }
0789 
0790 bool non_blocking_write_at(int d, uint64_t offset,
0791     const buf* bufs, std::size_t count,
0792     boost::system::error_code& ec, std::size_t& bytes_transferred)
0793 {
0794   for (;;)
0795   {
0796     // Write some data.
0797     signed_size_type bytes = ::pwritev(d,
0798         bufs, static_cast<int>(count), offset);
0799     get_last_error(ec, bytes < 0);
0800 
0801     // Check if operation succeeded.
0802     if (bytes >= 0)
0803     {
0804       bytes_transferred = bytes;
0805       return true;
0806     }
0807 
0808     // Retry operation if interrupted by signal.
0809     if (ec == boost::asio::error::interrupted)
0810       continue;
0811 
0812     // Check if we need to run the operation again.
0813     if (ec == boost::asio::error::would_block
0814         || ec == boost::asio::error::try_again)
0815       return false;
0816 
0817     // Operation failed.
0818     bytes_transferred = 0;
0819     return true;
0820   }
0821 }
0822 
0823 bool non_blocking_write_at1(int d, uint64_t offset,
0824     const void* data, std::size_t size,
0825     boost::system::error_code& ec, std::size_t& bytes_transferred)
0826 {
0827   for (;;)
0828   {
0829     // Write some data.
0830     signed_size_type bytes = ::pwrite(d, data, size, offset);
0831     get_last_error(ec, bytes < 0);
0832 
0833     // Check if operation succeeded.
0834     if (bytes >= 0)
0835     {
0836       bytes_transferred = bytes;
0837       return true;
0838     }
0839 
0840     // Retry operation if interrupted by signal.
0841     if (ec == boost::asio::error::interrupted)
0842       continue;
0843 
0844     // Check if we need to run the operation again.
0845     if (ec == boost::asio::error::would_block
0846         || ec == boost::asio::error::try_again)
0847       return false;
0848 
0849     // Operation failed.
0850     bytes_transferred = 0;
0851     return true;
0852   }
0853 }
0854 
0855 #endif // defined(BOOST_ASIO_HAS_FILE)
0856 
0857 int ioctl(int d, state_type& state, long cmd,
0858     ioctl_arg_type* arg, boost::system::error_code& ec)
0859 {
0860   if (d == -1)
0861   {
0862     ec = boost::asio::error::bad_descriptor;
0863     return -1;
0864   }
0865 
0866   int result = ::ioctl(d, cmd, arg);
0867   get_last_error(ec, result < 0);
0868 
0869   if (result >= 0)
0870   {
0871     // When updating the non-blocking mode we always perform the ioctl syscall,
0872     // even if the flags would otherwise indicate that the descriptor is
0873     // already in the correct state. This ensures that the underlying
0874     // descriptor is put into the state that has been requested by the user. If
0875     // the ioctl syscall was successful then we need to update the flags to
0876     // match.
0877     if (cmd == static_cast<long>(FIONBIO))
0878     {
0879       if (*arg)
0880       {
0881         state |= user_set_non_blocking;
0882       }
0883       else
0884       {
0885         // Clearing the non-blocking mode always overrides any internally-set
0886         // non-blocking flag. Any subsequent asynchronous operations will need
0887         // to re-enable non-blocking I/O.
0888         state &= ~(user_set_non_blocking | internal_non_blocking);
0889       }
0890     }
0891   }
0892 
0893   return result;
0894 }
0895 
0896 int fcntl(int d, int cmd, boost::system::error_code& ec)
0897 {
0898   if (d == -1)
0899   {
0900     ec = boost::asio::error::bad_descriptor;
0901     return -1;
0902   }
0903 
0904   int result = ::fcntl(d, cmd);
0905   get_last_error(ec, result < 0);
0906   return result;
0907 }
0908 
0909 int fcntl(int d, int cmd, long arg, boost::system::error_code& ec)
0910 {
0911   if (d == -1)
0912   {
0913     ec = boost::asio::error::bad_descriptor;
0914     return -1;
0915   }
0916 
0917   int result = ::fcntl(d, cmd, arg);
0918   get_last_error(ec, result < 0);
0919   return result;
0920 }
0921 
0922 int poll_read(int d, state_type state, boost::system::error_code& ec)
0923 {
0924   if (d == -1)
0925   {
0926     ec = boost::asio::error::bad_descriptor;
0927     return -1;
0928   }
0929 
0930   pollfd fds;
0931   fds.fd = d;
0932   fds.events = POLLIN;
0933   fds.revents = 0;
0934   int timeout = (state & user_set_non_blocking) ? 0 : -1;
0935   int result = ::poll(&fds, 1, timeout);
0936   get_last_error(ec, result < 0);
0937   if (result == 0)
0938     if (state & user_set_non_blocking)
0939       ec = boost::asio::error::would_block;
0940   return result;
0941 }
0942 
0943 int poll_write(int d, state_type state, boost::system::error_code& ec)
0944 {
0945   if (d == -1)
0946   {
0947     ec = boost::asio::error::bad_descriptor;
0948     return -1;
0949   }
0950 
0951   pollfd fds;
0952   fds.fd = d;
0953   fds.events = POLLOUT;
0954   fds.revents = 0;
0955   int timeout = (state & user_set_non_blocking) ? 0 : -1;
0956   int result = ::poll(&fds, 1, timeout);
0957   get_last_error(ec, result < 0);
0958   if (result == 0)
0959     if (state & user_set_non_blocking)
0960       ec = boost::asio::error::would_block;
0961   return result;
0962 }
0963 
0964 int poll_error(int d, state_type state, boost::system::error_code& ec)
0965 {
0966   if (d == -1)
0967   {
0968     ec = boost::asio::error::bad_descriptor;
0969     return -1;
0970   }
0971 
0972   pollfd fds;
0973   fds.fd = d;
0974   fds.events = POLLPRI | POLLERR | POLLHUP;
0975   fds.revents = 0;
0976   int timeout = (state & user_set_non_blocking) ? 0 : -1;
0977   int result = ::poll(&fds, 1, timeout);
0978   get_last_error(ec, result < 0);
0979   if (result == 0)
0980     if (state & user_set_non_blocking)
0981       ec = boost::asio::error::would_block;
0982   return result;
0983 }
0984 
0985 } // namespace descriptor_ops
0986 } // namespace detail
0987 } // namespace asio
0988 } // namespace boost
0989 
0990 #include <boost/asio/detail/pop_options.hpp>
0991 
0992 #endif // !defined(BOOST_ASIO_WINDOWS)
0993        //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
0994        //   && !defined(__CYGWIN__)
0995 
0996 #endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP