Fallback to unoptimized version if sendfile64() fails
It might fail on some filesystems such as `ecryptfs`, see https://github.com/Martchus/cpp-utilities/issues/24.
This commit is contained in:
parent
2467c4f815
commit
83025c17a1
12
io/copy.h
12
io/copy.h
|
@ -114,9 +114,13 @@ template <std::size_t bufferSize> void CopyHelper<bufferSize>::copy(NativeFileSt
|
||||||
while (count) {
|
while (count) {
|
||||||
const auto bytesCopied = ::sendfile64(output.fileDescriptor(), input.fileDescriptor(), nullptr, count);
|
const auto bytesCopied = ::sendfile64(output.fileDescriptor(), input.fileDescriptor(), nullptr, count);
|
||||||
if (bytesCopied < 0) {
|
if (bytesCopied < 0) {
|
||||||
|
if (errno == EINVAL && static_cast<std::uint64_t>(totalBytes) == count) {
|
||||||
|
// try again the unoptimized version, maybe the filesystem doesn't support sendfile
|
||||||
|
goto unoptimized_version;
|
||||||
|
}
|
||||||
throw std::ios_base::failure(argsToString("sendfile64() failed: ", std::strerror(errno)));
|
throw std::ios_base::failure(argsToString("sendfile64() failed: ", std::strerror(errno)));
|
||||||
}
|
}
|
||||||
count -= static_cast<std::size_t>(bytesCopied);
|
count -= static_cast<std::uint64_t>(bytesCopied);
|
||||||
}
|
}
|
||||||
input.sync();
|
input.sync();
|
||||||
output.sync();
|
output.sync();
|
||||||
|
@ -126,6 +130,7 @@ template <std::size_t bufferSize> void CopyHelper<bufferSize>::copy(NativeFileSt
|
||||||
input.seekp(inputTellp + totalBytes);
|
input.seekp(inputTellp + totalBytes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
unoptimized_version:
|
||||||
#endif
|
#endif
|
||||||
copy(static_cast<std::istream &>(input), static_cast<std::ostream &>(output), count);
|
copy(static_cast<std::istream &>(input), static_cast<std::ostream &>(output), count);
|
||||||
}
|
}
|
||||||
|
@ -158,6 +163,10 @@ void CopyHelper<bufferSize>::callbackCopy(NativeFileStream &input, NativeFileStr
|
||||||
const auto bytesToCopy = static_cast<std::size_t>(std::min(count, static_cast<std::uint64_t>(bufferSize)));
|
const auto bytesToCopy = static_cast<std::size_t>(std::min(count, static_cast<std::uint64_t>(bufferSize)));
|
||||||
const auto bytesCopied = ::sendfile64(output.fileDescriptor(), input.fileDescriptor(), nullptr, bytesToCopy);
|
const auto bytesCopied = ::sendfile64(output.fileDescriptor(), input.fileDescriptor(), nullptr, bytesToCopy);
|
||||||
if (bytesCopied < 0) {
|
if (bytesCopied < 0) {
|
||||||
|
if (errno == EINVAL && static_cast<std::uint64_t>(totalBytes) == count) {
|
||||||
|
// try again the unoptimized version, maybe the filesystem doesn't support sendfile
|
||||||
|
goto unoptimized_version;
|
||||||
|
}
|
||||||
throw std::ios_base::failure(argsToString("sendfile64() failed: ", std::strerror(errno)));
|
throw std::ios_base::failure(argsToString("sendfile64() failed: ", std::strerror(errno)));
|
||||||
}
|
}
|
||||||
count -= static_cast<std::uint64_t>(bytesCopied);
|
count -= static_cast<std::uint64_t>(bytesCopied);
|
||||||
|
@ -175,6 +184,7 @@ void CopyHelper<bufferSize>::callbackCopy(NativeFileStream &input, NativeFileStr
|
||||||
callback(1.0);
|
callback(1.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
unoptimized_version:
|
||||||
#endif
|
#endif
|
||||||
callbackCopy(static_cast<std::istream &>(input), static_cast<std::ostream &>(output), count, isAborted, callback);
|
callbackCopy(static_cast<std::istream &>(input), static_cast<std::ostream &>(output), count, isAborted, callback);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue