aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLongPing Wei <weilongping@huawei.com>2022-03-16 10:38:55 +0800
committerRob Landley <rob@landley.net>2022-03-17 09:10:17 -0500
commit613db35596e37c16063d531de6d635f0bd3b2f52 (patch)
tree879cd76d750e315e647f08f58d65fc69abfbbbcc /lib
parent745947434342b5ae8b8147849561c5fff4b0d82b (diff)
downloadtoybox-613db35596e37c16063d531de6d635f0bd3b2f52.tar.gz
Enable copy_file_range when it is available.
Fallback to read+write when copy_file_range failed, as both fd_in and fd_out must refer to regular files. Signed-off-by: LongPing Wei <weilongping@huawei.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/portability.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/lib/portability.c b/lib/portability.c
index 5f98138c..d7648a8f 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -629,20 +629,25 @@ int get_block_device_size(int fd, unsigned long long* size)
long long sendfile_len(int in, int out, long long bytes, long long *consumed)
{
long long total = 0, len, ww;
+ int copy_file_range = CFG_TOYBOX_COPYFILERANGE;
if (consumed) *consumed = 0;
if (in<0) return 0;
while (bytes != total) {
ww = 0;
len = bytes-total;
- if (bytes<0 || len>sizeof(libbuf)) len = sizeof(libbuf);
errno = 0;
-#if CFG_TOYBOX_COPYFILERANGE
- len = copy_file_range(in, 0, out, 0, bytes, 0);
-#else
- ww = len = read(in, libbuf, len);
-#endif
+ if (copy_file_range) {
+ if (bytes<0) len = INT_MAX;
+ len = syscall(__NR_copy_file_range, in, 0, out, 0, len, 0);
+ if (len < 0 && errno == EINVAL)
+ copy_file_range = 0;
+ }
+ if (!copy_file_range) {
+ if (bytes<0 || len>sizeof(libbuf)) len = sizeof(libbuf);
+ ww = len = read(in, libbuf, len);
+ }
if (len<1 && errno==EAGAIN) continue;
if (len<1) break;
if (consumed) *consumed += len;