32static bool GetConfigOptions(std::istream& stream,
const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections)
35 std::string::size_type pos;
37 while (std::getline(stream, str)) {
38 bool used_hash =
false;
39 if ((pos = str.find(
'#')) != std::string::npos) {
40 str = str.substr(0, pos);
43 const static std::string pattern =
" \t\r\n";
46 if (*str.begin() ==
'[' && *str.rbegin() ==
']') {
47 const std::string section = str.substr(1, str.size() - 2);
48 sections.emplace_back(
SectionInfo{section, filepath, linenr});
50 }
else if (*str.begin() ==
'-') {
51 error =
strprintf(
"parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str);
53 }
else if ((pos = str.find(
'=')) != std::string::npos) {
55 std::string_view value =
TrimStringView(std::string_view{str}.substr(pos + 1), pattern);
56 if (used_hash &&
name.find(
"rpcpassword") != std::string::npos) {
57 error =
strprintf(
"parse error on line %i, using # in rpcpassword can be ambiguous and should be avoided", linenr);
60 options.emplace_back(
name, value);
61 if ((pos =
name.rfind(
'.')) != std::string::npos &&
prefix.length() <= pos) {
62 sections.emplace_back(
SectionInfo{
name.substr(0, pos), filepath, linenr});
65 error =
strprintf(
"parse error on line %i: %s", linenr, str);
66 if (str.size() >= 2 && str.starts_with(
"no")) {
67 error +=
strprintf(
", if you intended to specify a negated option, use %s=1 instead", str);
78 if (key.
name ==
"conf") {
79 error =
"conf cannot be set in the configuration file; use includeconf= if you want to include additional config files";
82 if (key.
name ==
"reindex") {
85 LogWarning(
"reindex=1 is set in the configuration file, which will significantly slow down startup. Consider removing or commenting out this option for better performance, unless there is currently a condition which makes rebuilding the indexes necessary");
94 std::vector<std::pair<std::string, std::string>> options;
95 if (!
GetConfigOptions(stream, filepath, error, options, m_config_sections)) {
98 for (
const std::pair<std::string, std::string>& option : options) {
103 std::optional<common::SettingsValue> value =
InterpretValue(key, &option.second, *
flags, error);
107 m_settings.ro_config[key.
section][key.
name].push_back(*value);
109 if (ignore_invalid_keys) {
110 LogWarning(
"Ignoring unknown configuration value %s", option.first);
112 error =
strprintf(
"Invalid configuration value %s", option.first);
122 std::istringstream streamConfig(str_config);
125 m_settings.ro_config.clear();
126 m_config_sections.clear();
136 m_settings.ro_config.clear();
137 m_config_sections.clear();
143 std::ifstream stream;
144 if (!conf_path.empty()) {
145 if (fs::is_directory(conf_path)) {
149 stream = std::ifstream{conf_path.std_path()};
151 if (
IsArgSet(
"-conf") && !stream.good()) {
163 bool use_conf_file{
true};
166 if (
auto* includes =
common::FindKey(m_settings.command_line_options,
"includeconf")) {
169 use_conf_file =
false;
174 std::vector<std::string> conf_file_names;
176 auto add_includes = [&](
const std::string& network,
size_t skip = 0) {
177 size_t num_values = 0;
182 conf_file_names.push_back((*
values)[i].get_str());
184 num_values =
values->size();
192 const size_t chain_includes = add_includes(chain_id);
193 const size_t default_includes = add_includes({});
195 for (
const std::string& conf_file_name : conf_file_names) {
196 const auto include_conf_path{
AbsPathForConfigVal(*
this, fs::PathFromString(conf_file_name),
false)};
197 if (fs::is_directory(include_conf_path)) {
198 error =
strprintf(
"Included config file \"%s\" is a directory.", fs::PathToString(include_conf_path));
201 std::ifstream conf_file_stream{include_conf_path.std_path()};
202 if (conf_file_stream.good()) {
203 if (!
ReadConfigStream(conf_file_stream, conf_file_name, error, ignore_invalid_keys)) {
206 LogInfo(
"Included configuration file %s\n", conf_file_name);
208 error =
"Failed to include configuration file " + conf_file_name;
214 conf_file_names.clear();
215 add_includes(chain_id, chain_includes);
216 add_includes({}, default_includes);
218 if (chain_id_final != chain_id) {
220 add_includes(chain_id_final);
222 for (
const std::string& conf_file_name : conf_file_names) {
223 tfm::format(std::cerr,
"warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", conf_file_name);
231 error =
strprintf(
"specified data directory \"%s\" does not exist.",
GetArg(
"-datadir",
""));
239 if (path.is_absolute() || path.empty()) {
std::optional< common::SettingsValue > InterpretValue(const KeyInfo &key, const std::string *value, unsigned int flags, std::string &error)
Interpret settings value based on registered flags.
bool CheckDataDirOption(const ArgsManager &args)
KeyInfo InterpretKey(std::string key)
Parse "name", "section.name", "noname", "section.noname" settings keys.
const char *const BITCOIN_CONF_FILENAME
bool ReadConfigString(const std::string &str_config) EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
fs::path GetDataDirBase() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Get data directory path.
fs::path GetConfigFilePath() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Return config file path (read-only)
fs::path GetPathArg_(std::string arg, const fs::path &default_value={}) const EXCLUSIVE_LOCKS_REQUIRED(cs_args)
bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false) EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
void ClearPathCache() EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Clear cached directory paths.
fs::path GetDataDir(bool net_specific) const EXCLUSIVE_LOCKS_REQUIRED(cs_args)
Get data directory path.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Return string argument or default value.
std::string GetChainTypeString() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Returns the appropriate chain type string from the program arguments.
bool IsArgSet(const std::string &strArg) const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Return true if the given argument has been manually set.
fs::path GetDataDirNet() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Get data directory path with appended network identifier.
bool ReadConfigStream(std::istream &stream, const std::string &filepath, std::string &error, bool ignore_invalid_keys=false) EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
std::optional< unsigned int > GetArgFlags_(const std::string &name) const EXCLUSIVE_LOCKS_REQUIRED(cs_args)
static bool GetConfigOptions(std::istream &stream, const std::string &filepath, std::string &error, std::vector< std::pair< std::string, std::string > > &options, std::list< SectionInfo > §ions)
bool IsConfSupported(KeyInfo &key, std::string &error)
fs::path AbsPathForConfigVal(const ArgsManager &args, const fs::path &path, bool net_specific)
Most paths passed as configuration arguments are treated as relative to the datadir if they are not a...
static std::string PathToString(const path &path)
Convert path object to a byte string.
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
std::string_view TrimStringView(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
std::string TrimString(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
Accessor for list of settings that skips negated values when iterated over.
bool last_negated() const
True if the last value is negated.
size_t negated() const
Number of negated values.