daemon: Loop over ‘copy_file_range’ upon short writes.

Fixes <https://issues.guix.gnu.org/70877>.

* nix/libutil/util.cc (copyFile): Loop over ‘copy_file_range’ instead of
throwing upon short write.

Reported-by: Ricardo Wurmus <rekado@elephly.net>
Change-Id: Id7b8a65ea59006c2d91bc23732309a68665b9ca0
This commit is contained in:
Ludovic Courtès 2024-05-13 12:02:30 +02:00
parent be235a3092
commit 7757fdd491
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5

View file

@ -397,9 +397,14 @@ static void copyFile(int sourceFd, int destinationFd)
} else {
if (result < 0)
throw SysError(format("copy_file_range `%1%' to `%2%'") % sourceFd % destinationFd);
if (result < st.st_size)
throw SysError(format("short write in copy_file_range `%1%' to `%2%'")
% sourceFd % destinationFd);
/* If 'copy_file_range' copied less than requested, try again. */
for (ssize_t copied = result; copied < st.st_size; copied += result) {
result = copy_file_range(sourceFd, NULL, destinationFd, NULL,
st.st_size - copied, 0);
if (result < 0)
throw SysError(format("copy_file_range `%1%' to `%2%'") % sourceFd % destinationFd);
}
}
}