aboutsummaryrefslogtreecommitdiff
path: root/src/util/system.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/system.cpp')
-rw-r--r--src/util/system.cpp131
1 files changed, 96 insertions, 35 deletions
diff --git a/src/util/system.cpp b/src/util/system.cpp
index bfb1a79b40..1953a9f836 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -25,6 +25,7 @@
#include <util/getuniquepath.h>
#include <util/strencodings.h>
#include <util/string.h>
+#include <util/syserror.h>
#include <util/translation.h>
@@ -54,16 +55,6 @@
#else
-#ifdef _MSC_VER
-#pragma warning(disable:4786)
-#pragma warning(disable:4804)
-#pragma warning(disable:4805)
-#pragma warning(disable:4717)
-#endif
-
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
#include <codecvt>
#include <io.h> /* for _commit */
@@ -75,7 +66,6 @@
#include <malloc.h>
#endif
-#include <boost/algorithm/string/replace.hpp>
#include <univalue.h>
#include <fstream>
@@ -96,7 +86,7 @@ const char * const BITCOIN_SETTINGS_FILENAME = "settings.json";
ArgsManager gArgs;
/** Mutex to protect dir_locks. */
-static Mutex cs_dir_locks;
+static GlobalMutex cs_dir_locks;
/** A map that contains all the currently held directory locks. After
* successful locking, these will be held here until the global destructor
* cleans them up and thus automatically unlocks them, or ReleaseDirectoryLocks
@@ -104,7 +94,7 @@ static Mutex cs_dir_locks;
*/
static std::map<std::string, std::unique_ptr<fsbridge::FileLock>> dir_locks GUARDED_BY(cs_dir_locks);
-bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only)
+bool LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only)
{
LOCK(cs_dir_locks);
fs::path pathLockFile = directory / lockfile_name;
@@ -128,7 +118,7 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b
return true;
}
-void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name)
+void UnlockDirectory(const fs::path& directory, const fs::path& lockfile_name)
{
LOCK(cs_dir_locks);
dir_locks.erase(fs::PathToString(directory / lockfile_name));
@@ -236,7 +226,7 @@ KeyInfo InterpretKey(std::string key)
* @return parsed settings value if it is valid, otherwise nullopt accompanied
* by a descriptive error string
*/
-static std::optional<util::SettingsValue> InterpretValue(const KeyInfo& key, const std::string& value,
+static std::optional<util::SettingsValue> InterpretValue(const KeyInfo& key, const std::string* value,
unsigned int flags, std::string& error)
{
// Return negated settings as false values.
@@ -246,20 +236,24 @@ static std::optional<util::SettingsValue> InterpretValue(const KeyInfo& key, con
return std::nullopt;
}
// Double negatives like -nofoo=0 are supported (but discouraged)
- if (!InterpretBool(value)) {
- LogPrintf("Warning: parsed potentially confusing double-negative -%s=%s\n", key.name, value);
+ if (value && !InterpretBool(*value)) {
+ LogPrintf("Warning: parsed potentially confusing double-negative -%s=%s\n", key.name, *value);
return true;
}
return false;
}
- return value;
+ if (!value && (flags & ArgsManager::DISALLOW_ELISION)) {
+ error = strprintf("Can not set -%s with no value. Please specify value with -%s=value.", key.name, key.name);
+ return std::nullopt;
+ }
+ return value ? *value : "";
}
// Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to
// #include class definitions for all members.
// For example, m_settings has an internal dependency on univalue.
-ArgsManager::ArgsManager() {}
-ArgsManager::~ArgsManager() {}
+ArgsManager::ArgsManager() = default;
+ArgsManager::~ArgsManager() = default;
const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
{
@@ -320,7 +314,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
#endif
if (key == "-") break; //bitcoin-tx using stdin
- std::string val;
+ std::optional<std::string> val;
size_t is_index = key.find('=');
if (is_index != std::string::npos) {
val = key.substr(is_index + 1);
@@ -366,7 +360,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
return false;
}
- std::optional<util::SettingsValue> value = InterpretValue(keyinfo, val, *flags, error);
+ std::optional<util::SettingsValue> value = InterpretValue(keyinfo, val ? &*val : nullptr, *flags, error);
if (!value) return false;
m_settings.command_line_options[keyinfo.name].push_back(*value);
@@ -526,12 +520,15 @@ bool ArgsManager::InitSettings(std::string& error)
return true;
}
-bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp) const
+bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp, bool backup) const
{
fs::path settings = GetPathArg("-settings", BITCOIN_SETTINGS_FILENAME);
if (settings.empty()) {
return false;
}
+ if (backup) {
+ settings += ".bak";
+ }
if (filepath) {
*filepath = fsbridge::AbsPathJoin(GetDataDirNet(), temp ? settings + ".tmp" : settings);
}
@@ -572,10 +569,10 @@ bool ArgsManager::ReadSettingsFile(std::vector<std::string>* errors)
return true;
}
-bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors) const
+bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors, bool backup) const
{
fs::path path, path_tmp;
- if (!GetSettingsPath(&path, /* temp= */ false) || !GetSettingsPath(&path_tmp, /* temp= */ true)) {
+ if (!GetSettingsPath(&path, /*temp=*/false, backup) || !GetSettingsPath(&path_tmp, /*temp=*/true, backup)) {
throw std::logic_error("Attempt to write settings file when dynamic settings are disabled.");
}
@@ -592,6 +589,13 @@ bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors) const
return true;
}
+util::SettingsValue ArgsManager::GetPersistentSetting(const std::string& name) const
+{
+ LOCK(cs_args);
+ return util::GetSetting(m_settings, m_network, name, !UseDefaultSection("-" + name),
+ /*ignore_nonpersistent=*/true, /*get_chain_name=*/false);
+}
+
bool ArgsManager::IsArgNegated(const std::string& strArg) const
{
return GetSetting(strArg).isFalse();
@@ -599,20 +603,75 @@ bool ArgsManager::IsArgNegated(const std::string& strArg) const
std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault) const
{
+ return GetArg(strArg).value_or(strDefault);
+}
+
+std::optional<std::string> ArgsManager::GetArg(const std::string& strArg) const
+{
const util::SettingsValue value = GetSetting(strArg);
- return value.isNull() ? strDefault : value.isFalse() ? "0" : value.isTrue() ? "1" : value.isNum() ? value.getValStr() : value.get_str();
+ return SettingToString(value);
+}
+
+std::optional<std::string> SettingToString(const util::SettingsValue& value)
+{
+ if (value.isNull()) return std::nullopt;
+ if (value.isFalse()) return "0";
+ if (value.isTrue()) return "1";
+ if (value.isNum()) return value.getValStr();
+ return value.get_str();
+}
+
+std::string SettingToString(const util::SettingsValue& value, const std::string& strDefault)
+{
+ return SettingToString(value).value_or(strDefault);
}
int64_t ArgsManager::GetIntArg(const std::string& strArg, int64_t nDefault) const
{
+ return GetIntArg(strArg).value_or(nDefault);
+}
+
+std::optional<int64_t> ArgsManager::GetIntArg(const std::string& strArg) const
+{
const util::SettingsValue value = GetSetting(strArg);
- return value.isNull() ? nDefault : value.isFalse() ? 0 : value.isTrue() ? 1 : value.isNum() ? value.get_int64() : LocaleIndependentAtoi<int64_t>(value.get_str());
+ return SettingToInt(value);
+}
+
+std::optional<int64_t> SettingToInt(const util::SettingsValue& value)
+{
+ if (value.isNull()) return std::nullopt;
+ if (value.isFalse()) return 0;
+ if (value.isTrue()) return 1;
+ if (value.isNum()) return value.getInt<int64_t>();
+ return LocaleIndependentAtoi<int64_t>(value.get_str());
+}
+
+int64_t SettingToInt(const util::SettingsValue& value, int64_t nDefault)
+{
+ return SettingToInt(value).value_or(nDefault);
}
bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault) const
{
+ return GetBoolArg(strArg).value_or(fDefault);
+}
+
+std::optional<bool> ArgsManager::GetBoolArg(const std::string& strArg) const
+{
const util::SettingsValue value = GetSetting(strArg);
- return value.isNull() ? fDefault : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
+ return SettingToBool(value);
+}
+
+std::optional<bool> SettingToBool(const util::SettingsValue& value)
+{
+ if (value.isNull()) return std::nullopt;
+ if (value.isBool()) return value.get_bool();
+ return InterpretBool(value.get_str());
+}
+
+bool SettingToBool(const util::SettingsValue& value, bool fDefault)
+{
+ return SettingToBool(value).value_or(fDefault);
}
bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strValue)
@@ -681,7 +740,7 @@ std::string ArgsManager::GetHelpMessage() const
{
const bool show_debug = GetBoolArg("-help-debug", false);
- std::string usage = "";
+ std::string usage;
LOCK(cs_args);
for (const auto& arg_map : m_available_args) {
switch(arg_map.first) {
@@ -853,8 +912,8 @@ static bool GetConfigOptions(std::istream& stream, const std::string& filepath,
error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str);
return false;
} else if ((pos = str.find('=')) != std::string::npos) {
- std::string name = prefix + TrimString(str.substr(0, pos), pattern);
- std::string value = TrimString(str.substr(pos + 1), pattern);
+ std::string name = prefix + TrimString(std::string_view{str}.substr(0, pos), pattern);
+ std::string_view value = TrimStringView(std::string_view{str}.substr(pos + 1), pattern);
if (used_hash && name.find("rpcpassword") != std::string::npos) {
error = strprintf("parse error on line %i, using # in rpcpassword can be ambiguous and should be avoided", linenr);
return false;
@@ -887,7 +946,7 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& file
KeyInfo key = InterpretKey(option.first);
std::optional<unsigned int> flags = GetArgFlags('-' + key.name);
if (flags) {
- std::optional<util::SettingsValue> value = InterpretValue(key, option.second, *flags, error);
+ std::optional<util::SettingsValue> value = InterpretValue(key, &option.second, *flags, error);
if (!value) {
return false;
}
@@ -1002,6 +1061,7 @@ std::string ArgsManager::GetChainName() const
LOCK(cs_args);
util::SettingsValue value = util::GetSetting(m_settings, /* section= */ "", SettingName(arg),
/* ignore_default_section_config= */ false,
+ /*ignore_nonpersistent=*/false,
/* get_chain_name= */ true);
return value.isNull() ? false : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
};
@@ -1034,7 +1094,8 @@ util::SettingsValue ArgsManager::GetSetting(const std::string& arg) const
{
LOCK(cs_args);
return util::GetSetting(
- m_settings, m_network, SettingName(arg), !UseDefaultSection(arg), /* get_chain_name= */ false);
+ m_settings, m_network, SettingName(arg), !UseDefaultSection(arg),
+ /*ignore_nonpersistent=*/false, /*get_chain_name=*/false);
}
std::vector<util::SettingsValue> ArgsManager::GetSettingsList(const std::string& arg) const
@@ -1252,7 +1313,7 @@ fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
std::string ShellEscape(const std::string& arg)
{
std::string escaped = arg;
- boost::replace_all(escaped, "'", "'\"'\"'");
+ ReplaceAll(escaped, "'", "'\"'\"'");
return "'" + escaped + "'";
}
#endif
@@ -1374,7 +1435,7 @@ void ScheduleBatchPriority()
const static sched_param param{};
const int rc = pthread_setschedparam(pthread_self(), SCHED_BATCH, &param);
if (rc != 0) {
- LogPrintf("Failed to pthread_setschedparam: %s\n", strerror(rc));
+ LogPrintf("Failed to pthread_setschedparam: %s\n", SysErrorString(rc));
}
#endif
}