From 3dba8336e96f49325c76b4cb9482fc334be8085f Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Thu, 24 May 2018 15:49:25 +0900 Subject: [PATCH] standby clone: don't assume existence of "user" in upstream conninfo Usually a seperate user (typically "repmgr") is set up specifically to manage the repmgr metadata, however there's no compelling requirement to do this, and it's possible the database owner (usually: "postgres") will be used, in which case it's possible the username will be left out of the conninfo string. Addresses GitHub #437. --- dbutils.c | 31 +++++++++++++++++++++++++++++++ dbutils.h | 3 ++- repmgr-action-standby.c | 14 +++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/dbutils.c b/dbutils.c index 14c2f9d7..0b1a0b78 100644 --- a/dbutils.c +++ b/dbutils.c @@ -371,6 +371,37 @@ get_conninfo_value(const char *conninfo, const char *keyword, char *output) } +/* + * Get a default conninfo value for the provided parameter, and copy + * it to the 'output' buffer. + * + * Returns true on success, or false on failure (provided keyword not found). + * + */ +bool +get_conninfo_default_value(const char *param, char *output, int maxlen) +{ + PQconninfoOption *defs = NULL; + PQconninfoOption *def = NULL; + bool found = false; + + defs = PQconndefaults(); + + for (def = defs; def->keyword; def++) + { + if (strncmp(def->keyword, param, maxlen) == 0) + { + strncpy(output, def->val, maxlen); + found = true; + } + } + + PQconninfoFree(defs); + + return found; +} + + void initialize_conninfo_params(t_conninfo_param_list *param_list, bool set_defaults) { diff --git a/dbutils.h b/dbutils.h index 8d78ca71..461d4f55 100644 --- a/dbutils.h +++ b/dbutils.h @@ -357,7 +357,7 @@ void close_connection(PGconn **conn); /* conninfo manipulation functions */ bool get_conninfo_value(const char *conninfo, const char *keyword, char *output); - +bool get_conninfo_default_value(const char *param, char *output, int maxlen); void initialize_conninfo_params(t_conninfo_param_list *param_list, bool set_defaults); void free_conninfo_params(t_conninfo_param_list *param_list); void copy_conninfo_params(t_conninfo_param_list *dest_list, t_conninfo_param_list *source_list); @@ -369,6 +369,7 @@ bool parse_conninfo_string(const char *conninfo_str, t_conninfo_param_list *par char *param_list_to_string(t_conninfo_param_list *param_list); bool has_passfile(void); + /* transaction functions */ bool begin_transaction(PGconn *conn); bool commit_transaction(PGconn *conn); diff --git a/repmgr-action-standby.c b/repmgr-action-standby.c index 61ea0bda..faacdb37 100644 --- a/repmgr-action-standby.c +++ b/repmgr-action-standby.c @@ -4078,13 +4078,25 @@ check_source_server() if (record_status == RECORD_FOUND) { t_conninfo_param_list upstream_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER; + char *upstream_conninfo_user; initialize_conninfo_params(&upstream_conninfo, false); parse_conninfo_string(node_record.conninfo, &upstream_conninfo, NULL, false); strncpy(recovery_conninfo_str, node_record.conninfo, MAXLEN); strncpy(upstream_repluser, node_record.repluser, NAMEDATALEN); - strncpy(upstream_user, param_get(&upstream_conninfo, "user"), NAMEDATALEN); + + upstream_conninfo_user = param_get(&upstream_conninfo, "user"); + if (upstream_conninfo_user != NULL) + { + strncpy(upstream_user, upstream_conninfo_user, NAMEDATALEN); + } + else + { + get_conninfo_default_value("user", upstream_user, NAMEDATALEN); + } + + log_verbose(LOG_DEBUG, "upstream_user is \"%s\"", upstream_user); upstream_conninfo_found = true; }