Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2021 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 : : /**
# 7 : : * Server/client environment: argument handling, config file parsing,
# 8 : : * thread wrappers, startup time
# 9 : : */
# 10 : : #ifndef BITCOIN_UTIL_SYSTEM_H
# 11 : : #define BITCOIN_UTIL_SYSTEM_H
# 12 : :
# 13 : : #if defined(HAVE_CONFIG_H)
# 14 : : #include <config/bitcoin-config.h>
# 15 : : #endif
# 16 : :
# 17 : : #include <attributes.h>
# 18 : : #include <compat.h>
# 19 : : #include <compat/assumptions.h>
# 20 : : #include <fs.h>
# 21 : : #include <logging.h>
# 22 : : #include <sync.h>
# 23 : : #include <tinyformat.h>
# 24 : : #include <util/settings.h>
# 25 : : #include <util/time.h>
# 26 : :
# 27 : : #include <any>
# 28 : : #include <exception>
# 29 : : #include <map>
# 30 : : #include <optional>
# 31 : : #include <set>
# 32 : : #include <stdint.h>
# 33 : : #include <string>
# 34 : : #include <utility>
# 35 : : #include <vector>
# 36 : :
# 37 : : class UniValue;
# 38 : :
# 39 : : // Application startup time (used for uptime calculation)
# 40 : : int64_t GetStartupTime();
# 41 : :
# 42 : : extern const char * const BITCOIN_CONF_FILENAME;
# 43 : : extern const char * const BITCOIN_SETTINGS_FILENAME;
# 44 : :
# 45 : : void SetupEnvironment();
# 46 : : bool SetupNetworking();
# 47 : :
# 48 : : template<typename... Args>
# 49 : : bool error(const char* fmt, const Args&... args)
# 50 : 8861 : {
# 51 : 8861 : LogPrintf("ERROR: %s\n", tfm::format(fmt, args...));
# 52 : 8861 : return false;
# 53 : 8861 : }
# 54 : :
# 55 : : void PrintExceptionContinue(const std::exception *pex, const char* pszThread);
# 56 : :
# 57 : : /**
# 58 : : * Ensure file contents are fully committed to disk, using a platform-specific
# 59 : : * feature analogous to fsync().
# 60 : : */
# 61 : : bool FileCommit(FILE *file);
# 62 : :
# 63 : : /**
# 64 : : * Sync directory contents. This is required on some environments to ensure that
# 65 : : * newly created files are committed to disk.
# 66 : : */
# 67 : : void DirectoryCommit(const fs::path &dirname);
# 68 : :
# 69 : : bool TruncateFile(FILE *file, unsigned int length);
# 70 : : int RaiseFileDescriptorLimit(int nMinFD);
# 71 : : void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
# 72 : :
# 73 : : /**
# 74 : : * Rename src to dest.
# 75 : : * @return true if the rename was successful.
# 76 : : */
# 77 : : [[nodiscard]] bool RenameOver(fs::path src, fs::path dest);
# 78 : :
# 79 : : bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false);
# 80 : : void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name);
# 81 : : bool DirIsWritable(const fs::path& directory);
# 82 : : bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes = 0);
# 83 : :
# 84 : : /** Get the size of a file by scanning it.
# 85 : : *
# 86 : : * @param[in] path The file path
# 87 : : * @param[in] max Stop seeking beyond this limit
# 88 : : * @return The file size or max
# 89 : : */
# 90 : : std::streampos GetFileSize(const char* path, std::streamsize max = std::numeric_limits<std::streamsize>::max());
# 91 : :
# 92 : : /** Release all directory locks. This is used for unit testing only, at runtime
# 93 : : * the global destructor will take care of the locks.
# 94 : : */
# 95 : : void ReleaseDirectoryLocks();
# 96 : :
# 97 : : bool TryCreateDirectories(const fs::path& p);
# 98 : : fs::path GetDefaultDataDir();
# 99 : : // Return true if -datadir option points to a valid directory or is not specified.
# 100 : : bool CheckDataDirOption();
# 101 : : fs::path GetConfigFile(const std::string& confPath);
# 102 : : #ifdef WIN32
# 103 : : fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
# 104 : : #endif
# 105 : : #ifndef WIN32
# 106 : : std::string ShellEscape(const std::string& arg);
# 107 : : #endif
# 108 : : #if HAVE_SYSTEM
# 109 : : void runCommand(const std::string& strCommand);
# 110 : : #endif
# 111 : : /**
# 112 : : * Execute a command which returns JSON, and parse the result.
# 113 : : *
# 114 : : * @param str_command The command to execute, including any arguments
# 115 : : * @param str_std_in string to pass to stdin
# 116 : : * @return parsed JSON
# 117 : : */
# 118 : : UniValue RunCommandParseJSON(const std::string& str_command, const std::string& str_std_in="");
# 119 : :
# 120 : : /**
# 121 : : * Most paths passed as configuration arguments are treated as relative to
# 122 : : * the datadir if they are not absolute.
# 123 : : *
# 124 : : * @param path The path to be conditionally prefixed with datadir.
# 125 : : * @param net_specific Use network specific datadir variant
# 126 : : * @return The normalized path.
# 127 : : */
# 128 : : fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific = true);
# 129 : :
# 130 : : inline bool IsSwitchChar(char c)
# 131 : 10340 : {
# 132 : : #ifdef WIN32
# 133 : : return c == '-' || c == '/';
# 134 : : #else
# 135 : 10340 : return c == '-';
# 136 : 10340 : #endif
# 137 : 10340 : }
# 138 : :
# 139 : : enum class OptionsCategory {
# 140 : : OPTIONS,
# 141 : : CONNECTION,
# 142 : : WALLET,
# 143 : : WALLET_DEBUG_TEST,
# 144 : : ZMQ,
# 145 : : DEBUG_TEST,
# 146 : : CHAINPARAMS,
# 147 : : NODE_RELAY,
# 148 : : BLOCK_CREATION,
# 149 : : RPC,
# 150 : : GUI,
# 151 : : COMMANDS,
# 152 : : REGISTER_COMMANDS,
# 153 : :
# 154 : : HIDDEN // Always the last option to avoid printing these in the help
# 155 : : };
# 156 : :
# 157 : : struct SectionInfo
# 158 : : {
# 159 : : std::string m_name;
# 160 : : std::string m_file;
# 161 : : int m_line;
# 162 : : };
# 163 : :
# 164 : : std::string SettingToString(const util::SettingsValue&, const std::string&);
# 165 : : int64_t SettingToInt(const util::SettingsValue&, int64_t);
# 166 : : bool SettingToBool(const util::SettingsValue&, bool);
# 167 : :
# 168 : : class ArgsManager
# 169 : : {
# 170 : : public:
# 171 : : /**
# 172 : : * Flags controlling how config and command line arguments are validated and
# 173 : : * interpreted.
# 174 : : */
# 175 : : enum Flags : uint32_t {
# 176 : : ALLOW_ANY = 0x01, //!< disable validation
# 177 : : // ALLOW_BOOL = 0x02, //!< unimplemented, draft implementation in #16545
# 178 : : // ALLOW_INT = 0x04, //!< unimplemented, draft implementation in #16545
# 179 : : // ALLOW_STRING = 0x08, //!< unimplemented, draft implementation in #16545
# 180 : : // ALLOW_LIST = 0x10, //!< unimplemented, draft implementation in #16545
# 181 : : DISALLOW_NEGATION = 0x20, //!< disallow -nofoo syntax
# 182 : :
# 183 : : DEBUG_ONLY = 0x100,
# 184 : : /* Some options would cause cross-contamination if values for
# 185 : : * mainnet were used while running on regtest/testnet (or vice-versa).
# 186 : : * Setting them as NETWORK_ONLY ensures that sharing a config file
# 187 : : * between mainnet and regtest/testnet won't cause problems due to these
# 188 : : * parameters by accident. */
# 189 : : NETWORK_ONLY = 0x200,
# 190 : : // This argument's value is sensitive (such as a password).
# 191 : : SENSITIVE = 0x400,
# 192 : : COMMAND = 0x800,
# 193 : : };
# 194 : :
# 195 : : protected:
# 196 : : struct Arg
# 197 : : {
# 198 : : std::string m_help_param;
# 199 : : std::string m_help_text;
# 200 : : unsigned int m_flags;
# 201 : : };
# 202 : :
# 203 : : mutable RecursiveMutex cs_args;
# 204 : : util::Settings m_settings GUARDED_BY(cs_args);
# 205 : : std::vector<std::string> m_command GUARDED_BY(cs_args);
# 206 : : std::string m_network GUARDED_BY(cs_args);
# 207 : : std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
# 208 : : std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
# 209 : : bool m_accept_any_command GUARDED_BY(cs_args){true};
# 210 : : std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
# 211 : : mutable fs::path m_cached_blocks_path GUARDED_BY(cs_args);
# 212 : : mutable fs::path m_cached_datadir_path GUARDED_BY(cs_args);
# 213 : : mutable fs::path m_cached_network_datadir_path GUARDED_BY(cs_args);
# 214 : :
# 215 : : [[nodiscard]] bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false);
# 216 : :
# 217 : : /**
# 218 : : * Returns true if settings values from the default section should be used,
# 219 : : * depending on the current network and whether the setting is
# 220 : : * network-specific.
# 221 : : */
# 222 : : bool UseDefaultSection(const std::string& arg) const EXCLUSIVE_LOCKS_REQUIRED(cs_args);
# 223 : :
# 224 : : public:
# 225 : : /**
# 226 : : * Get setting value.
# 227 : : *
# 228 : : * Result will be null if setting was unset, true if "-setting" argument was passed
# 229 : : * false if "-nosetting" argument was passed, and a string if a "-setting=value"
# 230 : : * argument was passed.
# 231 : : */
# 232 : : util::SettingsValue GetSetting(const std::string& arg) const;
# 233 : :
# 234 : : /**
# 235 : : * Get list of setting values.
# 236 : : */
# 237 : : std::vector<util::SettingsValue> GetSettingsList(const std::string& arg) const;
# 238 : :
# 239 : : ArgsManager();
# 240 : : ~ArgsManager();
# 241 : :
# 242 : : /**
# 243 : : * Select the network in use
# 244 : : */
# 245 : : void SelectConfigNetwork(const std::string& network);
# 246 : :
# 247 : : [[nodiscard]] bool ParseParameters(int argc, const char* const argv[], std::string& error);
# 248 : : [[nodiscard]] bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
# 249 : :
# 250 : : /**
# 251 : : * Log warnings for options in m_section_only_args when
# 252 : : * they are specified in the default section but not overridden
# 253 : : * on the command line or in a network-specific section in the
# 254 : : * config file.
# 255 : : */
# 256 : : const std::set<std::string> GetUnsuitableSectionOnlyArgs() const;
# 257 : :
# 258 : : /**
# 259 : : * Log warnings for unrecognized section names in the config file.
# 260 : : */
# 261 : : const std::list<SectionInfo> GetUnrecognizedSections() const;
# 262 : :
# 263 : : struct Command {
# 264 : : /** The command (if one has been registered with AddCommand), or empty */
# 265 : : std::string command;
# 266 : : /**
# 267 : : * If command is non-empty: Any args that followed it
# 268 : : * If command is empty: The unregistered command and any args that followed it
# 269 : : */
# 270 : : std::vector<std::string> args;
# 271 : : };
# 272 : : /**
# 273 : : * Get the command and command args (returns std::nullopt if no command provided)
# 274 : : */
# 275 : : std::optional<const Command> GetCommand() const;
# 276 : :
# 277 : : /**
# 278 : : * Get blocks directory path
# 279 : : *
# 280 : : * @return Blocks path which is network specific
# 281 : : */
# 282 : : const fs::path& GetBlocksDirPath() const;
# 283 : :
# 284 : : /**
# 285 : : * Get data directory path
# 286 : : *
# 287 : : * @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
# 288 : : * @post Returned directory path is created unless it is empty
# 289 : : */
# 290 : 4890 : const fs::path& GetDataDirBase() const { return GetDataDir(false); }
# 291 : :
# 292 : : /**
# 293 : : * Get data directory path with appended network identifier
# 294 : : *
# 295 : : * @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
# 296 : : * @post Returned directory path is created unless it is empty
# 297 : : */
# 298 : 27838 : const fs::path& GetDataDirNet() const { return GetDataDir(true); }
# 299 : :
# 300 : : /**
# 301 : : * Clear cached directory paths
# 302 : : */
# 303 : : void ClearPathCache();
# 304 : :
# 305 : : /**
# 306 : : * Return a vector of strings of the given argument
# 307 : : *
# 308 : : * @param strArg Argument to get (e.g. "-foo")
# 309 : : * @return command-line arguments
# 310 : : */
# 311 : : std::vector<std::string> GetArgs(const std::string& strArg) const;
# 312 : :
# 313 : : /**
# 314 : : * Return true if the given argument has been manually set
# 315 : : *
# 316 : : * @param strArg Argument to get (e.g. "-foo")
# 317 : : * @return true if the argument has been set
# 318 : : */
# 319 : : bool IsArgSet(const std::string& strArg) const;
# 320 : :
# 321 : : /**
# 322 : : * Return true if the argument was originally passed as a negated option,
# 323 : : * i.e. -nofoo.
# 324 : : *
# 325 : : * @param strArg Argument to get (e.g. "-foo")
# 326 : : * @return true if the argument was passed negated
# 327 : : */
# 328 : : bool IsArgNegated(const std::string& strArg) const;
# 329 : :
# 330 : : /**
# 331 : : * Return string argument or default value
# 332 : : *
# 333 : : * @param strArg Argument to get (e.g. "-foo")
# 334 : : * @param strDefault (e.g. "1")
# 335 : : * @return command-line argument or default value
# 336 : : */
# 337 : : std::string GetArg(const std::string& strArg, const std::string& strDefault) const;
# 338 : :
# 339 : : /**
# 340 : : * Return path argument or default value
# 341 : : *
# 342 : : * @param arg Argument to get a path from (e.g., "-datadir", "-blocksdir" or "-walletdir")
# 343 : : * @param default_value Optional default value to return instead of the empty path.
# 344 : : * @return normalized path if argument is set, with redundant "." and ".."
# 345 : : * path components and trailing separators removed (see patharg unit test
# 346 : : * for examples or implementation for details). If argument is empty or not
# 347 : : * set, default_value is returned unchanged.
# 348 : : */
# 349 : : fs::path GetPathArg(std::string arg, const fs::path& default_value = {}) const;
# 350 : :
# 351 : : /**
# 352 : : * Return integer argument or default value
# 353 : : *
# 354 : : * @param strArg Argument to get (e.g. "-foo")
# 355 : : * @param nDefault (e.g. 1)
# 356 : : * @return command-line argument (0 if invalid number) or default value
# 357 : : */
# 358 : : int64_t GetIntArg(const std::string& strArg, int64_t nDefault) const;
# 359 : :
# 360 : : /**
# 361 : : * Return boolean argument or default value
# 362 : : *
# 363 : : * @param strArg Argument to get (e.g. "-foo")
# 364 : : * @param fDefault (true or false)
# 365 : : * @return command-line argument or default value
# 366 : : */
# 367 : : bool GetBoolArg(const std::string& strArg, bool fDefault) const;
# 368 : :
# 369 : : /**
# 370 : : * Set an argument if it doesn't already have a value
# 371 : : *
# 372 : : * @param strArg Argument to set (e.g. "-foo")
# 373 : : * @param strValue Value (e.g. "1")
# 374 : : * @return true if argument gets set, false if it already had a value
# 375 : : */
# 376 : : bool SoftSetArg(const std::string& strArg, const std::string& strValue);
# 377 : :
# 378 : : /**
# 379 : : * Set a boolean argument if it doesn't already have a value
# 380 : : *
# 381 : : * @param strArg Argument to set (e.g. "-foo")
# 382 : : * @param fValue Value (e.g. false)
# 383 : : * @return true if argument gets set, false if it already had a value
# 384 : : */
# 385 : : bool SoftSetBoolArg(const std::string& strArg, bool fValue);
# 386 : :
# 387 : : // Forces an arg setting. Called by SoftSetArg() if the arg hasn't already
# 388 : : // been set. Also called directly in testing.
# 389 : : void ForceSetArg(const std::string& strArg, const std::string& strValue);
# 390 : :
# 391 : : /**
# 392 : : * Returns the appropriate chain name from the program arguments.
# 393 : : * @return CBaseChainParams::MAIN by default; raises runtime error if an invalid combination is given.
# 394 : : */
# 395 : : std::string GetChainName() const;
# 396 : :
# 397 : : /**
# 398 : : * Add argument
# 399 : : */
# 400 : : void AddArg(const std::string& name, const std::string& help, unsigned int flags, const OptionsCategory& cat);
# 401 : :
# 402 : : /**
# 403 : : * Add subcommand
# 404 : : */
# 405 : : void AddCommand(const std::string& cmd, const std::string& help);
# 406 : :
# 407 : : /**
# 408 : : * Add many hidden arguments
# 409 : : */
# 410 : : void AddHiddenArgs(const std::vector<std::string>& args);
# 411 : :
# 412 : : /**
# 413 : : * Clear available arguments
# 414 : : */
# 415 : 836 : void ClearArgs() {
# 416 : 836 : LOCK(cs_args);
# 417 : 836 : m_available_args.clear();
# 418 : 836 : m_network_only_args.clear();
# 419 : 836 : }
# 420 : :
# 421 : : /**
# 422 : : * Get the help string
# 423 : : */
# 424 : : std::string GetHelpMessage() const;
# 425 : :
# 426 : : /**
# 427 : : * Return Flags for known arg.
# 428 : : * Return nullopt for unknown arg.
# 429 : : */
# 430 : : std::optional<unsigned int> GetArgFlags(const std::string& name) const;
# 431 : :
# 432 : : /**
# 433 : : * Read and update settings file with saved settings. This needs to be
# 434 : : * called after SelectParams() because the settings file location is
# 435 : : * network-specific.
# 436 : : */
# 437 : : bool InitSettings(std::string& error);
# 438 : :
# 439 : : /**
# 440 : : * Get settings file path, or return false if read-write settings were
# 441 : : * disabled with -nosettings.
# 442 : : */
# 443 : : bool GetSettingsPath(fs::path* filepath = nullptr, bool temp = false) const;
# 444 : :
# 445 : : /**
# 446 : : * Read settings file. Push errors to vector, or log them if null.
# 447 : : */
# 448 : : bool ReadSettingsFile(std::vector<std::string>* errors = nullptr);
# 449 : :
# 450 : : /**
# 451 : : * Write settings file. Push errors to vector, or log them if null.
# 452 : : */
# 453 : : bool WriteSettingsFile(std::vector<std::string>* errors = nullptr) const;
# 454 : :
# 455 : : /**
# 456 : : * Get current setting from config file or read/write settings file,
# 457 : : * ignoring runtime command line or forced argument values.
# 458 : : */
# 459 : : util::SettingsValue GetPersistentSetting(const std::string& name) const;
# 460 : :
# 461 : : /**
# 462 : : * Access settings with lock held.
# 463 : : */
# 464 : : template <typename Fn>
# 465 : : void LockSettings(Fn&& fn)
# 466 : 595 : {
# 467 : 595 : LOCK(cs_args);
# 468 : 595 : fn(m_settings);
# 469 : 595 : }
# 470 : :
# 471 : : /**
# 472 : : * Log the config file options and the command line arguments,
# 473 : : * useful for troubleshooting.
# 474 : : */
# 475 : : void LogArgs() const;
# 476 : :
# 477 : : private:
# 478 : : /**
# 479 : : * Get data directory path
# 480 : : *
# 481 : : * @param net_specific Append network identifier to the returned path
# 482 : : * @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
# 483 : : * @post Returned directory path is created unless it is empty
# 484 : : */
# 485 : : const fs::path& GetDataDir(bool net_specific) const;
# 486 : :
# 487 : : // Helper function for LogArgs().
# 488 : : void logArgsPrefix(
# 489 : : const std::string& prefix,
# 490 : : const std::string& section,
# 491 : : const std::map<std::string, std::vector<util::SettingsValue>>& args) const;
# 492 : : };
# 493 : :
# 494 : : extern ArgsManager gArgs;
# 495 : :
# 496 : : /**
# 497 : : * @return true if help has been requested via a command-line arg
# 498 : : */
# 499 : : bool HelpRequested(const ArgsManager& args);
# 500 : :
# 501 : : /** Add help options to the args manager */
# 502 : : void SetupHelpOptions(ArgsManager& args);
# 503 : :
# 504 : : /**
# 505 : : * Format a string to be used as group of options in help messages
# 506 : : *
# 507 : : * @param message Group name (e.g. "RPC server options:")
# 508 : : * @return the formatted string
# 509 : : */
# 510 : : std::string HelpMessageGroup(const std::string& message);
# 511 : :
# 512 : : /**
# 513 : : * Format a string to be used as option description in help messages
# 514 : : *
# 515 : : * @param option Option message (e.g. "-rpcuser=<user>")
# 516 : : * @param message Option description (e.g. "Username for JSON-RPC connections")
# 517 : : * @return the formatted string
# 518 : : */
# 519 : : std::string HelpMessageOpt(const std::string& option, const std::string& message);
# 520 : :
# 521 : : /**
# 522 : : * Return the number of cores available on the current system.
# 523 : : * @note This does count virtual cores, such as those provided by HyperThreading.
# 524 : : */
# 525 : : int GetNumCores();
# 526 : :
# 527 : : /**
# 528 : : * On platforms that support it, tell the kernel the calling thread is
# 529 : : * CPU-intensive and non-interactive. See SCHED_BATCH in sched(7) for details.
# 530 : : *
# 531 : : */
# 532 : : void ScheduleBatchPriority();
# 533 : :
# 534 : : namespace util {
# 535 : :
# 536 : : //! Simplification of std insertion
# 537 : : template <typename Tdst, typename Tsrc>
# 538 : : inline void insert(Tdst& dst, const Tsrc& src) {
# 539 : : dst.insert(dst.begin(), src.begin(), src.end());
# 540 : : }
# 541 : : template <typename TsetT, typename Tsrc>
# 542 : 233880 : inline void insert(std::set<TsetT>& dst, const Tsrc& src) {
# 543 : 233880 : dst.insert(src.begin(), src.end());
# 544 : 233880 : }
# 545 : :
# 546 : : /**
# 547 : : * Helper function to access the contained object of a std::any instance.
# 548 : : * Returns a pointer to the object if passed instance has a value and the type
# 549 : : * matches, nullptr otherwise.
# 550 : : */
# 551 : : template<typename T>
# 552 : : T* AnyPtr(const std::any& any) noexcept
# 553 : 126481 : {
# 554 : 126481 : T* const* ptr = std::any_cast<T*>(&any);
# 555 [ + - ][ + - ]: 126481 : return ptr ? *ptr : nullptr;
# 556 : 126481 : }
# 557 : :
# 558 : : #ifdef WIN32
# 559 : : class WinCmdLineArgs
# 560 : : {
# 561 : : public:
# 562 : : WinCmdLineArgs();
# 563 : : ~WinCmdLineArgs();
# 564 : : std::pair<int, char**> get();
# 565 : :
# 566 : : private:
# 567 : : int argc;
# 568 : : char** argv;
# 569 : : std::vector<std::string> args;
# 570 : : };
# 571 : : #endif
# 572 : :
# 573 : : } // namespace util
# 574 : :
# 575 : : #endif // BITCOIN_UTIL_SYSTEM_H
|