| 133 | } |
| 134 | |
| 135 | bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) |
| 136 | { |
| 137 | { |
| 138 | LOCK(cs_args); |
| 139 | m_settings.ro_config.clear(); |
| 140 | m_config_sections.clear(); |
| 141 | const auto conf_val = GetPathArg_("-conf", BITCOIN_CONF_FILENAME); |
| 142 | m_config_path = (conf_val.is_absolute() || conf_val.empty()) ? conf_val : fsbridge::AbsPathJoin(GetDataDir(/*net_specific=*/false), conf_val); |
| 143 | } |
| 144 | |
| 145 | const auto conf_path{GetConfigFilePath()}; |
| 146 | std::ifstream stream; |
| 147 | if (!conf_path.empty()) { // path is empty when -noconf is specified |
| 148 | if (fs::is_directory(conf_path)) { |
| 149 | error = strprintf("Config file \"%s\" is a directory.", fs::PathToString(conf_path)); |
| 150 | return false; |
| 151 | } |
| 152 | stream = std::ifstream{conf_path.std_path()}; |
| 153 | // If the file is explicitly specified, it must be readable |
| 154 | if (IsArgSet("-conf") && !stream.good()) { |
| 155 | error = strprintf("specified config file \"%s\" could not be opened.", fs::PathToString(conf_path)); |
| 156 | return false; |
| 157 | } |
| 158 | } |
| 159 | // ok to not have a config file |
| 160 | if (stream.good()) { |
| 161 | if (!ReadConfigStream(stream, fs::PathToString(conf_path), error, ignore_invalid_keys)) { |
| 162 | return false; |
| 163 | } |
| 164 | // `-includeconf` cannot be included in the command line arguments except |
| 165 | // as `-noincludeconf` (which indicates that no included conf file should be used). |
| 166 | bool use_conf_file{true}; |
| 167 | { |
| 168 | LOCK(cs_args); |
| 169 | if (auto* includes = common::FindKey(m_settings.command_line_options, "includeconf")) { |
| 170 | // ParseParameters() fails if a non-negated -includeconf is passed on the command-line |
| 171 | assert(common::SettingsSpan(*includes).last_negated()); |
| 172 | use_conf_file = false; |
| 173 | } |
| 174 | } |
| 175 | if (use_conf_file) { |
| 176 | std::string chain_id = GetChainTypeString(); |
| 177 | std::vector<std::string> conf_file_names; |
| 178 | |
| 179 | auto add_includes = [&](const std::string& network, size_t skip = 0) { |
| 180 | size_t num_values = 0; |
| 181 | LOCK(cs_args); |
| 182 | if (auto* section = common::FindKey(m_settings.ro_config, network)) { |
| 183 | if (auto* values = common::FindKey(*section, "includeconf")) { |
| 184 | for (size_t i = std::max(skip, common::SettingsSpan(*values).negated()); i < values->size(); ++i) { |
| 185 | conf_file_names.push_back((*values)[i].get_str()); |
| 186 | } |
| 187 | num_values = values->size(); |
| 188 | } |
| 189 | } |
| 190 | return num_values; |
| 191 | }; |
| 192 | |