Fix indentation in twophase.c
[pgsql.git] / src / fe_utils / recovery_gen.c
blob99834a3b69e4b811f558e1b78df6b345ef9e4eec
1 /*-------------------------------------------------------------------------
3 * recovery_gen.c
4 * Generator for recovery configuration
6 * Portions Copyright (c) 2011-2023, PostgreSQL Global Development Group
8 *-------------------------------------------------------------------------
9 */
10 #include "postgres_fe.h"
12 #include "common/logging.h"
13 #include "fe_utils/recovery_gen.h"
14 #include "fe_utils/string_utils.h"
16 static char *escape_quotes(const char *src);
19 * Write recovery configuration contents into a fresh PQExpBuffer, and
20 * return it.
22 PQExpBuffer
23 GenerateRecoveryConfig(PGconn *pgconn, char *replication_slot)
25 PQconninfoOption *connOptions;
26 PQExpBufferData conninfo_buf;
27 char *escaped;
28 PQExpBuffer contents;
30 Assert(pgconn != NULL);
32 contents = createPQExpBuffer();
33 if (!contents)
34 pg_fatal("out of memory");
37 * In PostgreSQL 12 and newer versions, standby_mode is gone, replaced by
38 * standby.signal to trigger a standby state at recovery.
40 if (PQserverVersion(pgconn) < MINIMUM_VERSION_FOR_RECOVERY_GUC)
41 appendPQExpBufferStr(contents, "standby_mode = 'on'\n");
43 connOptions = PQconninfo(pgconn);
44 if (connOptions == NULL)
45 pg_fatal("out of memory");
47 initPQExpBuffer(&conninfo_buf);
48 for (PQconninfoOption *opt = connOptions; opt && opt->keyword; opt++)
50 /* Omit empty settings and those libpqwalreceiver overrides. */
51 if (strcmp(opt->keyword, "replication") == 0 ||
52 strcmp(opt->keyword, "dbname") == 0 ||
53 strcmp(opt->keyword, "fallback_application_name") == 0 ||
54 (opt->val == NULL) ||
55 (opt->val != NULL && opt->val[0] == '\0'))
56 continue;
58 /* Separate key-value pairs with spaces */
59 if (conninfo_buf.len != 0)
60 appendPQExpBufferChar(&conninfo_buf, ' ');
63 * Write "keyword=value" pieces, the value string is escaped and/or
64 * quoted if necessary.
66 appendPQExpBuffer(&conninfo_buf, "%s=", opt->keyword);
67 appendConnStrVal(&conninfo_buf, opt->val);
69 if (PQExpBufferDataBroken(conninfo_buf))
70 pg_fatal("out of memory");
73 * Escape the connection string, so that it can be put in the config file.
74 * Note that this is different from the escaping of individual connection
75 * options above!
77 escaped = escape_quotes(conninfo_buf.data);
78 termPQExpBuffer(&conninfo_buf);
79 appendPQExpBuffer(contents, "primary_conninfo = '%s'\n", escaped);
80 free(escaped);
82 if (replication_slot)
84 /* unescaped: ReplicationSlotValidateName allows [a-z0-9_] only */
85 appendPQExpBuffer(contents, "primary_slot_name = '%s'\n",
86 replication_slot);
89 if (PQExpBufferBroken(contents))
90 pg_fatal("out of memory");
92 PQconninfoFree(connOptions);
94 return contents;
98 * Write the configuration file in the directory specified in target_dir,
99 * with the contents already collected in memory appended. Then write
100 * the signal file into the target_dir. If the server does not support
101 * recovery parameters as GUCs, the signal file is not necessary, and
102 * configuration is written to recovery.conf.
104 void
105 WriteRecoveryConfig(PGconn *pgconn, char *target_dir, PQExpBuffer contents)
107 char filename[MAXPGPATH];
108 FILE *cf;
109 bool use_recovery_conf;
111 Assert(pgconn != NULL);
113 use_recovery_conf =
114 PQserverVersion(pgconn) < MINIMUM_VERSION_FOR_RECOVERY_GUC;
116 snprintf(filename, MAXPGPATH, "%s/%s", target_dir,
117 use_recovery_conf ? "recovery.conf" : "postgresql.auto.conf");
119 cf = fopen(filename, use_recovery_conf ? "w" : "a");
120 if (cf == NULL)
121 pg_fatal("could not open file \"%s\": %m", filename);
123 if (fwrite(contents->data, contents->len, 1, cf) != 1)
124 pg_fatal("could not write to file \"%s\": %m", filename);
126 fclose(cf);
128 if (!use_recovery_conf)
130 snprintf(filename, MAXPGPATH, "%s/%s", target_dir, "standby.signal");
131 cf = fopen(filename, "w");
132 if (cf == NULL)
133 pg_fatal("could not create file \"%s\": %m", filename);
135 fclose(cf);
140 * Escape a string so that it can be used as a value in a key-value pair
141 * a configuration file.
143 static char *
144 escape_quotes(const char *src)
146 char *result = escape_single_quotes_ascii(src);
148 if (!result)
149 pg_fatal("out of memory");
150 return result;