Skip to content

Commit a33e17f

Browse files
committed
Rework internal command generation of pg_rewind
pg_rewind generates and executes internally up to two commands to work on the target cluster, depending on the options given by its caller: - postgres -C to retrieve the value of restore_command, when using -c/--restore-target-wal. - postgres --single to enforce recovery once and get the target cluster in a clean shutdown state. Both commands have been applying incorrect quoting rules, which could lead to failures when for example using a target data directory with unexpected characters like CRLFs. Those commands are now generated with PQExpBuffer, making use of string_utils.h to quote those commands as they should. We may extend those commands in the future with more options, so this makes any upcoming additions easier. This is arguably a bug fix, but nobody has complained about the existing code being a problem either, so no backpatch is done. Extracted from a larger patch by the same author. Author: Gunnar "Nick" Bluth Discussion: https://postgr.es/m/7c59265d-ac50-b0aa-ca1e-65e8bd27642a@pro-open.de
1 parent 7a85073 commit a33e17f

File tree

1 file changed

+33
-10
lines changed

1 file changed

+33
-10
lines changed

src/bin/pg_rewind/pg_rewind.c

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "common/restricted_token.h"
2424
#include "common/string.h"
2525
#include "fe_utils/recovery_gen.h"
26+
#include "fe_utils/string_utils.h"
2627
#include "file_ops.h"
2728
#include "filemap.h"
2829
#include "getopt_long.h"
@@ -1016,8 +1017,8 @@ getRestoreCommand(const char *argv0)
10161017
{
10171018
int rc;
10181019
char postgres_exec_path[MAXPGPATH],
1019-
postgres_cmd[MAXPGPATH],
10201020
cmd_output[MAXPGPATH];
1021+
PQExpBuffer postgres_cmd;
10211022

10221023
if (!restore_wal)
10231024
return;
@@ -1051,11 +1052,19 @@ getRestoreCommand(const char *argv0)
10511052
* Build a command able to retrieve the value of GUC parameter
10521053
* restore_command, if set.
10531054
*/
1054-
snprintf(postgres_cmd, sizeof(postgres_cmd),
1055-
"\"%s\" -D \"%s\" -C restore_command",
1056-
postgres_exec_path, datadir_target);
1055+
postgres_cmd = createPQExpBuffer();
10571056

1058-
if (!pipe_read_line(postgres_cmd, cmd_output, sizeof(cmd_output)))
1057+
/* path to postgres, properly quoted */
1058+
appendShellString(postgres_cmd, postgres_exec_path);
1059+
1060+
/* add -D switch, with properly quoted data directory */
1061+
appendPQExpBufferStr(postgres_cmd, " -D ");
1062+
appendShellString(postgres_cmd, datadir_target);
1063+
1064+
/* add -C switch, for restore_command */
1065+
appendPQExpBufferStr(postgres_cmd, " -C restore_command");
1066+
1067+
if (!pipe_read_line(postgres_cmd->data, cmd_output, sizeof(cmd_output)))
10591068
exit(1);
10601069

10611070
(void) pg_strip_crlf(cmd_output);
@@ -1067,6 +1076,8 @@ getRestoreCommand(const char *argv0)
10671076

10681077
pg_log_debug("using for rewind restore_command = \'%s\'",
10691078
restore_command);
1079+
1080+
destroyPQExpBuffer(postgres_cmd);
10701081
}
10711082

10721083

@@ -1080,7 +1091,7 @@ ensureCleanShutdown(const char *argv0)
10801091
int ret;
10811092
#define MAXCMDLEN (2 * MAXPGPATH)
10821093
char exec_path[MAXPGPATH];
1083-
char cmd[MAXCMDLEN];
1094+
PQExpBuffer postgres_cmd;
10841095

10851096
/* locate postgres binary */
10861097
if ((ret = find_other_exec(argv0, "postgres",
@@ -1119,14 +1130,26 @@ ensureCleanShutdown(const char *argv0)
11191130
* fsync here. This makes the recovery faster, and the target data folder
11201131
* is synced at the end anyway.
11211132
*/
1122-
snprintf(cmd, MAXCMDLEN, "\"%s\" --single -F -D \"%s\" template1 < \"%s\"",
1123-
exec_path, datadir_target, DEVNULL);
1133+
postgres_cmd = createPQExpBuffer();
11241134

1125-
if (system(cmd) != 0)
1135+
/* path to postgres, properly quoted */
1136+
appendShellString(postgres_cmd, exec_path);
1137+
1138+
/* add set of options with properly quoted data directory */
1139+
appendPQExpBufferStr(postgres_cmd, " --single -F -D ");
1140+
appendShellString(postgres_cmd, datadir_target);
1141+
1142+
/* finish with the database name, and a properly quoted redirection */
1143+
appendPQExpBufferStr(postgres_cmd, " template1 < ");
1144+
appendShellString(postgres_cmd, DEVNULL);
1145+
1146+
if (system(postgres_cmd->data) != 0)
11261147
{
11271148
pg_log_error("postgres single-user mode in target cluster failed");
1128-
pg_fatal("Command was: %s", cmd);
1149+
pg_fatal("Command was: %s", postgres_cmd->data);
11291150
}
1151+
1152+
destroyPQExpBuffer(postgres_cmd);
11301153
}
11311154

11321155
static void

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy