Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:31

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