diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index d3565a5..0e15562 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -137,7 +137,7 @@ ProcessConfigFile(GucContext context) /* Parse the file into a list of option names and values */ head = tail = NULL; - if (!ParseConfigFile(ConfigFileName, NULL, true, 0, elevel, &head, &tail)) + if (!ParseConfigFile(ConfigFileName, NULL, true, true, 0, elevel, &head, &tail)) { /* Syntax error(s) detected in the file, so bail out */ error = true; @@ -145,6 +145,40 @@ ProcessConfigFile(GucContext context) } /* + * If DataDir is now set, search for a recovery.conf file so we can + * read any parameters from that as well. If DataDir isn't set by now, + * we can ignore it, since it will error out at next level up. + * + * This step is the same as saying "include_if_exists recovery.conf" + * as the last line of the postgresql.conf + * + * recovery.conf is renamed to recovery.done at the end of recovery. + * Note that this means the contents of recovery.conf will not be + * reread when we SIGHUP after the end of recovery, so that all + * recovery parameters will end up at their boot values. + * + * Note also that this means that we use the setting of data_directory + * as it exists now for the purposes of reading recovery.conf. + * Some will note that setting data_directory inside recovery.conf + * could change the final value of that. If anybody thinks that is + * even remotely likely, we can put specific trap against that occurring + * easily enough. + */ +#define RECOVERY_COMMAND_FILE "recovery.conf" + if (DataDir) + { + char RecoveryConfFileName[MAXPGPATH]; + + snprintf(RecoveryConfFileName, MAXPGPATH, "%s/%s", DataDir, RECOVERY_COMMAND_FILE); + if (!ParseConfigFile(RecoveryConfFileName, NULL, false, false, 0, elevel, &head, &tail)) + { + /* Syntax error(s) detected in the file, so bail out */ + error = true; + goto cleanup_list; + } + } + + /* * Mark all extant GUC variables as not present in the config file. * We need this so that we can tell below which ones have been removed * from the file since we last processed it. @@ -404,7 +438,8 @@ AbsoluteConfigLocation(const char *location, const char *calling_file) * and absolute-ifying the path name if necessary. */ bool -ParseConfigFile(const char *config_file, const char *calling_file, bool strict, +ParseConfigFile(const char *config_file, const char *calling_file, + bool strict, bool log, int depth, int elevel, ConfigVariable **head_p, ConfigVariable **tail_p) @@ -439,7 +474,8 @@ ParseConfigFile(const char *config_file, const char *calling_file, bool strict, return false; } - ereport(LOG, + if (log) + ereport(LOG, (errmsg("skipping missing configuration file \"%s\"", config_file))); return OK; @@ -592,7 +628,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, * An include_if_exists directive isn't a variable and should be * processed immediately. */ - if (!ParseConfigFile(opt_value, config_file, false, + if (!ParseConfigFile(opt_value, config_file, false, true, depth + 1, elevel, head_p, tail_p)) OK = false; @@ -606,7 +642,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, * An include directive isn't a variable and should be processed * immediately. */ - if (!ParseConfigFile(opt_value, config_file, true, + if (!ParseConfigFile(opt_value, config_file, true, true, depth + 1, elevel, head_p, tail_p)) OK = false; @@ -614,6 +650,10 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, pfree(opt_name); pfree(opt_value); } + else if (guc_name_compare(opt_name, "data_directory") == 0) + { + SetDataDir(opt_value); + } else { /* ordinary variable, append to list */ @@ -779,7 +819,7 @@ ParseConfigDirectory(const char *includedir, qsort(filenames, num_filenames, sizeof(char *), pg_qsort_strcmp); for (i = 0; i < num_filenames; i++) { - if (!ParseConfigFile(filenames[i], NULL, true, + if (!ParseConfigFile(filenames[i], NULL, true, true, depth, elevel, head_p, tail_p)) { status = false; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index f9fb264..96f6727 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -4120,6 +4120,13 @@ SelectConfigFiles(const char *userDoption, const char *progname) configdir = make_absolute_path(getenv("PGDATA")); /* + * Set our initial value of DataDir from the configdir. + * This may be overidden later if data_directory parameter is set. + */ + if (configdir) + SetDataDir(configdir); + + /* * Find the configuration file: if config_file was specified on the * command line, use it, else use configdir/postgresql.conf. In any case * ensure the result is an absolute path, so that it will be interpreted @@ -4165,15 +4172,8 @@ SelectConfigFiles(const char *userDoption, const char *progname) /* * If the data_directory GUC variable has been set, use that as DataDir; * otherwise use configdir if set; else punt. - * - * Note: SetDataDir will copy and absolute-ize its argument, so we don't - * have to. */ - if (data_directory) - SetDataDir(data_directory); - else if (configdir) - SetDataDir(configdir); - else + if (!DataDir) { write_stderr("%s does not know where to find the database system data.\n" "This can be specified as \"data_directory\" in \"%s\", " diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 42428cb..16130e2 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -112,7 +112,7 @@ typedef struct ConfigVariable } ConfigVariable; extern bool ParseConfigFile(const char *config_file, const char *calling_file, - bool strict, int depth, int elevel, + bool strict, bool log, int depth, int elevel, ConfigVariable **head_p, ConfigVariable **tail_p); extern bool ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,