mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-26 16:46:28 +00:00
Initial refactoring of configuration file parsing
Have the configuration file parsing routine itself open the respective configuration file, rather than passing a file pointer from the original caller. This is required for handling include directives, which we'll want to do for sanity-checking the PostgreSQL configuration on a freshly cloned, unstarted standby.
This commit is contained in:
@@ -38,7 +38,11 @@ static sigjmp_buf *CONF_flex_fatal_jmp;
|
|||||||
static char *CONF_scanstr(const char *s);
|
static char *CONF_scanstr(const char *s);
|
||||||
static int CONF_flex_fatal(const char *msg);
|
static int CONF_flex_fatal(const char *msg);
|
||||||
|
|
||||||
static bool ProcessConfigFile(FILE *fp, const char *config_file, KeyValueList *contents, t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
static bool ProcessConfigFile(const char *config_file, const char *calling_file, KeyValueList *contents, t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
||||||
|
|
||||||
|
static bool ProcessConfigFp(FILE *fp, const char *config_file, KeyValueList *contents, t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
||||||
|
|
||||||
|
static char *AbsoluteConfigLocation(const char *location, const char *calling_file);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
@@ -91,19 +95,59 @@ STRING \'([^'\\\n]|\\.|\'\')*\'
|
|||||||
%%
|
%%
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
ProcessRepmgrConfigFile(FILE *fp, const char *config_file, t_configuration_options *options, ItemList *error_list, ItemList *warning_list)
|
ProcessRepmgrConfigFile(const char *config_file, t_configuration_options *options, ItemList *error_list, ItemList *warning_list)
|
||||||
{
|
{
|
||||||
return ProcessConfigFile(fp, config_file, NULL, options, error_list, warning_list);
|
return ProcessConfigFile(config_file, NULL, NULL, options, error_list, warning_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
ProcessPostgresConfigFile(FILE *fp, const char *config_file, KeyValueList *contents, ItemList *error_list, ItemList *warning_list)
|
ProcessPostgresConfigFile(const char *config_file, KeyValueList *contents, ItemList *error_list, ItemList *warning_list)
|
||||||
{
|
{
|
||||||
return ProcessConfigFile(fp, config_file, contents, NULL, error_list, warning_list);
|
return ProcessConfigFile(config_file, NULL, contents, NULL, error_list, warning_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ProcessConfigFile(FILE *fp, const char *config_file, KeyValueList *contents, t_configuration_options *options, ItemList *error_list, ItemList *warning_list)
|
ProcessConfigFile(const char *config_file, const char *calling_file, KeyValueList *contents, t_configuration_options *options, ItemList *error_list, ItemList *warning_list)
|
||||||
|
{
|
||||||
|
char *abs_path;
|
||||||
|
bool success = true;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reject file name that is all-blank (including empty), as that leads to
|
||||||
|
* confusion --- we'd try to read the containing directory as a file.
|
||||||
|
*/
|
||||||
|
if (strspn(config_file, " \t\r\n") == strlen(config_file))
|
||||||
|
{
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
abs_path = AbsoluteConfigLocation(config_file, calling_file);
|
||||||
|
|
||||||
|
// XXX reject direct recursion.
|
||||||
|
|
||||||
|
fp = fopen(abs_path, "r");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
item_list_append_format(error_list,
|
||||||
|
"could not open configuration file \"%s\": %s",
|
||||||
|
abs_path,
|
||||||
|
strerror(errno));
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = ProcessConfigFp(fp, abs_path, contents, options, error_list, warning_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(abs_path);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ProcessConfigFp(FILE *fp, const char *config_file, KeyValueList *contents, t_configuration_options *options, ItemList *error_list, ItemList *warning_list)
|
||||||
{
|
{
|
||||||
volatile bool OK = true;
|
volatile bool OK = true;
|
||||||
volatile YY_BUFFER_STATE lex_buffer = NULL;
|
volatile YY_BUFFER_STATE lex_buffer = NULL;
|
||||||
@@ -348,6 +392,36 @@ CONF_scanstr(const char *s)
|
|||||||
return newStr;
|
return newStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a configuration file or directory location that may be a relative
|
||||||
|
* path, return an absolute one. We consider the location to be relative to
|
||||||
|
* the directory holding the calling file, or to DataDir if no calling file.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
AbsoluteConfigLocation(const char *location, const char *calling_file)
|
||||||
|
{
|
||||||
|
char abs_path[MAXPGPATH];
|
||||||
|
|
||||||
|
if (is_absolute_path(location))
|
||||||
|
return strdup(location);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (calling_file != NULL)
|
||||||
|
{
|
||||||
|
strlcpy(abs_path, calling_file, sizeof(abs_path));
|
||||||
|
get_parent_directory(abs_path);
|
||||||
|
join_path_components(abs_path, abs_path, location);
|
||||||
|
canonicalize_path(abs_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*AssertState(DataDir);
|
||||||
|
join_path_components(abs_path, DataDir, location);
|
||||||
|
canonicalize_path(abs_path);*/
|
||||||
|
}
|
||||||
|
return strdup(abs_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flex fatal errors bring us here. Stash the error message and jump back to
|
* Flex fatal errors bring us here. Stash the error message and jump back to
|
||||||
|
|||||||
22
configfile.c
22
configfile.c
@@ -468,13 +468,17 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = fopen(config_file_path, "r");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A configuration file has been found, either provided by the user or
|
* A configuration file has been found, either provided by the user or
|
||||||
* found in one of the default locations. If we can't open it, fail with
|
* found in one of the default locations. Sanity check whether we
|
||||||
* an error.
|
* can open it, and fail with an error about the nature of the file
|
||||||
|
* (provided or default) if not. We do this here rather than having
|
||||||
|
* to teach the configuration file parser the difference.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
fp = fopen(config_file_path, "r");
|
||||||
|
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
{
|
{
|
||||||
if (config_file_provided)
|
if (config_file_provided)
|
||||||
@@ -491,10 +495,12 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) ProcessRepmgrConfigFile(fp, config_file_path, options, error_list, warning_list);
|
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
// XXX fail here if processing issue found
|
||||||
|
(void) ProcessRepmgrConfigFile(config_file_path, options, error_list, warning_list);
|
||||||
|
|
||||||
|
|
||||||
/* check required parameters */
|
/* check required parameters */
|
||||||
if (options->node_id == UNKNOWN_NODE_ID)
|
if (options->node_id == UNKNOWN_NODE_ID)
|
||||||
{
|
{
|
||||||
@@ -1951,6 +1957,7 @@ modify_auto_conf(const char *data_dir, KeyValueList *items)
|
|||||||
appendPQExpBuffer(&auto_conf, "%s/%s",
|
appendPQExpBuffer(&auto_conf, "%s/%s",
|
||||||
data_dir, PG_AUTOCONF_FILENAME);
|
data_dir, PG_AUTOCONF_FILENAME);
|
||||||
|
|
||||||
|
// XXX do we need this?
|
||||||
fp = fopen(auto_conf.data, "r");
|
fp = fopen(auto_conf.data, "r");
|
||||||
|
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
@@ -1961,10 +1968,11 @@ modify_auto_conf(const char *data_dir, KeyValueList *items)
|
|||||||
termPQExpBuffer(&auto_conf);
|
termPQExpBuffer(&auto_conf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
success = ProcessPostgresConfigFile(fp, auto_conf.data, &config, NULL, NULL);
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
success = ProcessPostgresConfigFile(auto_conf.data, &config, NULL, NULL);
|
||||||
|
|
||||||
|
|
||||||
if (success == false)
|
if (success == false)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "unable to process \"%s\"\n",
|
fprintf(stderr, "unable to process \"%s\"\n",
|
||||||
|
|||||||
@@ -351,8 +351,8 @@ const char *print_connection_check_type(ConnectionCheckType type);
|
|||||||
|
|
||||||
extern bool modify_auto_conf(const char *data_dir, KeyValueList *items);
|
extern bool modify_auto_conf(const char *data_dir, KeyValueList *items);
|
||||||
|
|
||||||
extern bool ProcessRepmgrConfigFile(FILE *fp, const char *config_file, t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
extern bool ProcessRepmgrConfigFile(const char *config_file, t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
||||||
|
|
||||||
extern bool ProcessPostgresConfigFile(FILE *fp, const char *config_file, KeyValueList *contents, ItemList *error_list, ItemList *warning_list);
|
extern bool ProcessPostgresConfigFile(const char *config_file, KeyValueList *contents, ItemList *error_list, ItemList *warning_list);
|
||||||
|
|
||||||
#endif /* _REPMGR_CONFIGFILE_H_ */
|
#endif /* _REPMGR_CONFIGFILE_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user