Blame SOURCES/0001-mptcpize-use-explicit-file-copy-instead-of-rename-16.patch

f01db0
From 591b3b168d949c45d5b5994332a3007767845434 Mon Sep 17 00:00:00 2001
f01db0
Message-Id: <591b3b168d949c45d5b5994332a3007767845434.1638277575.git.dcaratti@redhat.com>
f01db0
From: Paolo Abeni <paolo.abeni@gmail.com>
f01db0
Date: Thu, 14 Oct 2021 05:05:54 +0200
f01db0
Subject: [PATCH] mptcpize: use explicit file copy instead of rename() (#161)
f01db0
f01db0
The mentioned syscall fails if the involved files belong to
f01db0
different fs, which is pretty much expected in the relevant
f01db0
scenario (tmp file, in tmpfs, and unit file usually under the
f01db0
root partition)
f01db0
f01db0
Instead use sendfile() to explicitly copy all the contents. Note
f01db0
that we need to close and re-open the unit file, as sendfile()
f01db0
expect a O_WRITE fd as the target.
f01db0
---
f01db0
 src/mptcpize.c | 24 ++++++++++++++++++++----
f01db0
 1 file changed, 20 insertions(+), 4 deletions(-)
f01db0
f01db0
diff --git a/src/mptcpize.c b/src/mptcpize.c
f01db0
index cb79e09..b502d75 100644
f01db0
--- a/src/mptcpize.c
f01db0
+++ b/src/mptcpize.c
f01db0
@@ -13,6 +13,7 @@
f01db0
 
f01db0
 #include <sys/types.h>
f01db0
 #include <sys/stat.h>
f01db0
+#include <sys/sendfile.h>
f01db0
 
f01db0
 #include <argp.h>
f01db0
 #include <dlfcn.h>
f01db0
@@ -163,10 +164,12 @@ static int unit_update(int argc, char *argv[], int enable)
f01db0
 	char *unit, *line = NULL;
f01db0
 	int append_env = enable;
f01db0
 	char dst_path[PATH_MAX];
f01db0
+	off_t bytes_copied = 0;
f01db0
+	struct stat fileinfo;
f01db0
+	int dst, unit_fd;
f01db0
 	size_t len = 0;
f01db0
 	ssize_t read;
f01db0
 	FILE *src;
f01db0
-	int dst;
f01db0
 
f01db0
 	if (argc < 1) {
f01db0
 		fprintf(stderr, "missing unit argument\n");
f01db0
@@ -210,11 +213,24 @@ static int unit_update(int argc, char *argv[], int enable)
f01db0
 		error(1, errno, "can't read from %s", unit);
f01db0
 	free(line);
f01db0
 	fclose(src);
f01db0
-	close(dst);
f01db0
 
f01db0
-	if (rename(dst_path, unit) < 0)
f01db0
-		error(1, errno, "can't rename %s to %s", dst_path, unit);
f01db0
+	// copy back the modified file into the original unit
f01db0
+	// note: avoid using rename, as it fails across filesystems
f01db0
+	if (fstat(dst, &fileinfo) < 0)
f01db0
+		error(1, errno, "can't stat %s", dst_path);
f01db0
+
f01db0
+	// re-open the unit file for writing
f01db0
+	// mkstemp already opened the temporary file for R/W so we don't need
f01db0
+	// to touch that file descriptor.
f01db0
+	unit_fd = open(unit, O_TRUNC | O_RDWR);
f01db0
+	if (unit_fd < 0)
f01db0
+		error(1, errno, "can't open %s for writing", unit);
f01db0
 
f01db0
+	while (bytes_copied < fileinfo.st_size)
f01db0
+		if (sendfile(unit_fd, dst, &bytes_copied, fileinfo.st_size - bytes_copied) < 0)
f01db0
+			error(1, errno, "can't copy from %s to %s", dst_path, unit);
f01db0
+
f01db0
+	close(dst);
f01db0
 	if (system("systemctl daemon-reload") != 0)
f01db0
 		error(1, errno, "can't reload unit, manual 'systemctl daemon-reload' is required");
f01db0
 
f01db0
-- 
f01db0
2.31.1
f01db0