From: Egor Chelak Date: Fri, 6 Nov 2020 09:15:11 +0000 (+0200) Subject: ul_copy_file: use sendfile X-Git-Tag: v2.37-rc1~393^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a8b4e7cad1237ba021c02febb84aa8697e0944c0;p=thirdparty%2Futil-linux.git ul_copy_file: use sendfile Suggested-by: Karel Zak Reviewed-by: Sami Kerola Signed-off-by: Egor Chelak --- diff --git a/lib/fileutils.c b/lib/fileutils.c index 9e0823d30e..557fae0414 100644 --- a/lib/fileutils.c +++ b/lib/fileutils.c @@ -6,10 +6,12 @@ */ #include #include +#include #include #include #include #include +#include #include #include "c.h" @@ -248,8 +250,7 @@ char *stripoff_last_component(char *path) return p + 1; } -/* Copies the contents of a file. Returns -1 on read error, -2 on write error. */ -int ul_copy_file(int from, int to) +static int copy_file_simple(int from, int to) { ssize_t nr, nw, off; char buf[8 * 1024]; @@ -265,3 +266,28 @@ int ul_copy_file(int from, int to) #endif return 0; } + +/* Copies the contents of a file. Returns -1 on read error, -2 on write error. */ +int ul_copy_file(int from, int to) +{ + struct stat st; + ssize_t nw; + off_t left; + + if (fstat(from, &st) == -1) + return -1; + if (!S_ISREG(st.st_mode)) + return copy_file_simple(from, to); + for (left = st.st_size; left != 0; left -= nw) { + if ((nw = sendfile(to, from, NULL, left)) < 0) + return copy_file_simple(from, to); + if (!nw) + return 0; + } + /* For extra robustness, treat st_size as advisory and ensure that we + * actually get EOF. */ + while ((nw = sendfile(to, from, NULL, 1024*1024)) != 0) + if (nw < 0) + return copy_file_simple(from, to); + return 0; +}