From: Baptiste Daroussin Date: Thu, 5 Jan 2023 09:44:34 +0000 (+0100) Subject: dumpfd2fd: use copy_file_range if available (add testsuite for it) X-Git-Tag: RELEASE_1_4_0_a2~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cff8cfe2892448bed8fa2d741605c7c8a5e043e6;p=thirdparty%2Fmlmmj.git dumpfd2fd: use copy_file_range if available (add testsuite for it) --- diff --git a/ChangeLog b/ChangeLog index bb82ad05..7b05bae8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ 1.4.0-a2 o Fix a crash with forged probe emails o mlmmj-send does not need anymore absolute path + o Use copy_file_range if available + o Use arc4random_uniform if available 1.4.0-a1 o Add a test suite o Modernize code (dprintf, posix_spawn, asprintf, getline, daemon, ...) diff --git a/configure.ac b/configure.ac index 5709f0e8..62164131 100644 --- a/configure.ac +++ b/configure.ac @@ -48,7 +48,7 @@ AM_CONDITIONAL(WANT_RECEIVESTRIP, test x"$enable_receive_strip" = xyes) AC_FUNC_MALLOC AC_CHECK_FUNCS([ftruncate memset socket strerror strncasecmp snprintf fcntl]) AC_CHECK_FUNCS([nanosleep time strftime syslog regcomp regexec]) -AC_CHECK_FUNCS([arc4random_uniform]) +AC_CHECK_FUNCS([arc4random_uniform copy_file_range]) PKG_CHECK_MODULES([ATF], [atf-c]) AC_CONFIG_FILES([Makefile]) diff --git a/src/dumpfd2fd.c b/src/dumpfd2fd.c index 009fcb1a..7e70eda4 100644 --- a/src/dumpfd2fd.c +++ b/src/dumpfd2fd.c @@ -1,6 +1,6 @@ -/* Copyright (C) 2004 Mads Martin Joergensen - * - * $Id$ +/* + * Copyright (C) 2004 Mads Martin Joergensen + * Copyright (C) 2023 Baptiste Daroussin * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -21,31 +21,60 @@ * IN THE SOFTWARE. */ +#include #include -#include #include #include #include +#include -#include "wrappers.h" +#include "config.h" #define DUMPBUF 4096 -int dumpfd2fd(int infd, int outfd) +static int +_copy_file(int from, int to) { - size_t n; char buf[DUMPBUF]; + ssize_t r, wresid, w = 0; + char *bufp; + r = read(from, buf, DUMPBUF); + if (r < 0) + return (r); + for (bufp = buf, wresid = r; ; bufp += w, wresid -= w) { + w = write(to, bufp, wresid); + if (w <= 0) + break; + if (w >= (ssize_t) wresid) + break; + } + return (w < 0 ? w : r); +} + +int dumpfd2fd(int from, int to) +{ +#ifdef HAVE_COPY_FILE_RANGE2 + bool cfr = true; +#endif + int r; - while((n = read(infd, &buf, sizeof(buf))) != 0) { - if(n < 0) { - if(errno == EINTR) - continue; - else - return -1; /* Caller can check errno */ + do { +#ifdef HAVE_COPY_FILE_RANGE2 + if (cfr) { + r = copy_file_range(from, NULL, to, NULL, SSIZE_MAX, 0); + if (r < 0 && errno == EINVAL) { + printf("la\n"); + /* probably a non seekable FD */ + cfr = false; + } } - if(writen(outfd, &buf, n) < 0) - return -1; /* Caller can check errno */ - } - - return 0; + if (!cfr) { +#endif + r = _copy_file(from, to); +#ifdef HAVE_COPY_FILE_RANGE2 + } +#endif + } while (r > 0); + + return (r); } diff --git a/tests/mlmmj.c b/tests/mlmmj.c index cd6968ed..2a96a2c6 100644 --- a/tests/mlmmj.c +++ b/tests/mlmmj.c @@ -20,6 +20,7 @@ * IN THE SOFTWARE. */ +#include #include #include #include @@ -107,6 +108,7 @@ ATF_TC_WITHOUT_HEAD(getlistaddr); ATF_TC_WITHOUT_HEAD(statctrl); ATF_TC_WITHOUT_HEAD(is_subbed_in); ATF_TC_WITHOUT_HEAD(getaddrsfromfile); +ATF_TC_WITHOUT_HEAD(dumpfd2fd); #ifndef NELEM #define NELEM(array) (sizeof(array) / sizeof((array)[0])) @@ -1675,6 +1677,38 @@ ATF_TC_BODY(getaddrsfromfile, tc) fclose(fp); } +ATF_TC_BODY(dumpfd2fd, tc) +{ + FILE *plop = fopen("from", "w"); + fprintf(plop, "bla\n"); + fclose(plop); + + int from = open("from", O_RDONLY); + int to = open("to.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644); + + ATF_REQUIRE_EQ_MSG(dumpfd2fd(from, to), 0, "Invalid simple copy"); + close(from); + close(to); + + if (!atf_utils_compare_file("to.txt", "bla\n")) { + atf_utils_cat_file("to.txt", ""); + atf_tc_fail("Unexpected output"); + } + + /* non seekable */ + int shm = shm_open("/tmp/myshm", O_RDWR | O_CREAT, 0644); + ftruncate(shm, strlen("bla\n")); + dprintf(shm, "bla\n"); + from = shm_open("/tmp/myshm", O_RDONLY, 0644); + to = open("tobla.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644); + int ret = dumpfd2fd(from, to); + ATF_REQUIRE_EQ_MSG(ret, 0, "Invalid simple copy %d", ret); + if (!atf_utils_compare_file("tobla.txt", "bla\n")) { + atf_utils_cat_file("tobla.txt", ">>"); + atf_tc_fail("Unexpected output"); + } +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, random_int); @@ -1728,6 +1762,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, statctrl); ATF_TP_ADD_TC(tp, is_subbed_in); ATF_TP_ADD_TC(tp, getaddrsfromfile); + ATF_TP_ADD_TC(tp, dumpfd2fd); return (atf_no_error()); }