| 818 | #if defined(BOOST_FILESYSTEM_USE_SENDFILE) |
| 819 | |
| 820 | struct copy_file_data_sendfile |
| 821 | { |
| 822 | //! copy_file implementation that uses sendfile loop. Requires sendfile to support file descriptors. |
| 823 | static int impl(int infile, int outfile, uintmax_t size, std::size_t blksize) |
| 824 | { |
| 825 | // sendfile will not send more than this amount of data in one call |
| 826 | BOOST_CONSTEXPR_OR_CONST std::size_t max_batch_size = 0x7ffff000u; |
| 827 | uintmax_t offset = 0u; |
| 828 | while (offset < size) |
| 829 | { |
| 830 | uintmax_t size_left = size - offset; |
| 831 | std::size_t size_to_copy = max_batch_size; |
| 832 | if (size_left < static_cast< uintmax_t >(max_batch_size)) |
| 833 | size_to_copy = static_cast< std::size_t >(size_left); |
| 834 | ssize_t sz = ::sendfile(outfile, infile, nullptr, size_to_copy); |
| 835 | if (BOOST_LIKELY(sz > 0)) |
| 836 | { |
| 837 | offset += sz; |
| 838 | } |
| 839 | else if (sz < 0) |
| 840 | { |
| 841 | int err = errno; |
| 842 | if (err == EINTR) |
| 843 | continue; |
| 844 | |
| 845 | if (offset == 0u) |
| 846 | { |
| 847 | // sendfile may fail with EINVAL if the underlying filesystem does not support it |
| 848 | if (err == EINVAL) |
| 849 | { |
| 850 | fallback_to_read_write: |
| 851 | return copy_file_data_read_write(infile, outfile, size, blksize); |
| 852 | } |
| 853 | |
| 854 | if (err == ENOSYS) |
| 855 | { |
| 856 | filesystem::detail::atomic_store_relaxed(copy_file_data, ©_file_data_read_write); |
| 857 | goto fallback_to_read_write; |
| 858 | } |
| 859 | } |
| 860 | |
| 861 | return err; |
| 862 | } |
| 863 | else |
| 864 | { |
| 865 | // EOF: the input file was truncated while copying was in progress |
| 866 | break; |
| 867 | } |
| 868 | } |
| 869 | |
| 870 | return 0; |
| 871 | } |
| 872 | }; |
| 873 | |
| 874 | #endif // defined(BOOST_FILESYSTEM_USE_SENDFILE) |
| 875 |
nothing calls this directly
no outgoing calls
no test coverage detected