Consistently use "superuser" instead of "super user"
[pgsql.git] / src / fe_utils / recovery_gen.c
blob2643ecd6f3f91481c984b4e406bb119d914dab3e
1 /*-------------------------------------------------------------------------
3 * recovery_gen.c
4 * Generator for recovery configuration
6 * Portions Copyright (c) 2011-2021, 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)
35 pg_log_error("out of memory");
36 exit(1);
40 * In PostgreSQL 12 and newer versions, standby_mode is gone, replaced by
41 * standby.signal to trigger a standby state at recovery.
43 if (PQserverVersion(pgconn) < MINIMUM_VERSION_FOR_RECOVERY_GUC)
44 appendPQExpBufferStr(contents, "standby_mode = 'on'\n");
46 connOptions = PQconninfo(pgconn);
47 if (connOptions == NULL)
49 pg_log_error("out of memory");
50 exit(1);
53 initPQExpBuffer(&conninfo_buf);
54 for (PQconninfoOption *opt = connOptions; opt && opt->keyword; opt++)
56 /* Omit empty settings and those libpqwalreceiver overrides. */
57 if (strcmp(opt->keyword, "replication") == 0 ||
58 strcmp(opt->keyword, "dbname") == 0 ||
59 strcmp(opt->keyword, "fallback_application_name") == 0 ||
60 (opt->val == NULL) ||
61 (opt->val != NULL && opt->val[0] == '\0'))
62 continue;
64 /* Separate key-value pairs with spaces */
65 if (conninfo_buf.len != 0)
66 appendPQExpBufferChar(&conninfo_buf, ' ');
69 * Write "keyword=value" pieces, the value string is escaped and/or
70 * quoted if necessary.
72 appendPQExpBuffer(&conninfo_buf, "%s=", opt->keyword);
73 appendConnStrVal(&conninfo_buf, opt->val);
75 if (PQExpBufferDataBroken(conninfo_buf))
77 pg_log_error("out of memory");
78 exit(1);
82 * Escape the connection string, so that it can be put in the config file.
83 * Note that this is different from the escaping of individual connection
84 * options above!
86 escaped = escape_quotes(conninfo_buf.data);
87 termPQExpBuffer(&conninfo_buf);
88 appendPQExpBuffer(contents, "primary_conninfo = '%s'\n", escaped);
89 free(escaped);
91 if (replication_slot)
93 /* unescaped: ReplicationSlotValidateName allows [a-z0-9_] only */
94 appendPQExpBuffer(contents, "primary_slot_name = '%s'\n",
95 replication_slot);
98 if (PQExpBufferBroken(contents))
100 pg_log_error("out of memory");
101 exit(1);
104 PQconninfoFree(connOptions);
106 return contents;
110 * Write the configuration file in the directory specified in target_dir,
111 * with the contents already collected in memory appended. Then write
112 * the signal file into the target_dir. If the server does not support
113 * recovery parameters as GUCs, the signal file is not necessary, and
114 * configuration is written to recovery.conf.
116 void
117 WriteRecoveryConfig(PGconn *pgconn, char *target_dir, PQExpBuffer contents)
119 char filename[MAXPGPATH];
120 FILE *cf;
121 bool use_recovery_conf;
123 Assert(pgconn != NULL);
125 use_recovery_conf =
126 PQserverVersion(pgconn) < MINIMUM_VERSION_FOR_RECOVERY_GUC;
128 snprintf(filename, MAXPGPATH, "%s/%s", target_dir,
129 use_recovery_conf ? "recovery.conf" : "postgresql.auto.conf");
131 cf = fopen(filename, use_recovery_conf ? "w" : "a");
132 if (cf == NULL)
134 pg_log_error("could not open file \"%s\": %m", filename);
135 exit(1);
138 if (fwrite(contents->data, contents->len, 1, cf) != 1)
140 pg_log_error("could not write to file \"%s\": %m", filename);
141 exit(1);
144 fclose(cf);
146 if (!use_recovery_conf)
148 snprintf(filename, MAXPGPATH, "%s/%s", target_dir, "standby.signal");
149 cf = fopen(filename, "w");
150 if (cf == NULL)
152 pg_log_error("could not create file \"%s\": %m", filename);
153 exit(1);
156 fclose(cf);
161 * Escape a string so that it can be used as a value in a key-value pair
162 * a configuration file.
164 static char *
165 escape_quotes(const char *src)
167 char *result = escape_single_quotes_ascii(src);
169 if (!result)
171 pg_log_error("out of memory");
172 exit(1);
174 return result;