Bitcoin Core  0.18.99
P2P Digital Currency
system.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2019 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <util/system.h>
7 
8 #include <chainparamsbase.h>
9 #include <util/strencodings.h>
10 #include <util/translation.h>
11 
12 #include <stdarg.h>
13 
14 #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
15 #include <pthread.h>
16 #include <pthread_np.h>
17 #endif
18 
19 #ifndef WIN32
20 // for posix_fallocate
21 #ifdef __linux__
22 
23 #ifdef _POSIX_C_SOURCE
24 #undef _POSIX_C_SOURCE
25 #endif
26 
27 #define _POSIX_C_SOURCE 200112L
28 
29 #endif // __linux__
30 
31 #include <algorithm>
32 #include <fcntl.h>
33 #include <sched.h>
34 #include <sys/resource.h>
35 #include <sys/stat.h>
36 
37 #else
38 
39 #ifdef _MSC_VER
40 #pragma warning(disable:4786)
41 #pragma warning(disable:4804)
42 #pragma warning(disable:4805)
43 #pragma warning(disable:4717)
44 #endif
45 
46 #ifdef _WIN32_IE
47 #undef _WIN32_IE
48 #endif
49 #define _WIN32_IE 0x0501
50 
51 #define WIN32_LEAN_AND_MEAN 1
52 #ifndef NOMINMAX
53 #define NOMINMAX
54 #endif
55 #include <codecvt>
56 
57 #include <io.h> /* for _commit */
58 #include <shellapi.h>
59 #include <shlobj.h>
60 #endif
61 
62 #ifdef HAVE_MALLOPT_ARENA_MAX
63 #include <malloc.h>
64 #endif
65 
66 #include <thread>
67 
68 // Application startup time (used for uptime calculation)
69 const int64_t nStartupTime = GetTime();
70 
71 const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf";
72 
74 
80 static std::map<std::string, std::unique_ptr<fsbridge::FileLock>> dir_locks;
82 static std::mutex cs_dir_locks;
83 
84 bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only)
85 {
86  std::lock_guard<std::mutex> ulock(cs_dir_locks);
87  fs::path pathLockFile = directory / lockfile_name;
88 
89  // If a lock for this directory already exists in the map, don't try to re-lock it
90  if (dir_locks.count(pathLockFile.string())) {
91  return true;
92  }
93 
94  // Create empty lock file if it doesn't exist.
95  FILE* file = fsbridge::fopen(pathLockFile, "a");
96  if (file) fclose(file);
97  auto lock = MakeUnique<fsbridge::FileLock>(pathLockFile);
98  if (!lock->TryLock()) {
99  return error("Error while attempting to lock directory %s: %s", directory.string(), lock->GetReason());
100  }
101  if (!probe_only) {
102  // Lock successful and we're not just probing, put it into the map
103  dir_locks.emplace(pathLockFile.string(), std::move(lock));
104  }
105  return true;
106 }
107 
108 void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name)
109 {
110  std::lock_guard<std::mutex> lock(cs_dir_locks);
111  dir_locks.erase((directory / lockfile_name).string());
112 }
113 
115 {
116  std::lock_guard<std::mutex> ulock(cs_dir_locks);
117  dir_locks.clear();
118 }
119 
120 bool DirIsWritable(const fs::path& directory)
121 {
122  fs::path tmpFile = directory / fs::unique_path();
123 
124  FILE* file = fsbridge::fopen(tmpFile, "a");
125  if (!file) return false;
126 
127  fclose(file);
128  remove(tmpFile);
129 
130  return true;
131 }
132 
133 bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes)
134 {
135  constexpr uint64_t min_disk_space = 52428800; // 50 MiB
136 
137  uint64_t free_bytes_available = fs::space(dir).available;
138  return free_bytes_available >= min_disk_space + additional_bytes;
139 }
140 
158 static bool InterpretBool(const std::string& strValue)
159 {
160  if (strValue.empty())
161  return true;
162  return (atoi(strValue) != 0);
163 }
164 
167 public:
168  typedef std::map<std::string, std::vector<std::string>> MapArgs;
169 
172  static inline bool UseDefaultSection(const ArgsManager& am, const std::string& arg) EXCLUSIVE_LOCKS_REQUIRED(am.cs_args)
173  {
174  return (am.m_network == CBaseChainParams::MAIN || am.m_network_only_args.count(arg) == 0);
175  }
176 
178  static inline std::string NetworkArg(const ArgsManager& am, const std::string& arg)
179  {
180  assert(arg.length() > 1 && arg[0] == '-');
181  return "-" + am.m_network + "." + arg.substr(1);
182  }
183 
185  static inline void AddArgs(std::vector<std::string>& res, const MapArgs& map_args, const std::string& arg)
186  {
187  auto it = map_args.find(arg);
188  if (it != map_args.end()) {
189  res.insert(res.end(), it->second.begin(), it->second.end());
190  }
191  }
192 
196  static inline std::pair<bool,std::string> GetArgHelper(const MapArgs& map_args, const std::string& arg, bool getLast = false)
197  {
198  auto it = map_args.find(arg);
199 
200  if (it == map_args.end() || it->second.empty()) {
201  return std::make_pair(false, std::string());
202  }
203 
204  if (getLast) {
205  return std::make_pair(true, it->second.back());
206  } else {
207  return std::make_pair(true, it->second.front());
208  }
209  }
210 
211  /* Get the string value of an argument, returning a pair of a boolean
212  * indicating the argument was found, and the value for the argument
213  * if it was found (or the empty string if not found).
214  */
215  static inline std::pair<bool,std::string> GetArg(const ArgsManager &am, const std::string& arg)
216  {
217  LOCK(am.cs_args);
218  std::pair<bool,std::string> found_result(false, std::string());
219 
220  // We pass "true" to GetArgHelper in order to return the last
221  // argument value seen from the command line (so "bitcoind -foo=bar
222  // -foo=baz" gives GetArg(am,"foo")=={true,"baz"}
223  found_result = GetArgHelper(am.m_override_args, arg, true);
224  if (found_result.first) {
225  return found_result;
226  }
227 
228  // But in contrast we return the first argument seen in a config file,
229  // so "foo=bar \n foo=baz" in the config file gives
230  // GetArg(am,"foo")={true,"bar"}
231  if (!am.m_network.empty()) {
232  found_result = GetArgHelper(am.m_config_args, NetworkArg(am, arg));
233  if (found_result.first) {
234  return found_result;
235  }
236  }
237 
238  if (UseDefaultSection(am, arg)) {
239  found_result = GetArgHelper(am.m_config_args, arg);
240  if (found_result.first) {
241  return found_result;
242  }
243  }
244 
245  return found_result;
246  }
247 
248  /* Special test for -testnet and -regtest args, because we
249  * don't want to be confused by craziness like "[regtest] testnet=1"
250  */
251  static inline bool GetNetBoolArg(const ArgsManager &am, const std::string& net_arg) EXCLUSIVE_LOCKS_REQUIRED(am.cs_args)
252  {
253  std::pair<bool,std::string> found_result(false,std::string());
254  found_result = GetArgHelper(am.m_override_args, net_arg, true);
255  if (!found_result.first) {
256  found_result = GetArgHelper(am.m_config_args, net_arg, true);
257  if (!found_result.first) {
258  return false; // not set
259  }
260  }
261  return InterpretBool(found_result.second); // is set, so evaluate
262  }
263 };
264 
286 NODISCARD static bool InterpretOption(std::string key, std::string val, unsigned int flags,
287  std::map<std::string, std::vector<std::string>>& args,
288  std::string& error)
289 {
290  assert(key[0] == '-');
291 
292  size_t option_index = key.find('.');
293  if (option_index == std::string::npos) {
294  option_index = 1;
295  } else {
296  ++option_index;
297  }
298  if (key.substr(option_index, 2) == "no") {
299  key.erase(option_index, 2);
300  if (flags & ArgsManager::ALLOW_BOOL) {
301  if (InterpretBool(val)) {
302  args[key].clear();
303  return true;
304  }
305  // Double negatives like -nofoo=0 are supported (but discouraged)
306  LogPrintf("Warning: parsed potentially confusing double-negative %s=%s\n", key, val);
307  val = "1";
308  } else {
309  error = strprintf("Negating of %s is meaningless and therefore forbidden", key.c_str());
310  return false;
311  }
312  }
313  args[key].push_back(val);
314  return true;
315 }
316 
318 {
319  // nothing to do
320 }
321 
322 const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
323 {
324  std::set<std::string> unsuitables;
325 
326  LOCK(cs_args);
327 
328  // if there's no section selected, don't worry
329  if (m_network.empty()) return std::set<std::string> {};
330 
331  // if it's okay to use the default section for this network, don't worry
332  if (m_network == CBaseChainParams::MAIN) return std::set<std::string> {};
333 
334  for (const auto& arg : m_network_only_args) {
335  std::pair<bool, std::string> found_result;
336 
337  // if this option is overridden it's fine
338  found_result = ArgsManagerHelper::GetArgHelper(m_override_args, arg);
339  if (found_result.first) continue;
340 
341  // if there's a network-specific value for this option, it's fine
342  found_result = ArgsManagerHelper::GetArgHelper(m_config_args, ArgsManagerHelper::NetworkArg(*this, arg));
343  if (found_result.first) continue;
344 
345  // if there isn't a default value for this option, it's fine
346  found_result = ArgsManagerHelper::GetArgHelper(m_config_args, arg);
347  if (!found_result.first) continue;
348 
349  // otherwise, issue a warning
350  unsuitables.insert(arg);
351  }
352  return unsuitables;
353 }
354 
355 const std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const
356 {
357  // Section names to be recognized in the config file.
358  static const std::set<std::string> available_sections{
362  };
363 
364  LOCK(cs_args);
365  std::list<SectionInfo> unrecognized = m_config_sections;
366  unrecognized.remove_if([](const SectionInfo& appeared){ return available_sections.find(appeared.m_name) != available_sections.end(); });
367  return unrecognized;
368 }
369 
370 void ArgsManager::SelectConfigNetwork(const std::string& network)
371 {
372  LOCK(cs_args);
373  m_network = network;
374 }
375 
376 bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::string& error)
377 {
378  LOCK(cs_args);
379  m_override_args.clear();
380 
381  for (int i = 1; i < argc; i++) {
382  std::string key(argv[i]);
383  if (key == "-") break; //bitcoin-tx using stdin
384  std::string val;
385  size_t is_index = key.find('=');
386  if (is_index != std::string::npos) {
387  val = key.substr(is_index + 1);
388  key.erase(is_index);
389  }
390 #ifdef WIN32
391  key = ToLower(key);
392  if (key[0] == '/')
393  key[0] = '-';
394 #endif
395 
396  if (key[0] != '-')
397  break;
398 
399  // Transform --foo to -foo
400  if (key.length() > 1 && key[1] == '-')
401  key.erase(0, 1);
402 
403  const unsigned int flags = FlagsOfKnownArg(key);
404  if (flags) {
405  if (!InterpretOption(key, val, flags, m_override_args, error)) {
406  return false;
407  }
408  } else {
409  error = strprintf("Invalid parameter %s", key.c_str());
410  return false;
411  }
412  }
413 
414  // we do not allow -includeconf from command line, so we clear it here
415  auto it = m_override_args.find("-includeconf");
416  if (it != m_override_args.end()) {
417  if (it->second.size() > 0) {
418  for (const auto& ic : it->second) {
419  error += "-includeconf cannot be used from commandline; -includeconf=" + ic + "\n";
420  }
421  return false;
422  }
423  }
424  return true;
425 }
426 
427 unsigned int ArgsManager::FlagsOfKnownArg(const std::string& key) const
428 {
429  assert(key[0] == '-');
430 
431  size_t option_index = key.find('.');
432  if (option_index == std::string::npos) {
433  option_index = 1;
434  } else {
435  ++option_index;
436  }
437  if (key.substr(option_index, 2) == "no") {
438  option_index += 2;
439  }
440 
441  const std::string base_arg_name = '-' + key.substr(option_index);
442 
443  LOCK(cs_args);
444  for (const auto& arg_map : m_available_args) {
445  const auto search = arg_map.second.find(base_arg_name);
446  if (search != arg_map.second.end()) {
447  return search->second.m_flags;
448  }
449  }
450  return ArgsManager::NONE;
451 }
452 
453 std::vector<std::string> ArgsManager::GetArgs(const std::string& strArg) const
454 {
455  std::vector<std::string> result = {};
456  if (IsArgNegated(strArg)) return result; // special case
457 
458  LOCK(cs_args);
459 
460  ArgsManagerHelper::AddArgs(result, m_override_args, strArg);
461  if (!m_network.empty()) {
462  ArgsManagerHelper::AddArgs(result, m_config_args, ArgsManagerHelper::NetworkArg(*this, strArg));
463  }
464 
465  if (ArgsManagerHelper::UseDefaultSection(*this, strArg)) {
466  ArgsManagerHelper::AddArgs(result, m_config_args, strArg);
467  }
468 
469  return result;
470 }
471 
472 bool ArgsManager::IsArgSet(const std::string& strArg) const
473 {
474  if (IsArgNegated(strArg)) return true; // special case
475  return ArgsManagerHelper::GetArg(*this, strArg).first;
476 }
477 
478 bool ArgsManager::IsArgNegated(const std::string& strArg) const
479 {
480  LOCK(cs_args);
481 
482  const auto& ov = m_override_args.find(strArg);
483  if (ov != m_override_args.end()) return ov->second.empty();
484 
485  if (!m_network.empty()) {
486  const auto& cfs = m_config_args.find(ArgsManagerHelper::NetworkArg(*this, strArg));
487  if (cfs != m_config_args.end()) return cfs->second.empty();
488  }
489 
490  const auto& cf = m_config_args.find(strArg);
491  if (cf != m_config_args.end()) return cf->second.empty();
492 
493  return false;
494 }
495 
496 std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault) const
497 {
498  if (IsArgNegated(strArg)) return "0";
499  std::pair<bool,std::string> found_res = ArgsManagerHelper::GetArg(*this, strArg);
500  if (found_res.first) return found_res.second;
501  return strDefault;
502 }
503 
504 int64_t ArgsManager::GetArg(const std::string& strArg, int64_t nDefault) const
505 {
506  if (IsArgNegated(strArg)) return 0;
507  std::pair<bool,std::string> found_res = ArgsManagerHelper::GetArg(*this, strArg);
508  if (found_res.first) return atoi64(found_res.second);
509  return nDefault;
510 }
511 
512 bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault) const
513 {
514  if (IsArgNegated(strArg)) return false;
515  std::pair<bool,std::string> found_res = ArgsManagerHelper::GetArg(*this, strArg);
516  if (found_res.first) return InterpretBool(found_res.second);
517  return fDefault;
518 }
519 
520 bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strValue)
521 {
522  LOCK(cs_args);
523  if (IsArgSet(strArg)) return false;
524  ForceSetArg(strArg, strValue);
525  return true;
526 }
527 
528 bool ArgsManager::SoftSetBoolArg(const std::string& strArg, bool fValue)
529 {
530  if (fValue)
531  return SoftSetArg(strArg, std::string("1"));
532  else
533  return SoftSetArg(strArg, std::string("0"));
534 }
535 
536 void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strValue)
537 {
538  LOCK(cs_args);
539  m_override_args[strArg] = {strValue};
540 }
541 
542 void ArgsManager::AddArg(const std::string& name, const std::string& help, unsigned int flags, const OptionsCategory& cat)
543 {
544  // Split arg name from its help param
545  size_t eq_index = name.find('=');
546  if (eq_index == std::string::npos) {
547  eq_index = name.size();
548  }
549  std::string arg_name = name.substr(0, eq_index);
550 
551  LOCK(cs_args);
552  std::map<std::string, Arg>& arg_map = m_available_args[cat];
553  auto ret = arg_map.emplace(arg_name, Arg{name.substr(eq_index, name.size() - eq_index), help, flags});
554  assert(ret.second); // Make sure an insertion actually happened
555 
556  if (flags & ArgsManager::NETWORK_ONLY) {
557  m_network_only_args.emplace(arg_name);
558  }
559 }
560 
561 void ArgsManager::AddHiddenArgs(const std::vector<std::string>& names)
562 {
563  for (const std::string& name : names) {
565  }
566 }
567 
568 std::string ArgsManager::GetHelpMessage() const
569 {
570  const bool show_debug = gArgs.GetBoolArg("-help-debug", false);
571 
572  std::string usage = "";
573  LOCK(cs_args);
574  for (const auto& arg_map : m_available_args) {
575  switch(arg_map.first) {
577  usage += HelpMessageGroup("Options:");
578  break;
580  usage += HelpMessageGroup("Connection options:");
581  break;
583  usage += HelpMessageGroup("ZeroMQ notification options:");
584  break;
586  usage += HelpMessageGroup("Debugging/Testing options:");
587  break;
589  usage += HelpMessageGroup("Node relay options:");
590  break;
592  usage += HelpMessageGroup("Block creation options:");
593  break;
595  usage += HelpMessageGroup("RPC server options:");
596  break;
598  usage += HelpMessageGroup("Wallet options:");
599  break;
601  if (show_debug) usage += HelpMessageGroup("Wallet debugging/testing options:");
602  break;
604  usage += HelpMessageGroup("Chain selection options:");
605  break;
607  usage += HelpMessageGroup("UI Options:");
608  break;
610  usage += HelpMessageGroup("Commands:");
611  break;
613  usage += HelpMessageGroup("Register Commands:");
614  break;
615  default:
616  break;
617  }
618 
619  // When we get to the hidden options, stop
620  if (arg_map.first == OptionsCategory::HIDDEN) break;
621 
622  for (const auto& arg : arg_map.second) {
623  if (show_debug || !(arg.second.m_flags & ArgsManager::DEBUG_ONLY)) {
624  std::string name;
625  if (arg.second.m_help_param.empty()) {
626  name = arg.first;
627  } else {
628  name = arg.first + arg.second.m_help_param;
629  }
630  usage += HelpMessageOpt(name, arg.second.m_help_text);
631  }
632  }
633  }
634  return usage;
635 }
636 
637 bool HelpRequested(const ArgsManager& args)
638 {
639  return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help") || args.IsArgSet("-help-debug");
640 }
641 
643 {
644  args.AddArg("-?", "Print this help message and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
645  args.AddHiddenArgs({"-h", "-help"});
646 }
647 
648 static const int screenWidth = 79;
649 static const int optIndent = 2;
650 static const int msgIndent = 7;
651 
652 std::string HelpMessageGroup(const std::string &message) {
653  return std::string(message) + std::string("\n\n");
654 }
655 
656 std::string HelpMessageOpt(const std::string &option, const std::string &message) {
657  return std::string(optIndent,' ') + std::string(option) +
658  std::string("\n") + std::string(msgIndent,' ') +
660  std::string("\n\n");
661 }
662 
663 static std::string FormatException(const std::exception* pex, const char* pszThread)
664 {
665 #ifdef WIN32
666  char pszModule[MAX_PATH] = "";
667  GetModuleFileNameA(nullptr, pszModule, sizeof(pszModule));
668 #else
669  const char* pszModule = "bitcoin";
670 #endif
671  if (pex)
672  return strprintf(
673  "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
674  else
675  return strprintf(
676  "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
677 }
678 
679 void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
680 {
681  std::string message = FormatException(pex, pszThread);
682  LogPrintf("\n\n************************\n%s\n", message);
683  tfm::format(std::cerr, "\n\n************************\n%s\n", message.c_str());
684 }
685 
687 {
688  // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
689  // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
690  // Mac: ~/Library/Application Support/Bitcoin
691  // Unix: ~/.bitcoin
692 #ifdef WIN32
693  // Windows
694  return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
695 #else
696  fs::path pathRet;
697  char* pszHome = getenv("HOME");
698  if (pszHome == nullptr || strlen(pszHome) == 0)
699  pathRet = fs::path("/");
700  else
701  pathRet = fs::path(pszHome);
702 #ifdef MAC_OSX
703  // Mac
704  return pathRet / "Library/Application Support/Bitcoin";
705 #else
706  // Unix
707  return pathRet / ".bitcoin";
708 #endif
709 #endif
710 }
711 
713 static fs::path pathCached;
714 static fs::path pathCachedNetSpecific;
716 
717 const fs::path &GetBlocksDir()
718 {
719  LOCK(csPathCached);
720  fs::path &path = g_blocks_path_cache_net_specific;
721 
722  // Cache the path to avoid calling fs::create_directories on every call of
723  // this function
724  if (!path.empty()) return path;
725 
726  if (gArgs.IsArgSet("-blocksdir")) {
727  path = fs::system_complete(gArgs.GetArg("-blocksdir", ""));
728  if (!fs::is_directory(path)) {
729  path = "";
730  return path;
731  }
732  } else {
733  path = GetDataDir(false);
734  }
735 
736  path /= BaseParams().DataDir();
737  path /= "blocks";
738  fs::create_directories(path);
739  return path;
740 }
741 
742 const fs::path &GetDataDir(bool fNetSpecific)
743 {
744  LOCK(csPathCached);
745  fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
746 
747  // Cache the path to avoid calling fs::create_directories on every call of
748  // this function
749  if (!path.empty()) return path;
750 
751  std::string datadir = gArgs.GetArg("-datadir", "");
752  if (!datadir.empty()) {
753  path = fs::system_complete(datadir);
754  if (!fs::is_directory(path)) {
755  path = "";
756  return path;
757  }
758  } else {
759  path = GetDefaultDataDir();
760  }
761  if (fNetSpecific)
762  path /= BaseParams().DataDir();
763 
764  if (fs::create_directories(path)) {
765  // This is the first run, create wallets subdirectory too
766  fs::create_directories(path / "wallets");
767  }
768 
769  return path;
770 }
771 
773 {
774  std::string datadir = gArgs.GetArg("-datadir", "");
775  return datadir.empty() || fs::is_directory(fs::system_complete(datadir));
776 }
777 
779 {
780  LOCK(csPathCached);
781 
782  pathCached = fs::path();
783  pathCachedNetSpecific = fs::path();
785 }
786 
787 fs::path GetConfigFile(const std::string& confPath)
788 {
789  return AbsPathForConfigVal(fs::path(confPath), false);
790 }
791 
792 static std::string TrimString(const std::string& str, const std::string& pattern)
793 {
794  std::string::size_type front = str.find_first_not_of(pattern);
795  if (front == std::string::npos) {
796  return std::string();
797  }
798  std::string::size_type end = str.find_last_not_of(pattern);
799  return str.substr(front, end - front + 1);
800 }
801 
802 static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections)
803 {
804  std::string str, prefix;
805  std::string::size_type pos;
806  int linenr = 1;
807  while (std::getline(stream, str)) {
808  bool used_hash = false;
809  if ((pos = str.find('#')) != std::string::npos) {
810  str = str.substr(0, pos);
811  used_hash = true;
812  }
813  const static std::string pattern = " \t\r\n";
814  str = TrimString(str, pattern);
815  if (!str.empty()) {
816  if (*str.begin() == '[' && *str.rbegin() == ']') {
817  const std::string section = str.substr(1, str.size() - 2);
818  sections.emplace_back(SectionInfo{section, filepath, linenr});
819  prefix = section + '.';
820  } else if (*str.begin() == '-') {
821  error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str);
822  return false;
823  } else if ((pos = str.find('=')) != std::string::npos) {
824  std::string name = prefix + TrimString(str.substr(0, pos), pattern);
825  std::string value = TrimString(str.substr(pos + 1), pattern);
826  if (used_hash && name.find("rpcpassword") != std::string::npos) {
827  error = strprintf("parse error on line %i, using # in rpcpassword can be ambiguous and should be avoided", linenr);
828  return false;
829  }
830  options.emplace_back(name, value);
831  if ((pos = name.rfind('.')) != std::string::npos && prefix.length() <= pos) {
832  sections.emplace_back(SectionInfo{name.substr(0, pos), filepath, linenr});
833  }
834  } else {
835  error = strprintf("parse error on line %i: %s", linenr, str);
836  if (str.size() >= 2 && str.substr(0, 2) == "no") {
837  error += strprintf(", if you intended to specify a negated option, use %s=1 instead", str);
838  }
839  return false;
840  }
841  }
842  ++linenr;
843  }
844  return true;
845 }
846 
847 bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys)
848 {
849  LOCK(cs_args);
850  std::vector<std::pair<std::string, std::string>> options;
851  if (!GetConfigOptions(stream, filepath, error, options, m_config_sections)) {
852  return false;
853  }
854  for (const std::pair<std::string, std::string>& option : options) {
855  const std::string strKey = std::string("-") + option.first;
856  const unsigned int flags = FlagsOfKnownArg(strKey);
857  if (flags) {
858  if (!InterpretOption(strKey, option.second, flags, m_config_args, error)) {
859  return false;
860  }
861  } else {
862  if (ignore_invalid_keys) {
863  LogPrintf("Ignoring unknown configuration value %s\n", option.first);
864  } else {
865  error = strprintf("Invalid configuration value %s", option.first.c_str());
866  return false;
867  }
868  }
869  }
870  return true;
871 }
872 
873 bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
874 {
875  {
876  LOCK(cs_args);
877  m_config_args.clear();
878  m_config_sections.clear();
879  }
880 
881  const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME);
882  fsbridge::ifstream stream(GetConfigFile(confPath));
883 
884  // ok to not have a config file
885  if (stream.good()) {
886  if (!ReadConfigStream(stream, confPath, error, ignore_invalid_keys)) {
887  return false;
888  }
889  // if there is an -includeconf in the override args, but it is empty, that means the user
890  // passed '-noincludeconf' on the command line, in which case we should not include anything
891  bool emptyIncludeConf;
892  {
893  LOCK(cs_args);
894  emptyIncludeConf = m_override_args.count("-includeconf") == 0;
895  }
896  if (emptyIncludeConf) {
897  std::string chain_id = GetChainName();
898  std::vector<std::string> includeconf(GetArgs("-includeconf"));
899  {
900  // We haven't set m_network yet (that happens in SelectParams()), so manually check
901  // for network.includeconf args.
902  std::vector<std::string> includeconf_net(GetArgs(std::string("-") + chain_id + ".includeconf"));
903  includeconf.insert(includeconf.end(), includeconf_net.begin(), includeconf_net.end());
904  }
905 
906  // Remove -includeconf from configuration, so we can warn about recursion
907  // later
908  {
909  LOCK(cs_args);
910  m_config_args.erase("-includeconf");
911  m_config_args.erase(std::string("-") + chain_id + ".includeconf");
912  }
913 
914  for (const std::string& to_include : includeconf) {
915  fsbridge::ifstream include_config(GetConfigFile(to_include));
916  if (include_config.good()) {
917  if (!ReadConfigStream(include_config, to_include, error, ignore_invalid_keys)) {
918  return false;
919  }
920  LogPrintf("Included configuration file %s\n", to_include.c_str());
921  } else {
922  error = "Failed to include configuration file " + to_include;
923  return false;
924  }
925  }
926 
927  // Warn about recursive -includeconf
928  includeconf = GetArgs("-includeconf");
929  {
930  std::vector<std::string> includeconf_net(GetArgs(std::string("-") + chain_id + ".includeconf"));
931  includeconf.insert(includeconf.end(), includeconf_net.begin(), includeconf_net.end());
932  std::string chain_id_final = GetChainName();
933  if (chain_id_final != chain_id) {
934  // Also warn about recursive includeconf for the chain that was specified in one of the includeconfs
935  includeconf_net = GetArgs(std::string("-") + chain_id_final + ".includeconf");
936  includeconf.insert(includeconf.end(), includeconf_net.begin(), includeconf_net.end());
937  }
938  }
939  for (const std::string& to_include : includeconf) {
940  tfm::format(std::cerr, "warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", to_include.c_str());
941  }
942  }
943  }
944 
945  // If datadir is changed in .conf file:
947  if (!CheckDataDirOption()) {
948  error = strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "").c_str());
949  return false;
950  }
951  return true;
952 }
953 
954 std::string ArgsManager::GetChainName() const
955 {
956  LOCK(cs_args);
957  bool fRegTest = ArgsManagerHelper::GetNetBoolArg(*this, "-regtest");
958  bool fTestNet = ArgsManagerHelper::GetNetBoolArg(*this, "-testnet");
959 
960  if (fTestNet && fRegTest)
961  throw std::runtime_error("Invalid combination of -regtest and -testnet.");
962  if (fRegTest)
964  if (fTestNet)
966  return CBaseChainParams::MAIN;
967 }
968 
969 bool RenameOver(fs::path src, fs::path dest)
970 {
971 #ifdef WIN32
972  return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
973  MOVEFILE_REPLACE_EXISTING) != 0;
974 #else
975  int rc = std::rename(src.string().c_str(), dest.string().c_str());
976  return (rc == 0);
977 #endif /* WIN32 */
978 }
979 
985 bool TryCreateDirectories(const fs::path& p)
986 {
987  try
988  {
989  return fs::create_directories(p);
990  } catch (const fs::filesystem_error&) {
991  if (!fs::exists(p) || !fs::is_directory(p))
992  throw;
993  }
994 
995  // create_directories didn't create the directory, it had to have existed already
996  return false;
997 }
998 
999 bool FileCommit(FILE *file)
1000 {
1001  if (fflush(file) != 0) { // harmless if redundantly called
1002  LogPrintf("%s: fflush failed: %d\n", __func__, errno);
1003  return false;
1004  }
1005 #ifdef WIN32
1006  HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
1007  if (FlushFileBuffers(hFile) == 0) {
1008  LogPrintf("%s: FlushFileBuffers failed: %d\n", __func__, GetLastError());
1009  return false;
1010  }
1011 #else
1012  #if defined(__linux__) || defined(__NetBSD__)
1013  if (fdatasync(fileno(file)) != 0 && errno != EINVAL) { // Ignore EINVAL for filesystems that don't support sync
1014  LogPrintf("%s: fdatasync failed: %d\n", __func__, errno);
1015  return false;
1016  }
1017  #elif defined(MAC_OSX) && defined(F_FULLFSYNC)
1018  if (fcntl(fileno(file), F_FULLFSYNC, 0) == -1) { // Manpage says "value other than -1" is returned on success
1019  LogPrintf("%s: fcntl F_FULLFSYNC failed: %d\n", __func__, errno);
1020  return false;
1021  }
1022  #else
1023  if (fsync(fileno(file)) != 0 && errno != EINVAL) {
1024  LogPrintf("%s: fsync failed: %d\n", __func__, errno);
1025  return false;
1026  }
1027  #endif
1028 #endif
1029  return true;
1030 }
1031 
1032 bool TruncateFile(FILE *file, unsigned int length) {
1033 #if defined(WIN32)
1034  return _chsize(_fileno(file), length) == 0;
1035 #else
1036  return ftruncate(fileno(file), length) == 0;
1037 #endif
1038 }
1039 
1044 int RaiseFileDescriptorLimit(int nMinFD) {
1045 #if defined(WIN32)
1046  return 2048;
1047 #else
1048  struct rlimit limitFD;
1049  if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
1050  if (limitFD.rlim_cur < (rlim_t)nMinFD) {
1051  limitFD.rlim_cur = nMinFD;
1052  if (limitFD.rlim_cur > limitFD.rlim_max)
1053  limitFD.rlim_cur = limitFD.rlim_max;
1054  setrlimit(RLIMIT_NOFILE, &limitFD);
1055  getrlimit(RLIMIT_NOFILE, &limitFD);
1056  }
1057  return limitFD.rlim_cur;
1058  }
1059  return nMinFD; // getrlimit failed, assume it's fine
1060 #endif
1061 }
1062 
1067 void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
1068 #if defined(WIN32)
1069  // Windows-specific version
1070  HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
1071  LARGE_INTEGER nFileSize;
1072  int64_t nEndPos = (int64_t)offset + length;
1073  nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
1074  nFileSize.u.HighPart = nEndPos >> 32;
1075  SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
1076  SetEndOfFile(hFile);
1077 #elif defined(MAC_OSX)
1078  // OSX specific version
1079  fstore_t fst;
1080  fst.fst_flags = F_ALLOCATECONTIG;
1081  fst.fst_posmode = F_PEOFPOSMODE;
1082  fst.fst_offset = 0;
1083  fst.fst_length = (off_t)offset + length;
1084  fst.fst_bytesalloc = 0;
1085  if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
1086  fst.fst_flags = F_ALLOCATEALL;
1087  fcntl(fileno(file), F_PREALLOCATE, &fst);
1088  }
1089  ftruncate(fileno(file), fst.fst_length);
1090 #else
1091  #if defined(__linux__)
1092  // Version using posix_fallocate
1093  off_t nEndPos = (off_t)offset + length;
1094  if (0 == posix_fallocate(fileno(file), 0, nEndPos)) return;
1095  #endif
1096  // Fallback version
1097  // TODO: just write one byte per block
1098  static const char buf[65536] = {};
1099  if (fseek(file, offset, SEEK_SET)) {
1100  return;
1101  }
1102  while (length > 0) {
1103  unsigned int now = 65536;
1104  if (length < now)
1105  now = length;
1106  fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
1107  length -= now;
1108  }
1109 #endif
1110 }
1111 
1112 #ifdef WIN32
1113 fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
1114 {
1115  WCHAR pszPath[MAX_PATH] = L"";
1116 
1117  if(SHGetSpecialFolderPathW(nullptr, pszPath, nFolder, fCreate))
1118  {
1119  return fs::path(pszPath);
1120  }
1121 
1122  LogPrintf("SHGetSpecialFolderPathW() failed, could not obtain requested path.\n");
1123  return fs::path("");
1124 }
1125 #endif
1126 
1127 #if HAVE_SYSTEM
1128 void runCommand(const std::string& strCommand)
1129 {
1130  if (strCommand.empty()) return;
1131 #ifndef WIN32
1132  int nErr = ::system(strCommand.c_str());
1133 #else
1134  int nErr = ::_wsystem(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().from_bytes(strCommand).c_str());
1135 #endif
1136  if (nErr)
1137  LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
1138 }
1139 #endif
1140 
1142 {
1143 #ifdef HAVE_MALLOPT_ARENA_MAX
1144  // glibc-specific: On 32-bit systems set the number of arenas to 1.
1145  // By default, since glibc 2.10, the C library will create up to two heap
1146  // arenas per core. This is known to cause excessive virtual address space
1147  // usage in our usage. Work around it by setting the maximum number of
1148  // arenas to 1.
1149  if (sizeof(void*) == 4) {
1150  mallopt(M_ARENA_MAX, 1);
1151  }
1152 #endif
1153  // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
1154  // may be invalid, in which case the "C" locale is used as fallback.
1155 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
1156  try {
1157  std::locale(""); // Raises a runtime error if current locale is invalid
1158  } catch (const std::runtime_error&) {
1159  setenv("LC_ALL", "C", 1);
1160  }
1161 #elif defined(WIN32)
1162  // Set the default input/output charset is utf-8
1163  SetConsoleCP(CP_UTF8);
1164  SetConsoleOutputCP(CP_UTF8);
1165 #endif
1166  // The path locale is lazy initialized and to avoid deinitialization errors
1167  // in multithreading environments, it is set explicitly by the main thread.
1168  // A dummy locale is used to extract the internal default locale, used by
1169  // fs::path, which is then used to explicitly imbue the path.
1170  std::locale loc = fs::path::imbue(std::locale::classic());
1171 #ifndef WIN32
1172  fs::path::imbue(loc);
1173 #else
1174  fs::path::imbue(std::locale(loc, new std::codecvt_utf8_utf16<wchar_t>()));
1175 #endif
1176 }
1177 
1179 {
1180 #ifdef WIN32
1181  // Initialize Windows Sockets
1182  WSADATA wsadata;
1183  int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1184  if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
1185  return false;
1186 #endif
1187  return true;
1188 }
1189 
1191 {
1192  return std::thread::hardware_concurrency();
1193 }
1194 
1195 std::string CopyrightHolders(const std::string& strPrefix)
1196 {
1197  const auto copyright_devs = strprintf(_(COPYRIGHT_HOLDERS).translated, COPYRIGHT_HOLDERS_SUBSTITUTION);
1198  std::string strCopyrightHolders = strPrefix + copyright_devs;
1199 
1200  // Make sure Bitcoin Core copyright is not removed by accident
1201  if (copyright_devs.find("Bitcoin Core") == std::string::npos) {
1202  strCopyrightHolders += "\n" + strPrefix + "The Bitcoin Core developers";
1203  }
1204  return strCopyrightHolders;
1205 }
1206 
1207 // Obtain the application startup time (used for uptime calculation)
1209 {
1210  return nStartupTime;
1211 }
1212 
1213 fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific)
1214 {
1215  if (path.is_absolute()) {
1216  return path;
1217  }
1218  return fs::absolute(path, GetDataDir(net_specific));
1219 }
1220 
1222 {
1223 #ifdef SCHED_BATCH
1224  const static sched_param param{};
1225  if (int ret = pthread_setschedparam(pthread_self(), SCHED_BATCH, &param)) {
1226  LogPrintf("Failed to pthread_setschedparam: %s\n", strerror(errno));
1227  return ret;
1228  }
1229  return 0;
1230 #else
1231  return 1;
1232 #endif
1233 }
1234 
1235 namespace util {
1236 #ifdef WIN32
1237 WinCmdLineArgs::WinCmdLineArgs()
1238 {
1239  wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
1240  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_cvt;
1241  argv = new char*[argc];
1242  args.resize(argc);
1243  for (int i = 0; i < argc; i++) {
1244  args[i] = utf8_cvt.to_bytes(wargv[i]);
1245  argv[i] = &*args[i].begin();
1246  }
1247  LocalFree(wargv);
1248 }
1249 
1250 WinCmdLineArgs::~WinCmdLineArgs()
1251 {
1252  delete[] argv;
1253 }
1254 
1255 std::pair<int, char**> WinCmdLineArgs::get()
1256 {
1257  return std::make_pair(argc, argv);
1258 }
1259 #endif
1260 } // namespace util
NODISCARD bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
Definition: system.cpp:873
static const int optIndent
Definition: system.cpp:649
#define COPYRIGHT_HOLDERS_SUBSTITUTION
#define COPYRIGHT_HOLDERS
static bool GetNetBoolArg(const ArgsManager &am, const std::string &net_arg) EXCLUSIVE_LOCKS_REQUIRED(am.cs_args)
Definition: system.cpp:251
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:472
std::string FormatParagraph(const std::string &in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line...
bool FileCommit(FILE *file)
Definition: system.cpp:999
static std::map< std::string, std::unique_ptr< fsbridge::FileLock > > dir_locks
A map that contains all the currently held directory locks.
Definition: system.cpp:80
std::string ToLower(const std::string &str)
Returns the lowercase equivalent of the given string.
bool DirIsWritable(const fs::path &directory)
Definition: system.cpp:120
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:15
fs::path GetDefaultDataDir()
Definition: system.cpp:686
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn&#39;t already have a value.
Definition: system.cpp:528
static const int msgIndent
Definition: system.cpp:650
static const std::string REGTEST
int GetNumCores()
Return the number of cores available on the current system.
Definition: system.cpp:1190
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1067
const char * prefix
Definition: rest.cpp:626
void AddHiddenArgs(const std::vector< std::string > &args)
Add many hidden arguments.
Definition: system.cpp:561
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by Boost&#39;s create_directories if the requested directory exists...
Definition: system.cpp:985
fs::ifstream ifstream
Definition: fs.h:91
#define MAX_PATH
Definition: compat.h:69
void SetupEnvironment()
Definition: system.cpp:1141
static bool InterpretBool(const std::string &strValue)
Interpret a string argument as a boolean.
Definition: system.cpp:158
std::string CopyrightHolders(const std::string &strPrefix)
Definition: system.cpp:1195
void SelectConfigNetwork(const std::string &network)
Select the network in use.
Definition: system.cpp:370
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
static std::mutex cs_dir_locks
Mutex to protect dir_locks.
Definition: system.cpp:82
NODISCARD bool ReadConfigStream(std::istream &stream, const std::string &filepath, std::string &error, bool ignore_invalid_keys=false)
Definition: system.cpp:847
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:144
NODISCARD bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: system.cpp:376
const fs::path & GetBlocksDir()
Definition: system.cpp:717
int RaiseFileDescriptorLimit(int nMinFD)
this function tries to raise the file descriptor limit to the requested number.
Definition: system.cpp:1044
void ReleaseDirectoryLocks()
Release all directory locks.
Definition: system.cpp:114
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:512
void ClearDatadirCache()
Tests only.
Definition: system.cpp:778
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: system.cpp:536
bool CheckDiskSpace(const fs::path &dir, uint64_t additional_bytes)
Definition: system.cpp:133
const char *const BITCOIN_CONF_FILENAME
Definition: system.cpp:71
static bool UseDefaultSection(const ArgsManager &am, const std::string &arg) EXCLUSIVE_LOCKS_REQUIRED(am.cs_args)
Determine whether to use config settings in the default section, See also comments around ArgsManager...
Definition: system.cpp:172
bool SetupNetworking()
Definition: system.cpp:1178
static RecursiveMutex csPathCached
Definition: system.cpp:715
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn&#39;t already have a value.
Definition: system.cpp:520
std::string m_name
Definition: system.h:125
const std::string & DataDir() const
std::string GetHelpMessage() const
Get the help string.
Definition: system.cpp:568
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
bool CheckDataDirOption()
Definition: system.cpp:772
bool LockDirectory(const fs::path &directory, const std::string lockfile_name, bool probe_only)
Definition: system.cpp:84
bool IsArgNegated(const std::string &strArg) const
Return true if the argument was originally passed as a negated option, i.e.
Definition: system.cpp:478
#define NODISCARD
Definition: attributes.h:18
#define LOCK(cs)
Definition: sync.h:182
const char * name
Definition: rest.cpp:39
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:37
int atoi(const std::string &str)
void format(std::ostream &out, const char *fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:967
static NODISCARD bool InterpretOption(std::string key, std::string val, unsigned int flags, std::map< std::string, std::vector< std::string >> &args, std::string &error)
Interpret -nofoo as if the user supplied -foo=0.
Definition: system.cpp:286
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: system.cpp:542
bool HelpRequested(const ArgsManager &args)
Definition: system.cpp:637
const fs::path & GetDataDir(bool fNetSpecific)
Definition: system.cpp:742
static std::string NetworkArg(const ArgsManager &am, const std::string &arg)
Convert regular argument into the network-specific setting.
Definition: system.cpp:178
CCriticalSection cs_args
Definition: system.h:159
UniValue help(const JSONRPCRequest &jsonRequest)
Definition: server.cpp:132
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
Definition: system.cpp:679
static std::pair< bool, std::string > GetArg(const ArgsManager &am, const std::string &arg)
Definition: system.cpp:215
fs::path AbsPathForConfigVal(const fs::path &path, bool net_specific)
Most paths passed as configuration arguments are treated as relative to the datadir if they are not a...
Definition: system.cpp:1213
std::map< std::string, std::vector< std::string > > MapArgs
Definition: system.cpp:168
unsigned int FlagsOfKnownArg(const std::string &key) const
Return Flags for known arg.
Definition: system.cpp:427
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length)
this function tries to make a particular range of a file allocated (corresponding to disk space) it i...
Definition: system.cpp:1067
bool RenameOver(fs::path src, fs::path dest)
Definition: system.cpp:969
int flags
Definition: bitcoin-tx.cpp:509
static fs::path g_blocks_path_cache_net_specific
Definition: system.cpp:712
int64_t atoi64(const char *psz)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
Internal helper functions for ArgsManager.
Definition: system.cpp:166
int64_t GetStartupTime()
Server/client environment: argument handling, config file parsing, thread wrappers, startup time.
Definition: system.cpp:1208
static const int screenWidth
Definition: system.cpp:648
bool TruncateFile(FILE *file, unsigned int length)
Definition: system.cpp:1032
fs::path GetConfigFile(const std::string &confPath)
Definition: system.cpp:787
void UnlockDirectory(const fs::path &directory, const std::string &lockfile_name)
Definition: system.cpp:108
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:496
static bool GetConfigOptions(std::istream &stream, const std::string &filepath, std::string &error, std::vector< std::pair< std::string, std::string >> &options, std::list< SectionInfo > &sections)
Definition: system.cpp:802
ArgsManager gArgs
Definition: system.cpp:73
int ScheduleBatchPriority()
On platforms that support it, tell the kernel the calling thread is CPU-intensive and non-interactive...
Definition: system.cpp:1221
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
Definition: system.cpp:642
static fs::path pathCachedNetSpecific
Definition: system.cpp:714
static const std::string TESTNET
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Definition: system.cpp:954
const std::list< SectionInfo > GetUnrecognizedSections() const
Log warnings for unrecognized section names in the config file.
Definition: system.cpp:355
static fs::path pathCached
Definition: system.cpp:713
OptionsCategory
Definition: system.h:105
static std::string TrimString(const std::string &str, const std::string &pattern)
Definition: system.cpp:792
const int64_t nStartupTime
Definition: system.cpp:69
static void AddArgs(std::vector< std::string > &res, const MapArgs &map_args, const std::string &arg)
Find arguments in a map and add them to a vector.
Definition: system.cpp:185
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: system.cpp:453
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
Definition: system.cpp:656
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:20
auto it
Definition: validation.cpp:366
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
Definition: system.cpp:652
static std::string FormatException(const std::exception *pex, const char *pszThread)
Definition: system.cpp:663
const std::set< std::string > GetUnsuitableSectionOnlyArgs() const
Log warnings for options in m_section_only_args when they are specified in the default section but no...
Definition: system.cpp:322
bool error(const char *fmt, const Args &... args)
Definition: system.h:47
static std::pair< bool, std::string > GetArgHelper(const MapArgs &map_args, const std::string &arg, bool getLast=false)
Return true/false if an argument is set in a map, and also return the first (or last) of the possibly...
Definition: system.cpp:196