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