diff --git a/repmgr.c b/repmgr.c index c47cb2f9..e870ca43 100644 --- a/repmgr.c +++ b/repmgr.c @@ -159,7 +159,7 @@ static char *param_get(t_conninfo_param_list *param_list, const char *param); static bool parse_conninfo_string(const char *conninfo_str, t_conninfo_param_list *param_list, char *errmsg, bool ignore_application_name); static void conn_to_param_list(PGconn *conn, t_conninfo_param_list *param_list); static char *param_list_to_string(t_conninfo_param_list *param_list); -static void parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num); +static bool parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list); static void config_file_list_init(t_configfile_list *list, int max_size); static void config_file_list_add(t_configfile_list *list, const char *file, const char *filename, bool in_data_dir); @@ -7029,7 +7029,7 @@ run_basebackup(const char *data_dir, int server_version_num) * Parse the pg_basebackup_options provided in repmgr.conf - we'll want * to check later whether certain options were set by the user */ - parse_pg_basebackup_options(options.pg_basebackup_options, &backup_options, server_version_num); + parse_pg_basebackup_options(options.pg_basebackup_options, &backup_options, server_version_num, NULL); /* Create pg_basebackup command line options */ @@ -7852,6 +7852,8 @@ check_upstream_config(PGconn *conn, int server_version_num, bool exit_on_error) bool config_ok = true; char *wal_error_message = NULL; t_basebackup_options backup_options = T_BASEBACKUP_OPTIONS_INITIALIZER; + bool backup_options_ok = true; + ItemList backup_option_errors = { NULL, NULL }; bool xlog_stream = true; enum { @@ -7877,7 +7879,24 @@ check_upstream_config(PGconn *conn, int server_version_num, bool exit_on_error) * this will influence some checks */ - parse_pg_basebackup_options(options.pg_basebackup_options, &backup_options, server_version_num); + backup_options_ok = parse_pg_basebackup_options( + options.pg_basebackup_options, + &backup_options, server_version_num, + &backup_option_errors); + + if (backup_options_ok == false) + { + if (exit_on_error == true) + { + log_err(_("error(s) encountered parsing 'pg_basebackup_options'\n")); + print_error_list(&backup_option_errors, LOG_ERR); + log_hint(_("'pg_basebackup_options' is: '%s'\n"), options.pg_basebackup_options); + exit(ERR_BAD_CONFIG); + } + + config_ok = false; + } + if (strlen(backup_options.xlog_method) && strcmp(backup_options.xlog_method, "stream") != 0) xlog_stream = false; @@ -8762,8 +8781,8 @@ param_list_to_string(t_conninfo_param_list *param_list) } -static void -parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num) +static bool +parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list) { int options_len = strlen(pg_basebackup_options) + 1; char *options_string = pg_malloc(options_len); @@ -8785,6 +8804,8 @@ parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_opti struct option *long_options; + bool backup_options_ok = true; + /* We're only interested in these options */ static struct option long_options_9[] = { @@ -8793,17 +8814,21 @@ parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_opti {NULL, 0, NULL, 0} }; - /* From PostgreSQL 10, --xlog-method is renamed --wal-method */ + /* + * From PostgreSQL 10, --xlog-method is renamed --wal-method + * and there's also --no-slot, which we'll want to consider. + */ static struct option long_options_10[] = { {"slot", required_argument, NULL, 'S'}, {"wal-method", required_argument, NULL, 'X'}, + {"no-slot", no_argument, NULL, 1}, {NULL, 0, NULL, 0} }; /* Don't attempt to tokenise an empty string */ if (!strlen(pg_basebackup_options)) - return; + return backup_options_ok; if (server_version_num >= 100000) long_options = long_options_10; @@ -8855,6 +8880,9 @@ parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_opti /* Reset getopt's optind variable */ optind = 0; + /* Prevent getopt from emitting errors */ + opterr = 0; + while ((c = getopt_long(argc_item, argv_array, "S:X:", long_options, &optindex)) != -1) { @@ -8866,10 +8894,32 @@ parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_opti case 'X': strncpy(backup_options->xlog_method, optarg, MAXLEN); break; + case 1: + backup_options->no_slot = true; + break; + case '?': + if (server_version_num >= 100000 && optopt == 1) + { + if (error_list != NULL) + { + item_list_append(error_list, "invalid use of --no-slot"); + } + backup_options_ok = false; + } + break; } } - return; + if (backup_options->no_slot == true && backup_options->slot[0] != '\0') + { + if (error_list != NULL) + { + item_list_append(error_list, "--no-slot cannot be used with -S/--slot"); + } + backup_options_ok = false; + } + + return backup_options_ok; } static void diff --git a/repmgr.h b/repmgr.h index 47e0e236..8c2693f1 100644 --- a/repmgr.h +++ b/repmgr.h @@ -192,9 +192,10 @@ typedef struct { char slot[MAXLEN]; char xlog_method[MAXLEN]; + bool no_slot; /* from PostgreSQL 10 */ } t_basebackup_options; -#define T_BASEBACKUP_OPTIONS_INITIALIZER { "", "" } +#define T_BASEBACKUP_OPTIONS_INITIALIZER { "", "", false } typedef struct {