MCPcopy Create free account
hub / github.com/boostorg/filesystem / impl

Method impl

src/operations.cpp:881–953  ·  view source on GitHub ↗

copy_file implementation that uses copy_file_range loop. Requires copy_file_range to support cross-filesystem copying.

Source from the content-addressed store, hash-verified

879{
880 //! copy_file implementation that uses copy_file_range loop. Requires copy_file_range to support cross-filesystem copying.
881 static int impl(int infile, int outfile, uintmax_t size, std::size_t blksize)
882 {
883 // Although copy_file_range does not document any particular upper limit of one transfer, still use some upper bound to guarantee
884 // that size_t is not overflown in case if off_t is larger and the file size does not fit in size_t.
885 BOOST_CONSTEXPR_OR_CONST std::size_t max_batch_size = 0x7ffff000u;
886 uintmax_t offset = 0u;
887 while (offset < size)
888 {
889 uintmax_t size_left = size - offset;
890 std::size_t size_to_copy = max_batch_size;
891 if (size_left < static_cast< uintmax_t >(max_batch_size))
892 size_to_copy = static_cast< std::size_t >(size_left);
893 // Note: Use syscall directly to avoid depending on libc version. copy_file_range is added in glibc 2.27.
894 // uClibc-ng does not have copy_file_range as of the time of this writing (the latest uClibc-ng release is 1.0.33).
895 loff_t sz = ::syscall(__NR_copy_file_range, infile, (loff_t*)nullptr, outfile, (loff_t*)nullptr, size_to_copy, (unsigned int)0u);
896 if (BOOST_LIKELY(sz > 0))
897 {
898 offset += sz;
899 }
900 else if (sz < 0)
901 {
902 int err = errno;
903 if (err == EINTR)
904 continue;
905
906 if (offset == 0u)
907 {
908 // copy_file_range may fail with EINVAL if the underlying filesystem does not support it.
909 // In some RHEL/CentOS 7.7-7.8 kernel versions, copy_file_range on NFSv4 is also known to return EOPNOTSUPP
910 // if the remote server does not support COPY, despite that it is not a documented error code.
911 // See https://patchwork.kernel.org/project/linux-nfs/patch/20190411183418.4510-1-olga.kornievskaia@gmail.com/
912 // and https://bugzilla.redhat.com/show_bug.cgi?id=1783554.
913 if (err == EINVAL || err == EOPNOTSUPP)
914 {
915#if !defined(BOOST_FILESYSTEM_USE_SENDFILE)
916 fallback_to_read_write:
917#endif
918 return copy_file_data_read_write(infile, outfile, size, blksize);
919 }
920
921 if (err == EXDEV)
922 {
923#if defined(BOOST_FILESYSTEM_USE_SENDFILE)
924 fallback_to_sendfile:
925 return copy_file_data_sendfile::impl(infile, outfile, size, blksize);
926#else
927 goto fallback_to_read_write;
928#endif
929 }
930
931 if (err == ENOSYS)
932 {
933#if defined(BOOST_FILESYSTEM_USE_SENDFILE)
934 filesystem::detail::atomic_store_relaxed(copy_file_data, &check_fs_type< copy_file_data_preallocate< copy_file_data_sendfile > >);
935 goto fallback_to_sendfile;
936#else
937 filesystem::detail::atomic_store_relaxed(copy_file_data, &copy_file_data_read_write);
938 goto fallback_to_read_write;

Callers

nothing calls this directly

Calls 3

implClass · 0.85
atomic_store_relaxedFunction · 0.85

Tested by

no test coverage detected