Bitcoin ABC  0.24.7
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 <sync.h>
10 #include <util/strencodings.h>
11 #include <util/string.h>
12 #include <util/translation.h>
13 
14 #include <univalue.h>
15 
16 #include <memory>
17 #include <thread>
18 #include <typeinfo>
19 
20 #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
21 #include <pthread.h>
22 #include <pthread_np.h>
23 #endif
24 
25 #ifndef WIN32
26 // for posix_fallocate, in config/CMakeLists.txt we check if it is present after
27 // this
28 #ifdef __linux__
29 
30 #ifdef _POSIX_C_SOURCE
31 #undef _POSIX_C_SOURCE
32 #endif
33 
34 #define _POSIX_C_SOURCE 200112L
35 
36 #endif // __linux__
37 
38 #include <algorithm>
39 #include <fcntl.h>
40 #include <sched.h>
41 #include <sys/resource.h>
42 #include <sys/stat.h>
43 
44 #else
45 
46 #ifdef _MSC_VER
47 #pragma warning(disable : 4786)
48 #pragma warning(disable : 4804)
49 #pragma warning(disable : 4805)
50 #pragma warning(disable : 4717)
51 #endif
52 
53 #ifndef NOMINMAX
54 #define NOMINMAX
55 #endif
56 #include <codecvt>
57 
58 #include <io.h> /* for _commit */
59 #include <shellapi.h>
60 #include <shlobj.h>
61 #endif
62 
63 #ifdef HAVE_MALLOPT_ARENA_MAX
64 #include <malloc.h>
65 #endif
66 
67 #include <boost/algorithm/string/replace.hpp>
68 
69 // Application startup time (used for uptime calculation)
70 const int64_t nStartupTime = GetTime();
71 
72 const char *const BITCOIN_CONF_FILENAME = "bitcoin.conf";
73 const char *const BITCOIN_SETTINGS_FILENAME = "settings.json";
74 
76 
84 static std::map<std::string, std::unique_ptr<fsbridge::FileLock>>
85  dir_locks GUARDED_BY(cs_dir_locks);
86 
87 bool LockDirectory(const fs::path &directory, const std::string lockfile_name,
88  bool probe_only) {
90  fs::path pathLockFile = directory / lockfile_name;
91 
92  // If a lock for this directory already exists in the map, don't try to
93  // re-lock it
94  if (dir_locks.count(pathLockFile.string())) {
95  return true;
96  }
97 
98  // Create empty lock file if it doesn't exist.
99  FILE *file = fsbridge::fopen(pathLockFile, "a");
100  if (file) {
101  fclose(file);
102  }
103  auto lock = std::make_unique<fsbridge::FileLock>(pathLockFile);
104  if (!lock->TryLock()) {
105  return error("Error while attempting to lock directory %s: %s",
106  directory.string(), lock->GetReason());
107  }
108  if (!probe_only) {
109  // Lock successful and we're not just probing, put it into the map
110  dir_locks.emplace(pathLockFile.string(), std::move(lock));
111  }
112  return true;
113 }
114 
115 void UnlockDirectory(const fs::path &directory,
116  const std::string &lockfile_name) {
118  dir_locks.erase((directory / lockfile_name).string());
119 }
120 
123  dir_locks.clear();
124 }
125 
126 bool DirIsWritable(const fs::path &directory) {
127  fs::path tmpFile = directory / fs::unique_path();
128 
129  FILE *file = fsbridge::fopen(tmpFile, "a");
130  if (!file) {
131  return false;
132  }
133 
134  fclose(file);
135  remove(tmpFile);
136 
137  return true;
138 }
139 
140 bool CheckDiskSpace(const fs::path &dir, uint64_t additional_bytes) {
141  // 50 MiB
142  constexpr uint64_t min_disk_space = 52428800;
143 
144  uint64_t free_bytes_available = fs::space(dir).available;
145  return free_bytes_available >= min_disk_space + additional_bytes;
146 }
147 
148 std::streampos GetFileSize(const char *path, std::streamsize max) {
149  std::ifstream file(path, std::ios::binary);
150  file.ignore(max);
151  return file.gcount();
152 }
153 
171 static bool InterpretBool(const std::string &strValue) {
172  if (strValue.empty()) {
173  return true;
174  }
175  return (atoi(strValue) != 0);
176 }
177 
178 static std::string SettingName(const std::string &arg) {
179  return arg.size() > 0 && arg[0] == '-' ? arg.substr(1) : arg;
180 }
181 
202 static util::SettingsValue InterpretOption(std::string &section,
203  std::string &key,
204  const std::string &value) {
205  // Split section name from key name for keys like "testnet.foo" or
206  // "regtest.bar"
207  size_t option_index = key.find('.');
208  if (option_index != std::string::npos) {
209  section = key.substr(0, option_index);
210  key.erase(0, option_index + 1);
211  }
212  if (key.substr(0, 2) == "no") {
213  key.erase(0, 2);
214  // Double negatives like -nofoo=0 are supported (but discouraged)
215  if (!InterpretBool(value)) {
216  LogPrintf("Warning: parsed potentially confusing double-negative "
217  "-%s=%s\n",
218  key, value);
219  return true;
220  }
221  return false;
222  }
223  return value;
224 }
225 
233 static bool CheckValid(const std::string &key, const util::SettingsValue &val,
234  unsigned int flags, std::string &error) {
235  if (val.isBool() && !(flags & ArgsManager::ALLOW_BOOL)) {
236  error = strprintf(
237  "Negating of -%s is meaningless and therefore forbidden", key);
238  return false;
239  }
240  return true;
241 }
242 
243 // Define default constructor and destructor that are not inline, so code
244 // instantiating this class doesn't need to #include class definitions for all
245 // members. For example, m_settings has an internal dependency on univalue.
248 
249 const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const {
250  std::set<std::string> unsuitables;
251 
252  LOCK(cs_args);
253 
254  // if there's no section selected, don't worry
255  if (m_network.empty()) {
256  return std::set<std::string>{};
257  }
258 
259  // if it's okay to use the default section for this network, don't worry
260  if (m_network == CBaseChainParams::MAIN) {
261  return std::set<std::string>{};
262  }
263 
264  for (const auto &arg : m_network_only_args) {
265  if (OnlyHasDefaultSectionSetting(m_settings, m_network,
266  SettingName(arg))) {
267  unsuitables.insert(arg);
268  }
269  }
270  return unsuitables;
271 }
272 
273 const std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const {
274  // Section names to be recognized in the config file.
275  static const std::set<std::string> available_sections{
278 
279  LOCK(cs_args);
280  std::list<SectionInfo> unrecognized = m_config_sections;
281  unrecognized.remove_if([](const SectionInfo &appeared) {
282  return available_sections.find(appeared.m_name) !=
283  available_sections.end();
284  });
285  return unrecognized;
286 }
287 
288 void ArgsManager::SelectConfigNetwork(const std::string &network) {
289  LOCK(cs_args);
290  m_network = network;
291 }
292 
293 bool ParseKeyValue(std::string &key, std::string &val) {
294  size_t is_index = key.find('=');
295  if (is_index != std::string::npos) {
296  val = key.substr(is_index + 1);
297  key.erase(is_index);
298  }
299 #ifdef WIN32
300  key = ToLower(key);
301  if (key[0] == '/') {
302  key[0] = '-';
303  }
304 #endif
305 
306  if (key[0] != '-') {
307  return false;
308  }
309 
310  // Transform --foo to -foo
311  if (key.length() > 1 && key[1] == '-') {
312  key.erase(0, 1);
313  }
314  return true;
315 }
316 
317 bool ArgsManager::ParseParameters(int argc, const char *const argv[],
318  std::string &error) {
319  LOCK(cs_args);
320  m_settings.command_line_options.clear();
321 
322  for (int i = 1; i < argc; i++) {
323  std::string key(argv[i]);
324 
325 #ifdef MAC_OSX
326  // At the first time when a user gets the "App downloaded from the
327  // internet" warning, and clicks the Open button, macOS passes
328  // a unique process serial number (PSN) as -psn_... command-line
329  // argument, which we filter out.
330  if (key.substr(0, 5) == "-psn_") {
331  continue;
332  }
333 #endif
334 
335  if (key == "-") {
336  // bitcoin-tx using stdin
337  break;
338  }
339  std::string val;
340  if (!ParseKeyValue(key, val)) {
341  break;
342  }
343 
344  // Transform -foo to foo
345  key.erase(0, 1);
346  std::string section;
347  util::SettingsValue value = InterpretOption(section, key, val);
348  std::optional<unsigned int> flags = GetArgFlags('-' + key);
349 
350  // Unknown command line options and command line options with dot
351  // characters (which are returned from InterpretOption with nonempty
352  // section strings) are not valid.
353  if (!flags || !section.empty()) {
354  error = strprintf("Invalid parameter %s", argv[i]);
355  return false;
356  }
357 
358  if (!CheckValid(key, value, *flags, error)) {
359  return false;
360  }
361 
362  m_settings.command_line_options[key].push_back(value);
363  }
364 
365  // we do not allow -includeconf from command line
366  bool success = true;
367  if (auto *includes =
368  util::FindKey(m_settings.command_line_options, "includeconf")) {
369  for (const auto &include : util::SettingsSpan(*includes)) {
370  error +=
371  "-includeconf cannot be used from commandline; -includeconf=" +
372  include.get_str() + "\n";
373  success = false;
374  }
375  }
376  return success;
377 }
378 
379 std::optional<unsigned int>
380 ArgsManager::GetArgFlags(const std::string &name) const {
381  LOCK(cs_args);
382  for (const auto &arg_map : m_available_args) {
383  const auto search = arg_map.second.find(name);
384  if (search != arg_map.second.end()) {
385  return search->second.m_flags;
386  }
387  }
388  return std::nullopt;
389 }
390 
391 std::vector<std::string> ArgsManager::GetArgs(const std::string &strArg) const {
392  std::vector<std::string> result;
393  for (const util::SettingsValue &value : GetSettingsList(strArg)) {
394  result.push_back(
395  value.isFalse() ? "0" : value.isTrue() ? "1" : value.get_str());
396  }
397  return result;
398 }
399 
400 bool ArgsManager::IsArgSet(const std::string &strArg) const {
401  return !GetSetting(strArg).isNull();
402 }
403 
404 bool ArgsManager::InitSettings(std::string &error) {
405  if (!GetSettingsPath()) {
406  return true; // Do nothing if settings file disabled.
407  }
408 
409  std::vector<std::string> errors;
410  if (!ReadSettingsFile(&errors)) {
411  error = strprintf("Failed loading settings file:\n- %s\n",
412  Join(errors, "\n- "));
413  return false;
414  }
415  if (!WriteSettingsFile(&errors)) {
416  error = strprintf("Failed saving settings file:\n- %s\n",
417  Join(errors, "\n- "));
418  return false;
419  }
420  return true;
421 }
422 
423 bool ArgsManager::GetSettingsPath(fs::path *filepath, bool temp) const {
424  if (IsArgNegated("-settings")) {
425  return false;
426  }
427  if (filepath) {
428  std::string settings = GetArg("-settings", BITCOIN_SETTINGS_FILENAME);
429  *filepath = fs::absolute(temp ? settings + ".tmp" : settings,
430  GetDataDir(/* net_specific= */ true));
431  }
432  return true;
433 }
434 
435 static void SaveErrors(const std::vector<std::string> errors,
436  std::vector<std::string> *error_out) {
437  for (const auto &error : errors) {
438  if (error_out) {
439  error_out->emplace_back(error);
440  } else {
441  LogPrintf("%s\n", error);
442  }
443  }
444 }
445 
446 bool ArgsManager::ReadSettingsFile(std::vector<std::string> *errors) {
447  fs::path path;
448  if (!GetSettingsPath(&path, /* temp= */ false)) {
449  return true; // Do nothing if settings file disabled.
450  }
451 
452  LOCK(cs_args);
453  m_settings.rw_settings.clear();
454  std::vector<std::string> read_errors;
455  if (!util::ReadSettings(path, m_settings.rw_settings, read_errors)) {
456  SaveErrors(read_errors, errors);
457  return false;
458  }
459  for (const auto &setting : m_settings.rw_settings) {
460  std::string section;
461  std::string key = setting.first;
462  // Split setting key into section and argname
463  (void)InterpretOption(section, key, /* value */ {});
464  if (!GetArgFlags('-' + key)) {
465  LogPrintf("Ignoring unknown rw_settings value %s\n", setting.first);
466  }
467  }
468  return true;
469 }
470 
471 bool ArgsManager::WriteSettingsFile(std::vector<std::string> *errors) const {
472  fs::path path, path_tmp;
473  if (!GetSettingsPath(&path, /* temp= */ false) ||
474  !GetSettingsPath(&path_tmp, /* temp= */ true)) {
475  throw std::logic_error("Attempt to write settings file when dynamic "
476  "settings are disabled.");
477  }
478 
479  LOCK(cs_args);
480  std::vector<std::string> write_errors;
481  if (!util::WriteSettings(path_tmp, m_settings.rw_settings, write_errors)) {
482  SaveErrors(write_errors, errors);
483  return false;
484  }
485  if (!RenameOver(path_tmp, path)) {
486  SaveErrors({strprintf("Failed renaming settings file %s to %s\n",
487  path_tmp.string(), path.string())},
488  errors);
489  return false;
490  }
491  return true;
492 }
493 
494 bool ArgsManager::IsArgNegated(const std::string &strArg) const {
495  return GetSetting(strArg).isFalse();
496 }
497 
498 std::string ArgsManager::GetArg(const std::string &strArg,
499  const std::string &strDefault) const {
500  const util::SettingsValue value = GetSetting(strArg);
501  return value.isNull()
502  ? strDefault
503  : value.isFalse() ? "0" : value.isTrue() ? "1" : value.get_str();
504 }
505 
506 int64_t ArgsManager::GetArg(const std::string &strArg, int64_t nDefault) const {
507  const util::SettingsValue value = GetSetting(strArg);
508  return value.isNull()
509  ? nDefault
510  : value.isFalse()
511  ? 0
512  : value.isTrue() ? 1
513  : value.isNum() ? value.get_int64()
514  : atoi64(value.get_str());
515 }
516 
517 bool ArgsManager::GetBoolArg(const std::string &strArg, bool fDefault) const {
518  const util::SettingsValue value = GetSetting(strArg);
519  return value.isNull() ? fDefault
520  : value.isBool() ? value.get_bool()
521  : InterpretBool(value.get_str());
522 }
523 
524 bool ArgsManager::SoftSetArg(const std::string &strArg,
525  const std::string &strValue) {
526  LOCK(cs_args);
527  if (IsArgSet(strArg)) {
528  return false;
529  }
530  ForceSetArg(strArg, strValue);
531  return true;
532 }
533 
534 bool ArgsManager::SoftSetBoolArg(const std::string &strArg, bool fValue) {
535  if (fValue) {
536  return SoftSetArg(strArg, std::string("1"));
537  } else {
538  return SoftSetArg(strArg, std::string("0"));
539  }
540 }
541 
542 void ArgsManager::ForceSetArg(const std::string &strArg,
543  const std::string &strValue) {
544  LOCK(cs_args);
545  m_settings.forced_settings[SettingName(strArg)] = strValue;
546 }
547 
553 void ArgsManager::ForceSetMultiArg(const std::string &strArg,
554  const std::vector<std::string> &values) {
555  LOCK(cs_args);
556  util::SettingsValue value;
557  value.setArray();
558  for (const std::string &s : values) {
559  value.push_back(s);
560  }
561 
562  m_settings.forced_settings[SettingName(strArg)] = value;
563 }
564 
565 void ArgsManager::AddArg(const std::string &name, const std::string &help,
566  unsigned int flags, const OptionsCategory &cat) {
567  // Split arg name from its help param
568  size_t eq_index = name.find('=');
569  if (eq_index == std::string::npos) {
570  eq_index = name.size();
571  }
572  std::string arg_name = name.substr(0, eq_index);
573 
574  LOCK(cs_args);
575  std::map<std::string, Arg> &arg_map = m_available_args[cat];
576  auto ret = arg_map.emplace(
577  arg_name,
578  Arg{name.substr(eq_index, name.size() - eq_index), help, flags});
579  // Make sure an insertion actually happened.
580  assert(ret.second);
581 
583  m_network_only_args.emplace(arg_name);
584  }
585 }
586 
587 void ArgsManager::AddHiddenArgs(const std::vector<std::string> &names) {
588  for (const std::string &name : names) {
590  }
591 }
592 
593 void ArgsManager::ClearForcedArg(const std::string &strArg) {
594  LOCK(cs_args);
595  m_settings.forced_settings.erase(SettingName(strArg));
596 }
597 
598 std::string ArgsManager::GetHelpMessage() const {
599  const bool show_debug = GetBoolArg("-help-debug", false);
600 
601  std::string usage = "";
602  LOCK(cs_args);
603  for (const auto &arg_map : m_available_args) {
604  switch (arg_map.first) {
606  usage += HelpMessageGroup("Options:");
607  break;
609  usage += HelpMessageGroup("Connection options:");
610  break;
612  usage += HelpMessageGroup("ZeroMQ notification options:");
613  break;
615  usage += HelpMessageGroup("Debugging/Testing options:");
616  break;
618  usage += HelpMessageGroup("Node relay options:");
619  break;
621  usage += HelpMessageGroup("Block creation options:");
622  break;
624  usage += HelpMessageGroup("RPC server options:");
625  break;
627  usage += HelpMessageGroup("Wallet options:");
628  break;
630  if (show_debug) {
631  usage +=
632  HelpMessageGroup("Wallet debugging/testing options:");
633  }
634  break;
636  usage += HelpMessageGroup("Chain selection options:");
637  break;
639  usage += HelpMessageGroup("UI Options:");
640  break;
642  usage += HelpMessageGroup("Commands:");
643  break;
645  usage += HelpMessageGroup("Register Commands:");
646  break;
647  default:
648  break;
649  }
650 
651  // When we get to the hidden options, stop
652  if (arg_map.first == OptionsCategory::HIDDEN) {
653  break;
654  }
655 
656  for (const auto &arg : arg_map.second) {
657  if (show_debug || !(arg.second.m_flags & ArgsManager::DEBUG_ONLY)) {
658  std::string name;
659  if (arg.second.m_help_param.empty()) {
660  name = arg.first;
661  } else {
662  name = arg.first + arg.second.m_help_param;
663  }
664  usage += HelpMessageOpt(name, arg.second.m_help_text);
665  }
666  }
667  }
668  return usage;
669 }
670 
671 bool HelpRequested(const ArgsManager &args) {
672  return args.IsArgSet("-?") || args.IsArgSet("-h") ||
673  args.IsArgSet("-help") || args.IsArgSet("-help-debug");
674 }
675 
677  args.AddArg("-?", "Print this help message and exit", false,
679  args.AddHiddenArgs({"-h", "-help"});
680 }
681 
682 static const int screenWidth = 79;
683 static const int optIndent = 2;
684 static const int msgIndent = 7;
685 
686 std::string HelpMessageGroup(const std::string &message) {
687  return std::string(message) + std::string("\n\n");
688 }
689 
690 std::string HelpMessageOpt(const std::string &option,
691  const std::string &message) {
692  return std::string(optIndent, ' ') + std::string(option) +
693  std::string("\n") + std::string(msgIndent, ' ') +
695  std::string("\n\n");
696 }
697 
698 static std::string FormatException(const std::exception *pex,
699  const char *pszThread) {
700 #ifdef WIN32
701  char pszModule[MAX_PATH] = "";
702  GetModuleFileNameA(nullptr, pszModule, sizeof(pszModule));
703 #else
704  const char *pszModule = "bitcoin";
705 #endif
706  if (pex) {
707  return strprintf("EXCEPTION: %s \n%s \n%s in %s \n",
708  typeid(*pex).name(), pex->what(), pszModule,
709  pszThread);
710  } else {
711  return strprintf("UNKNOWN EXCEPTION \n%s in %s \n",
712  pszModule, pszThread);
713  }
714 }
715 
716 void PrintExceptionContinue(const std::exception *pex, const char *pszThread) {
717  std::string message = FormatException(pex, pszThread);
718  LogPrintf("\n\n************************\n%s\n", message);
719  tfm::format(std::cerr, "\n\n************************\n%s\n", message);
720 }
721 
722 fs::path GetDefaultDataDir() {
723 // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
724 // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
725 // Mac: ~/Library/Application Support/Bitcoin
726 // Unix: ~/.bitcoin
727 #ifdef WIN32
728  // Windows
729  return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
730 #else
731  fs::path pathRet;
732  char *pszHome = getenv("HOME");
733  if (pszHome == nullptr || strlen(pszHome) == 0) {
734  pathRet = fs::path("/");
735  } else {
736  pathRet = fs::path(pszHome);
737  }
738 #ifdef MAC_OSX
739  // Mac
740  return pathRet / "Library/Application Support/Bitcoin";
741 #else
742  // Unix
743  return pathRet / ".bitcoin";
744 #endif
745 #endif
746 }
747 
749 static fs::path pathCached;
750 static fs::path pathCachedNetSpecific;
752 
753 const fs::path &GetBlocksDir() {
755  fs::path &path = g_blocks_path_cache_net_specific;
756 
757  // Cache the path to avoid calling fs::create_directories on every call of
758  // this function
759  if (!path.empty()) {
760  return path;
761  }
762 
763  if (gArgs.IsArgSet("-blocksdir")) {
764  path = fs::system_complete(gArgs.GetArg("-blocksdir", ""));
765  if (!fs::is_directory(path)) {
766  path = "";
767  return path;
768  }
769  } else {
770  path = GetDataDir(false);
771  }
772 
773  path /= BaseParams().DataDir();
774  path /= "blocks";
775  fs::create_directories(path);
776  return path;
777 }
778 
779 const fs::path &GetDataDir(bool fNetSpecific) {
781  fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
782 
783  // Cache the path to avoid calling fs::create_directories on every call of
784  // this function
785  if (!path.empty()) {
786  return path;
787  }
788 
789  std::string datadir = gArgs.GetArg("-datadir", "");
790  if (!datadir.empty()) {
791  path = fs::system_complete(datadir);
792  if (!fs::is_directory(path)) {
793  path = "";
794  return path;
795  }
796  } else {
797  path = GetDefaultDataDir();
798  }
799 
800  if (fNetSpecific) {
801  path /= BaseParams().DataDir();
802  }
803 
804  if (fs::create_directories(path)) {
805  // This is the first run, create wallets subdirectory too
806  //
807  // TODO: this is an ugly way to create the wallets/ directory and
808  // really shouldn't be done here. Once this is fixed, please
809  // also remove the corresponding line in bitcoind.cpp AppInit.
810  // See more info at:
811  // https://reviews.bitcoinabc.org/D3312
812  fs::create_directories(path / "wallets");
813  }
814 
815  return path;
816 }
817 
819  std::string datadir = gArgs.GetArg("-datadir", "");
820  return datadir.empty() || fs::is_directory(fs::system_complete(datadir));
821 }
822 
825 
826  pathCached = fs::path();
827  pathCachedNetSpecific = fs::path();
829 }
830 
831 fs::path GetConfigFile(const std::string &confPath) {
832  return AbsPathForConfigVal(fs::path(confPath), false);
833 }
834 
835 static bool
836 GetConfigOptions(std::istream &stream, const std::string &filepath,
837  std::string &error,
838  std::vector<std::pair<std::string, std::string>> &options,
839  std::list<SectionInfo> &sections) {
840  std::string str, prefix;
841  std::string::size_type pos;
842  int linenr = 1;
843  while (std::getline(stream, str)) {
844  bool used_hash = false;
845  if ((pos = str.find('#')) != std::string::npos) {
846  str = str.substr(0, pos);
847  used_hash = true;
848  }
849  const static std::string pattern = " \t\r\n";
850  str = TrimString(str, pattern);
851  if (!str.empty()) {
852  if (*str.begin() == '[' && *str.rbegin() == ']') {
853  const std::string section = str.substr(1, str.size() - 2);
854  sections.emplace_back(SectionInfo{section, filepath, linenr});
855  prefix = section + '.';
856  } else if (*str.begin() == '-') {
857  error = strprintf(
858  "parse error on line %i: %s, options in configuration file "
859  "must be specified without leading -",
860  linenr, str);
861  return false;
862  } else if ((pos = str.find('=')) != std::string::npos) {
863  std::string name =
864  prefix + TrimString(str.substr(0, pos), pattern);
865  std::string value = TrimString(str.substr(pos + 1), pattern);
866  if (used_hash &&
867  name.find("rpcpassword") != std::string::npos) {
868  error = strprintf(
869  "parse error on line %i, using # in rpcpassword can be "
870  "ambiguous and should be avoided",
871  linenr);
872  return false;
873  }
874  options.emplace_back(name, value);
875  if ((pos = name.rfind('.')) != std::string::npos &&
876  prefix.length() <= pos) {
877  sections.emplace_back(
878  SectionInfo{name.substr(0, pos), filepath, linenr});
879  }
880  } else {
881  error = strprintf("parse error on line %i: %s", linenr, str);
882  if (str.size() >= 2 && str.substr(0, 2) == "no") {
883  error += strprintf(", if you intended to specify a negated "
884  "option, use %s=1 instead",
885  str);
886  }
887  return false;
888  }
889  }
890  ++linenr;
891  }
892  return true;
893 }
894 
895 bool ArgsManager::ReadConfigStream(std::istream &stream,
896  const std::string &filepath,
897  std::string &error,
898  bool ignore_invalid_keys) {
899  LOCK(cs_args);
900  std::vector<std::pair<std::string, std::string>> options;
901  if (!GetConfigOptions(stream, filepath, error, options,
902  m_config_sections)) {
903  return false;
904  }
905  for (const std::pair<std::string, std::string> &option : options) {
906  std::string section;
907  std::string key = option.first;
908  util::SettingsValue value =
909  InterpretOption(section, key, option.second);
910  std::optional<unsigned int> flags = GetArgFlags('-' + key);
911  if (flags) {
912  if (!CheckValid(key, value, *flags, error)) {
913  return false;
914  }
915  m_settings.ro_config[section][key].push_back(value);
916  } else {
917  if (ignore_invalid_keys) {
918  LogPrintf("Ignoring unknown configuration value %s\n",
919  option.first);
920  } else {
921  error = strprintf("Invalid configuration value %s",
922  option.first.c_str());
923  return false;
924  }
925  }
926  }
927  return true;
928 }
929 
931  bool ignore_invalid_keys) {
932  {
933  LOCK(cs_args);
934  m_settings.ro_config.clear();
935  m_config_sections.clear();
936  }
937 
938  const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME);
939  fsbridge::ifstream stream(GetConfigFile(confPath));
940 
941  // ok to not have a config file
942  if (stream.good()) {
943  if (!ReadConfigStream(stream, confPath, error, ignore_invalid_keys)) {
944  return false;
945  }
946  // `-includeconf` cannot be included in the command line arguments
947  // except as `-noincludeconf` (which indicates that no included conf
948  // file should be used).
949  bool use_conf_file{true};
950  {
951  LOCK(cs_args);
952  if (auto *includes = util::FindKey(m_settings.command_line_options,
953  "includeconf")) {
954  // ParseParameters() fails if a non-negated -includeconf is
955  // passed on the command-line
956  assert(util::SettingsSpan(*includes).last_negated());
957  use_conf_file = false;
958  }
959  }
960  if (use_conf_file) {
961  std::string chain_id = GetChainName();
962  std::vector<std::string> conf_file_names;
963 
964  auto add_includes = [&](const std::string &network,
965  size_t skip = 0) {
966  size_t num_values = 0;
967  LOCK(cs_args);
968  if (auto *section =
969  util::FindKey(m_settings.ro_config, network)) {
970  if (auto *values = util::FindKey(*section, "includeconf")) {
971  for (size_t i = std::max(
972  skip, util::SettingsSpan(*values).negated());
973  i < values->size(); ++i) {
974  conf_file_names.push_back((*values)[i].get_str());
975  }
976  num_values = values->size();
977  }
978  }
979  return num_values;
980  };
981 
982  // We haven't set m_network yet (that happens in SelectParams()), so
983  // manually check for network.includeconf args.
984  const size_t chain_includes = add_includes(chain_id);
985  const size_t default_includes = add_includes({});
986 
987  for (const std::string &conf_file_name : conf_file_names) {
988  fsbridge::ifstream conf_file_stream(
989  GetConfigFile(conf_file_name));
990  if (conf_file_stream.good()) {
991  if (!ReadConfigStream(conf_file_stream, conf_file_name,
992  error, ignore_invalid_keys)) {
993  return false;
994  }
995  LogPrintf("Included configuration file %s\n",
996  conf_file_name);
997  } else {
998  error = "Failed to include configuration file " +
999  conf_file_name;
1000  return false;
1001  }
1002  }
1003 
1004  // Warn about recursive -includeconf
1005  conf_file_names.clear();
1006  add_includes(chain_id, /* skip= */ chain_includes);
1007  add_includes({}, /* skip= */ default_includes);
1008  std::string chain_id_final = GetChainName();
1009  if (chain_id_final != chain_id) {
1010  // Also warn about recursive includeconf for the chain that was
1011  // specified in one of the includeconfs
1012  add_includes(chain_id_final);
1013  }
1014  for (const std::string &conf_file_name : conf_file_names) {
1015  tfm::format(std::cerr,
1016  "warning: -includeconf cannot be used from "
1017  "included files; ignoring -includeconf=%s\n",
1018  conf_file_name);
1019  }
1020  }
1021  }
1022 
1023  // If datadir is changed in .conf file:
1025  if (!CheckDataDirOption()) {
1026  error = strprintf("specified data directory \"%s\" does not exist.",
1027  GetArg("-datadir", "").c_str());
1028  return false;
1029  }
1030  return true;
1031 }
1032 
1033 std::string ArgsManager::GetChainName() const {
1034  auto get_net = [&](const std::string &arg) {
1035  LOCK(cs_args);
1036  util::SettingsValue value =
1037  util::GetSetting(m_settings, /* section= */ "", SettingName(arg),
1038  /* ignore_default_section_config= */ false,
1039  /* get_chain_name= */ true);
1040  return value.isNull() ? false
1041  : value.isBool() ? value.get_bool()
1042  : InterpretBool(value.get_str());
1043  };
1044 
1045  const bool fRegTest = get_net("-regtest");
1046  const bool fTestNet = get_net("-testnet");
1047  const bool is_chain_arg_set = IsArgSet("-chain");
1048 
1049  if (int(is_chain_arg_set) + int(fRegTest) + int(fTestNet) > 1) {
1050  throw std::runtime_error("Invalid combination of -regtest, -testnet "
1051  "and -chain. Can use at most one.");
1052  }
1053  if (fRegTest) {
1055  }
1056  if (fTestNet) {
1058  }
1059  return GetArg("-chain", CBaseChainParams::MAIN);
1060 }
1061 
1062 bool ArgsManager::UseDefaultSection(const std::string &arg) const {
1063  return m_network == CBaseChainParams::MAIN ||
1064  m_network_only_args.count(arg) == 0;
1065 }
1066 
1067 util::SettingsValue ArgsManager::GetSetting(const std::string &arg) const {
1068  LOCK(cs_args);
1069  return util::GetSetting(m_settings, m_network, SettingName(arg),
1070  !UseDefaultSection(arg),
1071  /* get_chain_name= */ false);
1072 }
1073 
1074 std::vector<util::SettingsValue>
1075 ArgsManager::GetSettingsList(const std::string &arg) const {
1076  LOCK(cs_args);
1077  return util::GetSettingsList(m_settings, m_network, SettingName(arg),
1078  !UseDefaultSection(arg));
1079 }
1080 
1082  const std::string &prefix, const std::string &section,
1083  const std::map<std::string, std::vector<util::SettingsValue>> &args) const {
1084  std::string section_str = section.empty() ? "" : "[" + section + "] ";
1085  for (const auto &arg : args) {
1086  for (const auto &value : arg.second) {
1087  std::optional<unsigned int> flags = GetArgFlags('-' + arg.first);
1088  if (flags) {
1089  std::string value_str =
1090  (*flags & SENSITIVE) ? "****" : value.write();
1091  LogPrintf("%s %s%s=%s\n", prefix, section_str, arg.first,
1092  value_str);
1093  }
1094  }
1095  }
1096 }
1097 
1098 void ArgsManager::LogArgs() const {
1099  LOCK(cs_args);
1100  for (const auto &section : m_settings.ro_config) {
1101  logArgsPrefix("Config file arg:", section.first, section.second);
1102  }
1103  for (const auto &setting : m_settings.rw_settings) {
1104  LogPrintf("Setting file arg: %s = %s\n", setting.first,
1105  setting.second.write());
1106  }
1107  logArgsPrefix("Command-line arg:", "", m_settings.command_line_options);
1108 }
1109 
1110 bool RenameOver(fs::path src, fs::path dest) {
1111 #ifdef WIN32
1112  return MoveFileExA(src.string().c_str(), dest.string().c_str(),
1113  MOVEFILE_REPLACE_EXISTING) != 0;
1114 #else
1115  int rc = std::rename(src.string().c_str(), dest.string().c_str());
1116  return (rc == 0);
1117 #endif /* WIN32 */
1118 }
1119 
1125 bool TryCreateDirectories(const fs::path &p) {
1126  try {
1127  return fs::create_directories(p);
1128  } catch (const fs::filesystem_error &) {
1129  if (!fs::exists(p) || !fs::is_directory(p)) {
1130  throw;
1131  }
1132  }
1133 
1134  // create_directory didn't create the directory, it had to have existed
1135  // already.
1136  return false;
1137 }
1138 
1139 bool FileCommit(FILE *file) {
1140  // harmless if redundantly called
1141  if (fflush(file) != 0) {
1142  LogPrintf("%s: fflush failed: %d\n", __func__, errno);
1143  return false;
1144  }
1145 #ifdef WIN32
1146  HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
1147  if (FlushFileBuffers(hFile) == 0) {
1148  LogPrintf("%s: FlushFileBuffers failed: %d\n", __func__,
1149  GetLastError());
1150  return false;
1151  }
1152 #else
1153 #if defined(HAVE_FDATASYNC)
1154  // Ignore EINVAL for filesystems that don't support sync
1155  if (fdatasync(fileno(file)) != 0 && errno != EINVAL) {
1156  LogPrintf("%s: fdatasync failed: %d\n", __func__, errno);
1157  return false;
1158  }
1159 #elif defined(MAC_OSX) && defined(F_FULLFSYNC)
1160  // Manpage says "value other than -1" is returned on success
1161  if (fcntl(fileno(file), F_FULLFSYNC, 0) == -1) {
1162  LogPrintf("%s: fcntl F_FULLFSYNC failed: %d\n", __func__, errno);
1163  return false;
1164  }
1165 #else
1166  if (fsync(fileno(file)) != 0 && errno != EINVAL) {
1167  LogPrintf("%s: fsync failed: %d\n", __func__, errno);
1168  return false;
1169  }
1170 #endif
1171 #endif
1172  return true;
1173 }
1174 
1175 bool TruncateFile(FILE *file, unsigned int length) {
1176 #if defined(WIN32)
1177  return _chsize(_fileno(file), length) == 0;
1178 #else
1179  return ftruncate(fileno(file), length) == 0;
1180 #endif
1181 }
1182 
1188 int RaiseFileDescriptorLimit(int nMinFD) {
1189 #if defined(WIN32)
1190  return 8192;
1191 #else
1192  struct rlimit limitFD;
1193  if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
1194  if (limitFD.rlim_cur < (rlim_t)nMinFD) {
1195  limitFD.rlim_cur = nMinFD;
1196  if (limitFD.rlim_cur > limitFD.rlim_max) {
1197  limitFD.rlim_cur = limitFD.rlim_max;
1198  }
1199  setrlimit(RLIMIT_NOFILE, &limitFD);
1200  getrlimit(RLIMIT_NOFILE, &limitFD);
1201  }
1202  return limitFD.rlim_cur;
1203  }
1204  // getrlimit failed, assume it's fine.
1205  return nMinFD;
1206 #endif
1207 }
1208 
1214 void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
1215 #if defined(WIN32)
1216  // Windows-specific version.
1217  HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
1218  LARGE_INTEGER nFileSize;
1219  int64_t nEndPos = (int64_t)offset + length;
1220  nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
1221  nFileSize.u.HighPart = nEndPos >> 32;
1222  SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
1223  SetEndOfFile(hFile);
1224 #elif defined(MAC_OSX)
1225  // OSX specific version
1226  // NOTE: Contrary to other OS versions, the OSX version assumes that
1227  // NOTE: offset is the size of the file.
1228  fstore_t fst;
1229  fst.fst_flags = F_ALLOCATECONTIG;
1230  fst.fst_posmode = F_PEOFPOSMODE;
1231  fst.fst_offset = 0;
1232  // mac os fst_length takes the number of free bytes to allocate,
1233  // not the desired file size
1234  fst.fst_length = length;
1235  fst.fst_bytesalloc = 0;
1236  if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
1237  fst.fst_flags = F_ALLOCATEALL;
1238  fcntl(fileno(file), F_PREALLOCATE, &fst);
1239  }
1240  ftruncate(fileno(file), static_cast<off_t>(offset) + length);
1241 #elif defined(HAVE_POSIX_FALLOCATE)
1242  // Version using posix_fallocate
1243  off_t nEndPos = (off_t)offset + length;
1244  posix_fallocate(fileno(file), 0, nEndPos);
1245 #else
1246  // Fallback version
1247  // TODO: just write one byte per block
1248  static const char buf[65536] = {};
1249  if (fseek(file, offset, SEEK_SET)) {
1250  return;
1251  }
1252  while (length > 0) {
1253  unsigned int now = 65536;
1254  if (length < now) {
1255  now = length;
1256  }
1257  // Allowed to fail; this function is advisory anyway.
1258  fwrite(buf, 1, now, file);
1259  length -= now;
1260  }
1261 #endif
1262 }
1263 
1264 #ifdef WIN32
1265 fs::path GetSpecialFolderPath(int nFolder, bool fCreate) {
1266  WCHAR pszPath[MAX_PATH] = L"";
1267 
1268  if (SHGetSpecialFolderPathW(nullptr, pszPath, nFolder, fCreate)) {
1269  return fs::path(pszPath);
1270  }
1271 
1272  LogPrintf(
1273  "SHGetSpecialFolderPathW() failed, could not obtain requested path.\n");
1274  return fs::path("");
1275 }
1276 #endif
1277 
1278 #ifndef WIN32
1279 std::string ShellEscape(const std::string &arg) {
1280  std::string escaped = arg;
1281  boost::replace_all(escaped, "'", "'\"'\"'");
1282  return "'" + escaped + "'";
1283 }
1284 #endif
1285 
1286 #if defined(HAVE_SYSTEM)
1287 void runCommand(const std::string &strCommand) {
1288  if (strCommand.empty()) {
1289  return;
1290  }
1291 #ifndef WIN32
1292  int nErr = ::system(strCommand.c_str());
1293 #else
1294  int nErr = ::_wsystem(
1295  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>()
1296  .from_bytes(strCommand)
1297  .c_str());
1298 #endif
1299  if (nErr) {
1300  LogPrintf("runCommand error: system(%s) returned %d\n", strCommand,
1301  nErr);
1302  }
1303 }
1304 #endif
1305 
1307 #ifdef HAVE_MALLOPT_ARENA_MAX
1308  // glibc-specific: On 32-bit systems set the number of arenas to 1. By
1309  // default, since glibc 2.10, the C library will create up to two heap
1310  // arenas per core. This is known to cause excessive virtual address space
1311  // usage in our usage. Work around it by setting the maximum number of
1312  // arenas to 1.
1313  if (sizeof(void *) == 4) {
1314  mallopt(M_ARENA_MAX, 1);
1315  }
1316 #endif
1317 // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale may
1318 // be invalid, in which case the "C.UTF-8" locale is used as fallback.
1319 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && \
1320  !defined(__OpenBSD__)
1321  try {
1322  // Raises a runtime error if current locale is invalid.
1323  std::locale("");
1324  } catch (const std::runtime_error &) {
1325  setenv("LC_ALL", "C.UTF-8", 1);
1326  }
1327 #elif defined(WIN32)
1328  // Set the default input/output charset is utf-8
1329  SetConsoleCP(CP_UTF8);
1330  SetConsoleOutputCP(CP_UTF8);
1331 #endif
1332  // The path locale is lazy initialized and to avoid deinitialization errors
1333  // in multithreading environments, it is set explicitly by the main thread.
1334  // A dummy locale is used to extract the internal default locale, used by
1335  // fs::path, which is then used to explicitly imbue the path.
1336  std::locale loc = fs::path::imbue(std::locale::classic());
1337 #ifndef WIN32
1338  fs::path::imbue(loc);
1339 #else
1340  fs::path::imbue(std::locale(loc, new std::codecvt_utf8_utf16<wchar_t>()));
1341 #endif
1342 }
1343 
1345 #ifdef WIN32
1346  // Initialize Windows Sockets.
1347  WSADATA wsadata;
1348  int ret = WSAStartup(MAKEWORD(2, 2), &wsadata);
1349  if (ret != NO_ERROR || LOBYTE(wsadata.wVersion) != 2 ||
1350  HIBYTE(wsadata.wVersion) != 2) {
1351  return false;
1352  }
1353 #endif
1354  return true;
1355 }
1356 
1358  return std::thread::hardware_concurrency();
1359 }
1360 
1361 std::string CopyrightHolders(const std::string &strPrefix) {
1362  return strPrefix + strprintf(_(COPYRIGHT_HOLDERS).translated,
1363  COPYRIGHT_HOLDERS_SUBSTITUTION);
1364 }
1365 
1366 // Obtain the application startup time (used for uptime calculation)
1367 int64_t GetStartupTime() {
1368  return nStartupTime;
1369 }
1370 
1371 fs::path AbsPathForConfigVal(const fs::path &path, bool net_specific) {
1372  if (path.is_absolute()) {
1373  return path;
1374  }
1375  return fs::absolute(path, GetDataDir(net_specific));
1376 }
1377 
1379 #ifdef SCHED_BATCH
1380  const static sched_param param{};
1381  const int rc = pthread_setschedparam(pthread_self(), SCHED_BATCH, &param);
1382  if (rc != 0) {
1383  LogPrintf("Failed to pthread_setschedparam: %s\n", strerror(rc));
1384  }
1385 #endif
1386 }
1387 
1388 namespace util {
1389 #ifdef WIN32
1390 WinCmdLineArgs::WinCmdLineArgs() {
1391  wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
1392  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_cvt;
1393  argv = new char *[argc];
1394  args.resize(argc);
1395  for (int i = 0; i < argc; i++) {
1396  args[i] = utf8_cvt.to_bytes(wargv[i]);
1397  argv[i] = &*args[i].begin();
1398  }
1399  LocalFree(wargv);
1400 }
1401 
1402 WinCmdLineArgs::~WinCmdLineArgs() {
1403  delete[] argv;
1404 }
1405 
1406 std::pair<int, char **> WinCmdLineArgs::get() {
1407  return std::make_pair(argc, argv);
1408 }
1409 #endif
1410 } // namespace util
CopyrightHolders
std::string CopyrightHolders(const std::string &strPrefix)
Definition: system.cpp:1361
util::WriteSettings
bool WriteSettings(const fs::path &path, const std::map< std::string, SettingsValue > &values, std::vector< std::string > &errors)
Write settings file.
Definition: settings.cpp:110
ArgsManager::LogArgs
void LogArgs() const
Log the config file options and the command line arguments, useful for troubleshooting.
Definition: system.cpp:1098
atoi64
int64_t atoi64(const std::string &str)
Definition: strencodings.cpp:469
msgIndent
static const int msgIndent
Definition: system.cpp:684
DirIsWritable
bool DirIsWritable(const fs::path &directory)
Definition: system.cpp:126
UniValue::isBool
bool isBool() const
Definition: univalue.h:92
ArgsManager::GetBoolArg
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:517
util::SettingsSpan::negated
size_t negated() const
Number of negated values.
Definition: settings.cpp:278
ArgsManager::AddHiddenArgs
void AddHiddenArgs(const std::vector< std::string > &args)
Add many hidden arguments.
Definition: system.cpp:587
_
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:55
fsbridge::ifstream
fs::ifstream ifstream
Definition: fs.h:98
SaveErrors
static void SaveErrors(const std::vector< std::string > errors, std::vector< std::string > *error_out)
Definition: system.cpp:435
GetConfigFile
fs::path GetConfigFile(const std::string &confPath)
Definition: system.cpp:831
GetDataDir
const fs::path & GetDataDir(bool fNetSpecific)
Definition: system.cpp:779
AbsPathForConfigVal
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:1371
UniValue::get_bool
bool get_bool() const
Definition: univalue_get.cpp:91
tinyformat::format
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:1111
ArgsManager::GetArgFlags
std::optional< unsigned int > GetArgFlags(const std::string &name) const
Return Flags for known arg.
Definition: system.cpp:380
InterpretBool
static bool InterpretBool(const std::string &strValue)
Interpret a string argument as a boolean.
Definition: system.cpp:171
OptionsCategory::RPC
@ RPC
fsbridge::fopen
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:24
flags
int flags
Definition: bitcoin-tx.cpp:532
ArgsManager::GetSetting
util::SettingsValue GetSetting(const std::string &arg) const
Get setting value.
Definition: system.cpp:1067
CheckDataDirOption
bool CheckDataDirOption()
Definition: system.cpp:818
ArgsManager::UseDefaultSection
bool UseDefaultSection(const std::string &arg) const EXCLUSIVE_LOCKS_REQUIRED(cs_args)
Returns true if settings values from the default section should be used, depending on the current net...
Definition: system.cpp:1062
SetupHelpOptions
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
Definition: system.cpp:676
ArgsManager::ALLOW_ANY
@ ALLOW_ANY
Definition: system.h:159
ArgsManager::SoftSetBoolArg
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Definition: system.cpp:534
help
static RPCHelpMan help()
Definition: server.cpp:177
sync.h
util::SettingsSpan::last_negated
bool last_negated() const
True if the last value is negated.
Definition: settings.cpp:275
ArgsManager::GetHelpMessage
std::string GetHelpMessage() const
Get the help string.
Definition: system.cpp:598
string.h
SetupEnvironment
void SetupEnvironment()
Definition: system.cpp:1306
atoi
int atoi(const std::string &str)
Definition: strencodings.cpp:477
HelpMessageOpt
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:690
ReleaseDirectoryLocks
void ReleaseDirectoryLocks()
Release all directory locks.
Definition: system.cpp:121
chainparamsbase.h
ArgsManager::GetChainName
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Definition: system.cpp:1033
ArgsManager::IsArgSet
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:400
RenameOver
bool RenameOver(fs::path src, fs::path dest)
Definition: system.cpp:1110
CBaseChainParams::TESTNET
static const std::string TESTNET
Definition: chainparamsbase.h:22
GetStartupTime
int64_t GetStartupTime()
Server/client environment: argument handling, config file parsing, thread wrappers,...
Definition: system.cpp:1367
UnlockDirectory
void UnlockDirectory(const fs::path &directory, const std::string &lockfile_name)
Definition: system.cpp:115
GetTime
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: time.cpp:27
optIndent
static const int optIndent
Definition: system.cpp:683
AnnotatedMixin< std::mutex >
ArgsManager::InitSettings
bool InitSettings(std::string &error)
Read and update settings file with saved settings.
Definition: system.cpp:404
SetupNetworking
bool SetupNetworking()
Definition: system.cpp:1344
OptionsCategory::CONNECTION
@ CONNECTION
UniValue::isNull
bool isNull() const
Definition: univalue.h:89
ScheduleBatchPriority
void ScheduleBatchPriority()
On platforms that support it, tell the kernel the calling thread is CPU-intensive and non-interactive...
Definition: system.cpp:1378
UniValue::isNum
bool isNum() const
Definition: univalue.h:94
TruncateFile
bool TruncateFile(FILE *file, unsigned int length)
Definition: system.cpp:1175
UniValue
Definition: univalue.h:23
pathCached
static fs::path pathCached
Definition: system.cpp:749
ArgsManager::~ArgsManager
~ArgsManager()
Definition: system.cpp:247
ShellEscape
std::string ShellEscape(const std::string &arg)
Definition: system.cpp:1279
CBaseChainParams::DataDir
const std::string & DataDir() const
Definition: chainparamsbase.h:25
ArgsManager::Arg
Definition: system.h:172
prefix
const char * prefix
Definition: rest.cpp:772
UniValue::isFalse
bool isFalse() const
Definition: univalue.h:91
UniValue::get_str
const std::string & get_str() const
Definition: univalue_get.cpp:98
util::ReadSettings
bool ReadSettings(const fs::path &path, std::map< std::string, SettingsValue > &values, std::vector< std::string > &errors)
Read settings file.
Definition: settings.cpp:61
HelpRequested
bool HelpRequested(const ArgsManager &args)
Definition: system.cpp:671
strencodings.h
ArgsManager::cs_args
RecursiveMutex cs_args
Definition: system.h:178
BITCOIN_SETTINGS_FILENAME
const char *const BITCOIN_SETTINGS_FILENAME
Definition: system.cpp:73
UniValue::get_int64
int64_t get_int64() const
Definition: univalue_get.cpp:115
ArgsManager::GetSettingsPath
bool GetSettingsPath(fs::path *filepath=nullptr, bool temp=false) const
Get settings file path, or return false if read-write settings were disabled with -nosettings.
Definition: system.cpp:423
OptionsCategory::HIDDEN
@ HIDDEN
nStartupTime
const int64_t nStartupTime
Definition: system.cpp:70
AllocateFileRange
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:1214
OptionsCategory::NODE_RELAY
@ NODE_RELAY
InterpretOption
static util::SettingsValue InterpretOption(std::string &section, std::string &key, const std::string &value)
Interpret -nofoo as if the user supplied -foo=0.
Definition: system.cpp:202
ArgsManager::ClearForcedArg
void ClearForcedArg(const std::string &strArg)
Remove a forced arg setting, used only in testing.
Definition: system.cpp:593
GetDefaultDataDir
fs::path GetDefaultDataDir()
Definition: system.cpp:722
ArgsManager::ALLOW_BOOL
@ ALLOW_BOOL
Definition: system.h:156
ArgsManager::SENSITIVE
@ SENSITIVE
Definition: system.h:168
ArgsManager::SoftSetArg
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn't already have a value.
Definition: system.cpp:524
GetConfigOptions
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:836
ArgsManager::DEBUG_ONLY
@ DEBUG_ONLY
Definition: system.h:160
ArgsManager::AddArg
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: system.cpp:565
ArgsManager::WriteSettingsFile
bool WriteSettingsFile(std::vector< std::string > *errors=nullptr) const
Write settings file.
Definition: system.cpp:471
univalue.h
CheckValid
static bool CheckValid(const std::string &key, const util::SettingsValue &val, unsigned int flags, std::string &error)
Check settings value validity according to flags.
Definition: system.cpp:233
CBaseChainParams::REGTEST
static const std::string REGTEST
Definition: chainparamsbase.h:23
GUARDED_BY
static std::map< std::string, std::unique_ptr< fsbridge::FileLock > > dir_locks GUARDED_BY(cs_dir_locks)
A map that contains all the currently held directory locks.
ArgsManager::GetUnsuitableSectionOnlyArgs
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:249
CheckDiskSpace
bool CheckDiskSpace(const fs::path &dir, uint64_t additional_bytes)
Definition: system.cpp:140
ArgsManager::ForceSetArg
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: system.cpp:542
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:498
OptionsCategory::OPTIONS
@ OPTIONS
ArgsManager::ArgsManager
ArgsManager()
Definition: system.cpp:246
ArgsManager::ParseParameters
NODISCARD bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: system.cpp:317
ArgsManager::ReadConfigFiles
NODISCARD bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
Definition: system.cpp:930
GetNumCores
int GetNumCores()
Return the number of cores available on the current system.
Definition: system.cpp:1357
screenWidth
static const int screenWidth
Definition: system.cpp:682
GetFileSize
std::streampos GetFileSize(const char *path, std::streamsize max)
Get the size of a file by scanning it.
Definition: system.cpp:148
ArgsManager::ReadConfigStream
NODISCARD bool ReadConfigStream(std::istream &stream, const std::string &filepath, std::string &error, bool ignore_invalid_keys=false)
Definition: system.cpp:895
SectionInfo::m_name
std::string m_name
Definition: system.h:147
CBaseChainParams::MAIN
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
Definition: chainparamsbase.h:21
g_blocks_path_cache_net_specific
static fs::path g_blocks_path_cache_net_specific
Definition: system.cpp:748
OptionsCategory
OptionsCategory
Definition: system.h:124
OptionsCategory::ZMQ
@ ZMQ
name
const char * name
Definition: rest.cpp:43
OptionsCategory::BLOCK_CREATION
@ BLOCK_CREATION
ArgsManager::ReadSettingsFile
bool ReadSettingsFile(std::vector< std::string > *errors=nullptr)
Read settings file.
Definition: system.cpp:446
ArgsManager::SelectConfigNetwork
void SelectConfigNetwork(const std::string &network)
Select the network in use.
Definition: system.cpp:288
system.h
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
ArgsManager::GetSettingsList
std::vector< util::SettingsValue > GetSettingsList(const std::string &arg) const
Get list of setting values.
Definition: system.cpp:1075
Join
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Definition: string.h:36
ArgsManager::IsArgNegated
bool IsArgNegated(const std::string &strArg) const
Return true if the argument was originally passed as a negated option, i.e.
Definition: system.cpp:494
SectionInfo
Definition: system.h:146
SettingName
static std::string SettingName(const std::string &arg)
Definition: system.cpp:178
HelpMessageGroup
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
Definition: system.cpp:686
ArgsManager
Definition: system.h:152
util::FindKey
auto FindKey(Map &&map, Key &&key) -> decltype(&map.at(key))
Map lookup helper.
Definition: settings.h:110
translation.h
BaseParams
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
Definition: chainparamsbase.cpp:36
OptionsCategory::WALLET_DEBUG_TEST
@ WALLET_DEBUG_TEST
UniValue::isTrue
bool isTrue() const
Definition: univalue.h:90
LOCK
#define LOCK(cs)
Definition: sync.h:241
ArgsManager::ForceSetMultiArg
void ForceSetMultiArg(const std::string &strArg, const std::vector< std::string > &values)
This function is only used for testing purpose so so we should not worry about element uniqueness and...
Definition: system.cpp:553
gArgs
ArgsManager gArgs
Definition: system.cpp:75
FileCommit
bool FileCommit(FILE *file)
Definition: system.cpp:1139
util::OnlyHasDefaultSectionSetting
bool OnlyHasDefaultSectionSetting(const Settings &settings, const std::string &section, const std::string &name)
Return true if a setting is set in the default config file section, and not overridden by a higher pr...
Definition: settings.cpp:243
ArgsManager::logArgsPrefix
void logArgsPrefix(const std::string &prefix, const std::string &section, const std::map< std::string, std::vector< util::SettingsValue >> &args) const
Definition: system.cpp:1081
OptionsCategory::WALLET
@ WALLET
util::GetSetting
SettingsValue GetSetting(const Settings &settings, const std::string &section, const std::string &name, bool ignore_default_section_config, bool get_chain_name)
Get settings value from combined sources: forced settings, command line arguments,...
Definition: settings.cpp:130
UniValue::push_back
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
ArgsManager::GetUnrecognizedSections
const std::list< SectionInfo > GetUnrecognizedSections() const
Log warnings for unrecognized section names in the config file.
Definition: system.cpp:273
ClearDatadirCache
void ClearDatadirCache()
Tests only.
Definition: system.cpp:823
GetBlocksDir
const fs::path & GetBlocksDir()
Definition: system.cpp:753
OptionsCategory::DEBUG_TEST
@ DEBUG_TEST
cs_dir_locks
static Mutex cs_dir_locks
Mutex to protect dir_locks.
Definition: system.cpp:78
BITCOIN_CONF_FILENAME
const char *const BITCOIN_CONF_FILENAME
Definition: system.cpp:72
ParseKeyValue
bool ParseKeyValue(std::string &key, std::string &val)
Definition: system.cpp:293
FormatException
static std::string FormatException(const std::exception *pex, const char *pszThread)
Definition: system.cpp:698
TrimString
NODISCARD std::string TrimString(const std::string &str, const std::string &pattern=" \f\n\r\t\v")
Definition: string.h:19
OptionsCategory::COMMANDS
@ COMMANDS
OptionsCategory::REGISTER_COMMANDS
@ REGISTER_COMMANDS
TryCreateDirectories
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by Boost's create_directories if the requested directory exists.
Definition: system.cpp:1125
ArgsManager::GetArgs
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: system.cpp:391
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:48
util::GetSettingsList
std::vector< SettingsValue > GetSettingsList(const Settings &settings, const std::string &section, const std::string &name, bool ignore_default_section_config)
Get combined setting value similar to GetSetting(), except if setting was specified multiple times,...
Definition: settings.cpp:191
ArgsManager::NETWORK_ONLY
@ NETWORK_ONLY
Definition: system.h:166
OptionsCategory::CHAINPARAMS
@ CHAINPARAMS
csPathCached
static RecursiveMutex csPathCached
Definition: system.cpp:751
OptionsCategory::GUI
@ GUI
util::SettingsSpan
Accessor for list of settings that skips negated values when iterated over.
Definition: settings.h:86
MAX_PATH
#define MAX_PATH
Definition: compat.h:65
util
Definition: httprpc.h:13
LockDirectory
bool LockDirectory(const fs::path &directory, const std::string lockfile_name, bool probe_only)
Definition: system.cpp:87
pathCachedNetSpecific
static fs::path pathCachedNetSpecific
Definition: system.cpp:750
LogPrintf
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:175
RaiseFileDescriptorLimit
int RaiseFileDescriptorLimit(int nMinFD)
This function tries to raise the file descriptor limit to the requested number.
Definition: system.cpp:1188
PrintExceptionContinue
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
Definition: system.cpp:716
FormatParagraph
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.
Definition: strencodings.cpp:429
UniValue::setArray
bool setArray()
Definition: univalue.cpp:94
ToLower
std::string ToLower(const std::string &str)
Returns the lowercase equivalent of the given string.
Definition: strencodings.cpp:632