|
73 | 73 | const int64_t nStartupTime = GetTime(); |
74 | 74 |
|
75 | 75 | const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf"; |
| 76 | +const char * const BITCOIN_SETTINGS_FILENAME = "settings.json"; |
76 | 77 |
|
77 | 78 | ArgsManager gArgs; |
78 | 79 |
|
@@ -372,6 +373,84 @@ bool ArgsManager::IsArgSet(const std::string& strArg) const |
372 | 373 | return !GetSetting(strArg).isNull(); |
373 | 374 | } |
374 | 375 |
|
| 376 | +bool ArgsManager::InitSettings(std::string& error) |
| 377 | +{ |
| 378 | + if (!GetSettingsPath()) { |
| 379 | + return true; // Do nothing if settings file disabled. |
| 380 | + } |
| 381 | + |
| 382 | + std::vector<std::string> errors; |
| 383 | + if (!ReadSettingsFile(&errors)) { |
| 384 | + error = strprintf("Failed loading settings file:\n- %s\n", Join(errors, "\n- ")); |
| 385 | + return false; |
| 386 | + } |
| 387 | + if (!WriteSettingsFile(&errors)) { |
| 388 | + error = strprintf("Failed saving settings file:\n- %s\n", Join(errors, "\n- ")); |
| 389 | + return false; |
| 390 | + } |
| 391 | + return true; |
| 392 | +} |
| 393 | + |
| 394 | +bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp) const |
| 395 | +{ |
| 396 | + if (IsArgNegated("-settings")) { |
| 397 | + return false; |
| 398 | + } |
| 399 | + if (filepath) { |
| 400 | + std::string settings = GetArg("-settings", BITCOIN_SETTINGS_FILENAME); |
| 401 | + *filepath = fs::absolute(temp ? settings + ".tmp" : settings, GetDataDir(/* net_specific= */ true)); |
| 402 | + } |
| 403 | + return true; |
| 404 | +} |
| 405 | + |
| 406 | +static void SaveErrors(const std::vector<std::string> errors, std::vector<std::string>* error_out) |
| 407 | +{ |
| 408 | + for (const auto& error : errors) { |
| 409 | + if (error_out) { |
| 410 | + error_out->emplace_back(error); |
| 411 | + } else { |
| 412 | + LogPrintf("%s\n", error); |
| 413 | + } |
| 414 | + } |
| 415 | +} |
| 416 | + |
| 417 | +bool ArgsManager::ReadSettingsFile(std::vector<std::string>* errors) |
| 418 | +{ |
| 419 | + fs::path path; |
| 420 | + if (!GetSettingsPath(&path, /* temp= */ false)) { |
| 421 | + return true; // Do nothing if settings file disabled. |
| 422 | + } |
| 423 | + |
| 424 | + LOCK(cs_args); |
| 425 | + m_settings.rw_settings.clear(); |
| 426 | + std::vector<std::string> read_errors; |
| 427 | + if (!util::ReadSettings(path, m_settings.rw_settings, read_errors)) { |
| 428 | + SaveErrors(read_errors, errors); |
| 429 | + return false; |
| 430 | + } |
| 431 | + return true; |
| 432 | +} |
| 433 | + |
| 434 | +bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors) const |
| 435 | +{ |
| 436 | + fs::path path, path_tmp; |
| 437 | + if (!GetSettingsPath(&path, /* temp= */ false) || !GetSettingsPath(&path_tmp, /* temp= */ true)) { |
| 438 | + throw std::logic_error("Attempt to write settings file when dynamic settings are disabled."); |
| 439 | + } |
| 440 | + |
| 441 | + LOCK(cs_args); |
| 442 | + std::vector<std::string> write_errors; |
| 443 | + if (!util::WriteSettings(path_tmp, m_settings.rw_settings, write_errors)) { |
| 444 | + SaveErrors(write_errors, errors); |
| 445 | + return false; |
| 446 | + } |
| 447 | + if (!RenameOver(path_tmp, path)) { |
| 448 | + SaveErrors({strprintf("Failed renaming settings file %s to %s\n", path_tmp.string(), path.string())}, errors); |
| 449 | + return false; |
| 450 | + } |
| 451 | + return true; |
| 452 | +} |
| 453 | + |
375 | 454 | bool ArgsManager::IsArgNegated(const std::string& strArg) const |
376 | 455 | { |
377 | 456 | return GetSetting(strArg).isFalse(); |
@@ -893,6 +972,9 @@ void ArgsManager::LogArgs() const |
893 | 972 | for (const auto& section : m_settings.ro_config) { |
894 | 973 | logArgsPrefix("Config file arg:", section.first, section.second); |
895 | 974 | } |
| 975 | + for (const auto& setting : m_settings.rw_settings) { |
| 976 | + LogPrintf("Setting file arg: %s = %s\n", setting.first, setting.second.write()); |
| 977 | + } |
896 | 978 | logArgsPrefix("Command-line arg:", "", m_settings.command_line_options); |
897 | 979 | } |
898 | 980 |
|
|
0 commit comments