diff options
author | Martin Matuska <mm@FreeBSD.org> | 2023-07-08 18:31:38 +0000 |
---|---|---|
committer | Martin Matuska <mm@FreeBSD.org> | 2023-07-08 19:51:15 +0000 |
commit | 8113cc827611a88540736c92ced7d3a7020a1723 (patch) | |
tree | c0dfd7384659c83811aeb8d14cf888d65ae87831 | |
parent | 70c00442d2bcf76fe123d84d39ea81346dfa2290 (diff) | |
download | src-8113cc827611a88540736c92ced7d3a7020a1723.tar.gz src-8113cc827611a88540736c92ced7d3a7020a1723.zip |
cat: 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.
Reviewed by: imp, rmacklem
Differential revision: https://reviews.freebsd.org/D40882
-rw-r--r-- | bin/cat/cat.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/bin/cat/cat.c b/bin/cat/cat.c index a58bbe93835e..1158a839cfd8 100644 --- a/bin/cat/cat.c +++ b/bin/cat/cat.c @@ -83,6 +83,7 @@ static void usage(void) __dead2; static void scanfiles(char *argv[], int cooked); #ifndef BOOTSTRAP_CAT static void cook_cat(FILE *); +static ssize_t in_kernel_copy(int); #endif static void raw_cat(int); @@ -280,7 +281,16 @@ scanfiles(char *argv[], int cooked __unused) } #endif } else { +#ifndef BOOTSTRAP_CAT + if (in_kernel_copy(fd) == -1) { + if (errno == EINVAL) + raw_cat(fd); + else + err(1, "stdout"); + } +#else raw_cat(fd); +#endif if (fd != STDIN_FILENO) close(fd); } @@ -380,6 +390,21 @@ ilseq: if (ferror(stdout)) err(1, "stdout"); } + +static ssize_t +in_kernel_copy(int rfd) +{ + int wfd; + ssize_t ret; + + wfd = fileno(stdout); + ret = 1; + + while (ret > 0) + ret = copy_file_range(rfd, NULL, wfd, NULL, SSIZE_MAX, 0); + + return (ret); +} #endif /* BOOTSTRAP_CAT */ static void |