diff options
-rw-r--r-- | src/qt/bitcoin.cpp | 1 | ||||
-rw-r--r-- | src/util/system.cpp | 41 | ||||
-rw-r--r-- | src/util/system.h | 12 |
3 files changed, 42 insertions, 12 deletions
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 59f433749d..c383c8bd58 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -167,6 +167,7 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans static bool InitSettings() { + gArgs.EnsureDataDir(); if (!gArgs.GetSettingsPath()) { return true; // Do nothing if settings file disabled. } diff --git a/src/util/system.cpp b/src/util/system.cpp index e72c970157..77b659df7e 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -417,8 +417,7 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const LOCK(cs_args); fs::path& path = net_specific ? m_cached_network_datadir_path : m_cached_datadir_path; - // Cache the path to avoid calling fs::create_directories on every call of - // this function + // Used cached path if available if (!path.empty()) return path; const fs::path datadir{GetPathArg("-datadir")}; @@ -432,20 +431,34 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const path = GetDefaultDataDir(); } - if (!fs::exists(path)) { - fs::create_directories(path / "wallets"); - } - if (net_specific && !BaseParams().DataDir().empty()) { path /= fs::PathFromString(BaseParams().DataDir()); - if (!fs::exists(path)) { - fs::create_directories(path / "wallets"); - } } return path; } +void ArgsManager::EnsureDataDir() const +{ + /** + * "/wallets" subdirectories are created in all **new** + * datadirs, because wallet code will create new wallets in the "wallets" + * subdirectory only if exists already, otherwise it will create them in + * the top-level datadir where they could interfere with other files. + * Wallet init code currently avoids creating "wallets" directories itself + * for backwards compatibility, but this be changed in the future and + * wallet code here could go away (#16220). + */ + auto path{GetDataDir(false)}; + if (!fs::exists(path)) { + fs::create_directories(path / "wallets"); + } + path = GetDataDir(true); + if (!fs::exists(path)) { + fs::create_directories(path / "wallets"); + } +} + void ArgsManager::ClearPathCache() { LOCK(cs_args); @@ -491,6 +504,7 @@ bool ArgsManager::IsArgSet(const std::string& strArg) const bool ArgsManager::InitSettings(std::string& error) { + EnsureDataDir(); if (!GetSettingsPath()) { return true; // Do nothing if settings file disabled. } @@ -965,6 +979,11 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& file return true; } +fs::path ArgsManager::GetConfigFilePath() const +{ + return GetConfigFile(GetPathArg("-conf", BITCOIN_CONF_FILENAME)); +} + bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) { { @@ -973,8 +992,8 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) m_config_sections.clear(); } - const fs::path conf_path = GetPathArg("-conf", BITCOIN_CONF_FILENAME); - std::ifstream stream{GetConfigFile(conf_path)}; + const auto conf_path{GetConfigFilePath()}; + std::ifstream stream{conf_path}; // not ok to have a config file specified that cannot be opened if (IsArgSet("-conf") && !stream.good()) { diff --git a/src/util/system.h b/src/util/system.h index c053adf8c3..14f093501a 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -242,6 +242,11 @@ protected: void SelectConfigNetwork(const std::string& network); [[nodiscard]] bool ParseParameters(int argc, const char* const argv[], std::string& error); + + /** + * Return config file path (read-only) + */ + fs::path GetConfigFilePath() const; [[nodiscard]] bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false); /** @@ -475,13 +480,18 @@ protected: */ void LogArgs() const; + /** + * If datadir does not exist, create it along with wallets/ + * subdirectory(s). + */ + void EnsureDataDir() const; + private: /** * Get data directory path * * @param net_specific Append network identifier to the returned path * @return Absolute path on success, otherwise an empty path when a non-directory path would be returned - * @post Returned directory path is created unless it is empty */ const fs::path& GetDataDir(bool net_specific) const; |