aboutsummaryrefslogtreecommitdiff
path: root/src/util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.cpp')
-rw-r--r--src/util.cpp86
1 files changed, 56 insertions, 30 deletions
diff --git a/src/util.cpp b/src/util.cpp
index 95bc427bb2..fa624aee90 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -58,6 +58,7 @@
#ifndef NOMINMAX
#define NOMINMAX
#endif
+#include <codecvt>
#include <io.h> /* for _commit */
#include <shlobj.h>
@@ -71,7 +72,6 @@
#include <malloc.h>
#endif
-#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/thread.hpp>
#include <openssl/crypto.h>
#include <openssl/rand.h>
@@ -86,8 +86,6 @@ const char * const BITCOIN_PID_FILENAME = "bitcoind.pid";
ArgsManager gArgs;
-CTranslationInterface translationInterface;
-
/** Init OpenSSL library multithreading support */
static std::unique_ptr<CCriticalSection[]> ppmutexOpenSSL;
void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
@@ -141,7 +139,7 @@ instance_of_cinit;
* cleans them up and thus automatically unlocks them, or ReleaseDirectoryLocks
* is called.
*/
-static std::map<std::string, std::unique_ptr<boost::interprocess::file_lock>> dir_locks;
+static std::map<std::string, std::unique_ptr<fsbridge::FileLock>> dir_locks;
/** Mutex to protect dir_locks. */
static std::mutex cs_dir_locks;
@@ -158,18 +156,13 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b
// Create empty lock file if it doesn't exist.
FILE* file = fsbridge::fopen(pathLockFile, "a");
if (file) fclose(file);
-
- try {
- auto lock = MakeUnique<boost::interprocess::file_lock>(pathLockFile.string().c_str());
- if (!lock->try_lock()) {
- return false;
- }
- if (!probe_only) {
- // Lock successful and we're not just probing, put it into the map
- dir_locks.emplace(pathLockFile.string(), std::move(lock));
- }
- } catch (const boost::interprocess::interprocess_exception& e) {
- return error("Error while attempting to lock directory %s: %s", directory.string(), e.what());
+ auto lock = MakeUnique<fsbridge::FileLock>(pathLockFile);
+ if (!lock->TryLock()) {
+ return error("Error while attempting to lock directory %s: %s", directory.string(), lock->GetReason());
+ }
+ if (!probe_only) {
+ // Lock successful and we're not just probing, put it into the map
+ dir_locks.emplace(pathLockFile.string(), std::move(lock));
}
return true;
}
@@ -224,7 +217,7 @@ public:
/** Determine whether to use config settings in the default section,
* See also comments around ArgsManager::ArgsManager() below. */
- static inline bool UseDefaultSection(const ArgsManager& am, const std::string& arg)
+ static inline bool UseDefaultSection(const ArgsManager& am, const std::string& arg) EXCLUSIVE_LOCKS_REQUIRED(am.cs_args)
{
return (am.m_network == CBaseChainParams::MAIN || am.m_network_only_args.count(arg) == 0);
}
@@ -303,7 +296,7 @@ public:
/* Special test for -testnet and -regtest args, because we
* don't want to be confused by craziness like "[regtest] testnet=1"
*/
- static inline bool GetNetBoolArg(const ArgsManager &am, const std::string& net_arg)
+ static inline bool GetNetBoolArg(const ArgsManager &am, const std::string& net_arg) EXCLUSIVE_LOCKS_REQUIRED(am.cs_args)
{
std::pair<bool,std::string> found_result(false,std::string());
found_result = GetArgHelper(am.m_override_args, net_arg, true);
@@ -380,6 +373,8 @@ ArgsManager::ArgsManager() :
void ArgsManager::WarnForSectionOnlyArgs()
{
+ LOCK(cs_args);
+
// if there's no section selected, don't worry
if (m_network.empty()) return;
@@ -408,6 +403,7 @@ void ArgsManager::WarnForSectionOnlyArgs()
void ArgsManager::SelectConfigNetwork(const std::string& network)
{
+ LOCK(cs_args);
m_network = network;
}
@@ -476,6 +472,7 @@ bool ArgsManager::IsArgKnown(const std::string& key) const
arg_no_net = std::string("-") + key.substr(option_index + 1, std::string::npos);
}
+ LOCK(cs_args);
for (const auto& arg_map : m_available_args) {
if (arg_map.second.count(arg_no_net)) return true;
}
@@ -579,6 +576,7 @@ void ArgsManager::AddArg(const std::string& name, const std::string& help, const
eq_index = name.size();
}
+ LOCK(cs_args);
std::map<std::string, Arg>& arg_map = m_available_args[cat];
auto ret = arg_map.emplace(name.substr(0, eq_index), Arg(name.substr(eq_index, name.size() - eq_index), help, debug_only));
assert(ret.second); // Make sure an insertion actually happened
@@ -596,6 +594,7 @@ std::string ArgsManager::GetHelpMessage() const
const bool show_debug = gArgs.GetBoolArg("-help-debug", false);
std::string usage = "";
+ LOCK(cs_args);
for (const auto& arg_map : m_available_args) {
switch(arg_map.first) {
case OptionsCategory::OPTIONS:
@@ -661,7 +660,7 @@ std::string ArgsManager::GetHelpMessage() const
bool HelpRequested(const ArgsManager& args)
{
- return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help");
+ return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help") || args.IsArgSet("-help-debug");
}
static const int screenWidth = 79;
@@ -820,11 +819,11 @@ static std::string TrimString(const std::string& str, const std::string& pattern
return str.substr(front, end - front + 1);
}
-static std::vector<std::pair<std::string, std::string>> GetConfigOptions(std::istream& stream)
+static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector<std::pair<std::string, std::string>> &options)
{
- std::vector<std::pair<std::string, std::string>> options;
std::string str, prefix;
std::string::size_type pos;
+ int linenr = 1;
while (std::getline(stream, str)) {
if ((pos = str.find('#')) != std::string::npos) {
str = str.substr(0, pos);
@@ -834,21 +833,34 @@ static std::vector<std::pair<std::string, std::string>> GetConfigOptions(std::is
if (!str.empty()) {
if (*str.begin() == '[' && *str.rbegin() == ']') {
prefix = str.substr(1, str.size() - 2) + '.';
+ } else if (*str.begin() == '-') {
+ 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);
options.emplace_back(name, value);
+ } else {
+ error = strprintf("parse error on line %i: %s", linenr, str);
+ if (str.size() >= 2 && str.substr(0, 2) == "no") {
+ error += strprintf(", if you intended to specify a negated option, use %s=1 instead", str);
+ }
+ return false;
}
}
+ ++linenr;
}
- return options;
+ return true;
}
bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys)
{
LOCK(cs_args);
-
- for (const std::pair<std::string, std::string>& option : GetConfigOptions(stream)) {
+ std::vector<std::pair<std::string, std::string>> options;
+ if (!GetConfigOptions(stream, error, options)) {
+ return false;
+ }
+ for (const std::pair<std::string, std::string>& option : options) {
std::string strKey = std::string("-") + option.first;
std::string strValue = option.second;
@@ -888,7 +900,12 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
}
// if there is an -includeconf in the override args, but it is empty, that means the user
// passed '-noincludeconf' on the command line, in which case we should not include anything
- if (m_override_args.count("-includeconf") == 0) {
+ bool emptyIncludeConf;
+ {
+ LOCK(cs_args);
+ emptyIncludeConf = m_override_args.count("-includeconf") == 0;
+ }
+ if (emptyIncludeConf) {
std::string chain_id = GetChainName();
std::vector<std::string> includeconf(GetArgs("-includeconf"));
{
@@ -948,6 +965,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
std::string ArgsManager::GetChainName() const
{
+ LOCK(cs_args);
bool fRegTest = ArgsManagerHelper::GetNetBoolArg(*this, "-regtest");
bool fTestNet = ArgsManagerHelper::GetNetBoolArg(*this, "-testnet");
@@ -980,7 +998,7 @@ void CreatePidFile(const fs::path &path, pid_t pid)
bool RenameOver(fs::path src, fs::path dest)
{
#ifdef WIN32
- return MoveFileExA(src.string().c_str(), dest.string().c_str(),
+ return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
MOVEFILE_REPLACE_EXISTING) != 0;
#else
int rc = std::rename(src.string().c_str(), dest.string().c_str());
@@ -1122,14 +1140,14 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
#ifdef WIN32
fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
{
- char pszPath[MAX_PATH] = "";
+ WCHAR pszPath[MAX_PATH] = L"";
- if(SHGetSpecialFolderPathA(nullptr, pszPath, nFolder, fCreate))
+ if(SHGetSpecialFolderPathW(nullptr, pszPath, nFolder, fCreate))
{
return fs::path(pszPath);
}
- LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
+ LogPrintf("SHGetSpecialFolderPathW() failed, could not obtain requested path.\n");
return fs::path("");
}
#endif
@@ -1137,7 +1155,11 @@ fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
void runCommand(const std::string& strCommand)
{
if (strCommand.empty()) return;
+#ifndef WIN32
int nErr = ::system(strCommand.c_str());
+#else
+ int nErr = ::_wsystem(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().from_bytes(strCommand).c_str());
+#endif
if (nErr)
LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
}
@@ -1184,7 +1206,11 @@ void SetupEnvironment()
// A dummy locale is used to extract the internal default locale, used by
// fs::path, which is then used to explicitly imbue the path.
std::locale loc = fs::path::imbue(std::locale::classic());
+#ifndef WIN32
fs::path::imbue(loc);
+#else
+ fs::path::imbue(std::locale(loc, new std::codecvt_utf8_utf16<wchar_t>()));
+#endif
}
bool SetupNetworking()
@@ -1226,7 +1252,7 @@ fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific)
return fs::absolute(path, GetDataDir(net_specific));
}
-int ScheduleBatchPriority(void)
+int ScheduleBatchPriority()
{
#ifdef SCHED_BATCH
const static sched_param param{0};