xinstall: use copy_file_range(2) with fallback to previous behavior

This allows to use special filesystem features like server-side
copying on NFS 4.2 or block cloning on OpenZFS 2.2.

Note: copy_file_range(2) is not used when a digest calculation is
requested as this would require to read the input file twice.

Reviewed by:	asomers, imp, rmacklem
Differential revision:	https://reviews.freebsd.org/D40898
This commit is contained in:
Martin Matuska 2023-07-08 21:46:46 +02:00
parent 8113cc8276
commit 5a50d52f11

View File

@ -1300,6 +1300,7 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
static size_t bufsize;
int nr, nw;
int serrno;
ssize_t ret;
char *p;
int done_copy;
DIGEST_CTX ctx;
@ -1310,6 +1311,26 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1)
err(EX_OSERR, "lseek: %s", to_name);
/* Try copy_file_range() if no digest is requested */
if (digesttype == DIGEST_NONE) {
ret = 1;
while (ret > 0) {
ret = copy_file_range(from_fd, NULL, to_fd, NULL,
SSIZE_MAX, 0);
}
if (ret == 0) {
/* DIGEST_NONE always returns NULL */
return (NULL);
}
if (errno != EINVAL) {
serrno = errno;
(void)unlink(to_name);
errno = serrno;
err(EX_OSERR, "%s", to_name);
}
/* Fall back */
}
digest_init(&ctx);
done_copy = 0;