]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
dumpfd2fd: use copy_file_range if available (add testsuite for it)
authorBaptiste Daroussin <bapt@FreeBSD.org>
Thu, 5 Jan 2023 09:44:34 +0000 (10:44 +0100)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Thu, 5 Jan 2023 09:44:34 +0000 (10:44 +0100)
ChangeLog
configure.ac
src/dumpfd2fd.c
tests/mlmmj.c

index bb82ad058ba3a5eb824ed76943297714603ba3b8..7b05bae848323abad57955a145bc5c805a91c727 100644 (file)
--- 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, ...)
index 5709f0e88e666c5546219d57f7b69a2e074a9972..621641315113ed2713aae42d8de18e8aa86921cc 100644 (file)
@@ -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])
index 009fcb1af9b83da8c3304c809c6aa4837164617c..7e70eda444489d92ca64b1d1815203509a9e0fe1 100644 (file)
@@ -1,6 +1,6 @@
-/* Copyright (C) 2004 Mads Martin Joergensen <mmj at mmj dot dk>
- *
- * $Id$
+/*
+ * Copyright (C) 2004 Mads Martin Joergensen <mmj at mmj dot dk>
+ * Copyright (C) 2023 Baptiste Daroussin <bapt@FreeBSD.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
  * IN THE SOFTWARE.
  */
 
+#include <sys/limits.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
+#include <stdbool.h>
 
-#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);
 }
index cd6968ed1ca0fccfc0d5be6ea0222e2f9c9a33fa..2a96a2c6095d3b544b1a1641f5938484ffb3eb9b 100644 (file)
@@ -20,6 +20,7 @@
  * IN THE SOFTWARE.
  */
 
+#include <sys/fcntl.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
@@ -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());
 }