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