From 5d4032bd916915bd9bd270628a42e03239686ecf Mon Sep 17 00:00:00 2001
From: Alena Vinter <dlaaren8@gmail.com>
Date: Tue, 2 Sep 2025 18:15:13 +0700
Subject: [PATCH v4 1/2] Implements helper function in recovery_gen

These functions support pg_createsubscriber's need to temporarily
configure recovery params and ensure proper cleanup after the conversion
to logical replication is complete.
---
 src/fe_utils/recovery_gen.c         | 77 +++++++++++++++++++++++++++++
 src/include/fe_utils/recovery_gen.h |  3 ++
 2 files changed, 80 insertions(+)

diff --git a/src/fe_utils/recovery_gen.c b/src/fe_utils/recovery_gen.c
index e9023584768..e8e0dde9e00 100644
--- a/src/fe_utils/recovery_gen.c
+++ b/src/fe_utils/recovery_gen.c
@@ -10,6 +10,7 @@
 #include "postgres_fe.h"
 
 #include "common/logging.h"
+#include "common/file_utils.h"
 #include "fe_utils/recovery_gen.h"
 #include "fe_utils/string_utils.h"
 
@@ -234,3 +235,79 @@ GetDbnameFromConnectionOptions(const char *connstr)
 	PQconninfoFree(conn_opts);
 	return dbname;
 }
+
+PQExpBuffer
+GetRecoveryConfig(PGconn *pgconn, const char *target_dir)
+{
+	PQExpBuffer contents;
+	char		filename[MAXPGPATH];
+	FILE	   *cf;
+	bool		use_recovery_conf;
+
+	char data[1024];
+	size_t bytes_read;
+
+	Assert(pgconn != NULL);
+
+	contents = createPQExpBuffer();
+	if (!contents)
+		pg_fatal("out of memory");
+
+	use_recovery_conf =
+		PQserverVersion(pgconn) < MINIMUM_VERSION_FOR_RECOVERY_GUC;
+
+	snprintf(filename, MAXPGPATH, "%s/%s", target_dir,
+			 use_recovery_conf ? "recovery.conf" : "postgresql.auto.conf");
+
+	cf = fopen(filename, "r");
+	if (cf == NULL)
+		pg_fatal("could not open file \"%s\": %m", filename);
+
+	while ((bytes_read = fread(data, 1, sizeof(data), cf)) > 0)
+	{
+		data[bytes_read] = '\0';
+		appendPQExpBufferStr(contents, data);
+	}
+
+	if (ferror(cf))
+	{
+		pg_fatal("could not read from file \"%s\": %m", filename);
+	}
+
+	fclose(cf);
+
+	return contents;
+}
+
+void
+ReplaceRecoveryConfig(PGconn *pgconn, const char *target_dir, PQExpBuffer contents)
+{
+	char		tmp_filename[MAXPGPATH];
+	char		filename[MAXPGPATH];
+	FILE	   *cf;
+	bool		use_recovery_conf;
+
+	Assert(pgconn != NULL);
+
+	use_recovery_conf =
+		PQserverVersion(pgconn) < MINIMUM_VERSION_FOR_RECOVERY_GUC;
+
+	snprintf(tmp_filename, MAXPGPATH, "%s/%s.tmp", target_dir,
+			 use_recovery_conf ? "recovery.conf" : "postgresql.auto.conf");
+
+	snprintf(filename, MAXPGPATH, "%s/%s", target_dir,
+			 use_recovery_conf ? "recovery.conf" : "postgresql.auto.conf");
+
+	cf = fopen(tmp_filename, "w");
+	if (cf == NULL)
+		pg_fatal("could not open file \"%s\": %m", tmp_filename);
+
+	if (fwrite(contents->data, contents->len, 1, cf) != 1)
+		pg_fatal("could not write to file \"%s\": %m", tmp_filename);
+
+	fclose(cf);
+
+	if (durable_rename(tmp_filename, filename) != 0)
+		pg_fatal("could not rename file \"%s\" to \"%s\": %m",
+				 tmp_filename, filename);
+}
diff --git a/src/include/fe_utils/recovery_gen.h b/src/include/fe_utils/recovery_gen.h
index c13f2263bcd..18219af966b 100644
--- a/src/include/fe_utils/recovery_gen.h
+++ b/src/include/fe_utils/recovery_gen.h
@@ -27,4 +27,7 @@ extern void WriteRecoveryConfig(PGconn *pgconn, const char *target_dir,
 								PQExpBuffer contents);
 extern char *GetDbnameFromConnectionOptions(const char *connstr);
 
+extern PQExpBuffer GetRecoveryConfig(PGconn *pgconn, const char *target_dir);
+extern void ReplaceRecoveryConfig(PGconn *pgconn, const char *target_dir, PQExpBuffer contents);
+
 #endif							/* RECOVERY_GEN_H */
-- 
2.39.5 (Apple Git-154)

