LCOV - code coverage report
Current view: top level - src/util - system.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 25 36 69.4 %
Date: 2020-09-26 01:30:44 Functions: 35 71 49.3 %

          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 <optional.h>
      23             : #include <sync.h>
      24             : #include <tinyformat.h>
      25             : #include <util/memory.h>
      26             : #include <util/settings.h>
      27             : #include <util/threadnames.h>
      28             : #include <util/time.h>
      29             : 
      30             : #include <exception>
      31             : #include <map>
      32             : #include <set>
      33             : #include <stdint.h>
      34             : #include <string>
      35             : #include <utility>
      36             : #include <vector>
      37             : 
      38             : #include <boost/thread/condition_variable.hpp> // for boost::thread_interrupted
      39             : 
      40             : class UniValue;
      41             : 
      42             : // Application startup time (used for uptime calculation)
      43             : int64_t GetStartupTime();
      44             : 
      45             : extern const char * const BITCOIN_CONF_FILENAME;
      46             : extern const char * const BITCOIN_SETTINGS_FILENAME;
      47             : 
      48             : void SetupEnvironment();
      49             : bool SetupNetworking();
      50             : 
      51             : template<typename... Args>
      52        1421 : bool error(const char* fmt, const Args&... args)
      53             : {
      54        1421 :     LogPrintf("ERROR: %s\n", tfm::format(fmt, args...));
      55        1421 :     return false;
      56           0 : }
      57             : 
      58             : void PrintExceptionContinue(const std::exception *pex, const char* pszThread);
      59             : bool FileCommit(FILE *file);
      60             : bool TruncateFile(FILE *file, unsigned int length);
      61             : int RaiseFileDescriptorLimit(int nMinFD);
      62             : void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
      63             : bool RenameOver(fs::path src, fs::path dest);
      64             : bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false);
      65             : void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name);
      66             : bool DirIsWritable(const fs::path& directory);
      67             : bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes = 0);
      68             : 
      69             : /** Get the size of a file by scanning it.
      70             :  *
      71             :  * @param[in] path The file path
      72             :  * @param[in] max Stop seeking beyond this limit
      73             :  * @return The file size or max
      74             :  */
      75             : std::streampos GetFileSize(const char* path, std::streamsize max = std::numeric_limits<std::streamsize>::max());
      76             : 
      77             : /** Release all directory locks. This is used for unit testing only, at runtime
      78             :  * the global destructor will take care of the locks.
      79             :  */
      80             : void ReleaseDirectoryLocks();
      81             : 
      82             : bool TryCreateDirectories(const fs::path& p);
      83             : fs::path GetDefaultDataDir();
      84             : // The blocks directory is always net specific.
      85             : const fs::path &GetBlocksDir();
      86             : const fs::path &GetDataDir(bool fNetSpecific = true);
      87             : // Return true if -datadir option points to a valid directory or is not specified.
      88             : bool CheckDataDirOption();
      89             : /** Tests only */
      90             : void ClearDatadirCache();
      91             : fs::path GetConfigFile(const std::string& confPath);
      92             : #ifdef WIN32
      93             : fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
      94             : #endif
      95             : #ifndef WIN32
      96             : std::string ShellEscape(const std::string& arg);
      97             : #endif
      98             : #if HAVE_SYSTEM
      99             : void runCommand(const std::string& strCommand);
     100             : #endif
     101             : #ifdef HAVE_BOOST_PROCESS
     102             : /**
     103             :  * Execute a command which returns JSON, and parse the result.
     104             :  *
     105             :  * @param str_command The command to execute, including any arguments
     106             :  * @param str_std_in string to pass to stdin
     107             :  * @return parsed JSON
     108             :  */
     109             : UniValue RunCommandParseJSON(const std::string& str_command, const std::string& str_std_in="");
     110             : #endif // HAVE_BOOST_PROCESS
     111             : 
     112             : /**
     113             :  * Most paths passed as configuration arguments are treated as relative to
     114             :  * the datadir if they are not absolute.
     115             :  *
     116             :  * @param path The path to be conditionally prefixed with datadir.
     117             :  * @param net_specific Forwarded to GetDataDir().
     118             :  * @return The normalized path.
     119             :  */
     120             : fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific = true);
     121             : 
     122        5835 : inline bool IsSwitchChar(char c)
     123             : {
     124             : #ifdef WIN32
     125             :     return c == '-' || c == '/';
     126             : #else
     127        5835 :     return c == '-';
     128             : #endif
     129             : }
     130             : 
     131             : enum class OptionsCategory {
     132             :     OPTIONS,
     133             :     CONNECTION,
     134             :     WALLET,
     135             :     WALLET_DEBUG_TEST,
     136             :     ZMQ,
     137             :     DEBUG_TEST,
     138             :     CHAINPARAMS,
     139             :     NODE_RELAY,
     140             :     BLOCK_CREATION,
     141             :     RPC,
     142             :     GUI,
     143             :     COMMANDS,
     144             :     REGISTER_COMMANDS,
     145             : 
     146             :     HIDDEN // Always the last option to avoid printing these in the help
     147             : };
     148             : 
     149      282252 : struct SectionInfo
     150             : {
     151             :     std::string m_name;
     152             :     std::string m_file;
     153             :     int m_line;
     154             : };
     155             : 
     156             : class ArgsManager
     157             : {
     158             : public:
     159             :     enum Flags {
     160             :         // Boolean options can accept negation syntax -noOPTION or -noOPTION=1
     161             :         ALLOW_BOOL = 0x01,
     162             :         ALLOW_INT = 0x02,
     163             :         ALLOW_STRING = 0x04,
     164             :         ALLOW_ANY = ALLOW_BOOL | ALLOW_INT | ALLOW_STRING,
     165             :         DEBUG_ONLY = 0x100,
     166             :         /* Some options would cause cross-contamination if values for
     167             :          * mainnet were used while running on regtest/testnet (or vice-versa).
     168             :          * Setting them as NETWORK_ONLY ensures that sharing a config file
     169             :          * between mainnet and regtest/testnet won't cause problems due to these
     170             :          * parameters by accident. */
     171             :         NETWORK_ONLY = 0x200,
     172             :         // This argument's value is sensitive (such as a password).
     173             :         SENSITIVE = 0x400,
     174             :     };
     175             : 
     176             : protected:
     177     1266708 :     struct Arg
     178             :     {
     179             :         std::string m_help_param;
     180             :         std::string m_help_text;
     181             :         unsigned int m_flags;
     182             :     };
     183             : 
     184             :     mutable RecursiveMutex cs_args;
     185             :     util::Settings m_settings GUARDED_BY(cs_args);
     186             :     std::string m_network GUARDED_BY(cs_args);
     187             :     std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
     188             :     std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
     189             :     std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
     190             : 
     191             :     NODISCARD bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false);
     192             : 
     193             :     /**
     194             :      * Returns true if settings values from the default section should be used,
     195             :      * depending on the current network and whether the setting is
     196             :      * network-specific.
     197             :      */
     198             :     bool UseDefaultSection(const std::string& arg) const EXCLUSIVE_LOCKS_REQUIRED(cs_args);
     199             : 
     200             :     /**
     201             :      * Get setting value.
     202             :      *
     203             :      * Result will be null if setting was unset, true if "-setting" argument was passed
     204             :      * false if "-nosetting" argument was passed, and a string if a "-setting=value"
     205             :      * argument was passed.
     206             :      */
     207             :     util::SettingsValue GetSetting(const std::string& arg) const;
     208             : 
     209             :     /**
     210             :      * Get list of setting values.
     211             :      */
     212             :     std::vector<util::SettingsValue> GetSettingsList(const std::string& arg) const;
     213             : 
     214             : public:
     215             :     ArgsManager();
     216             :     ~ArgsManager();
     217             : 
     218             :     /**
     219             :      * Select the network in use
     220             :      */
     221             :     void SelectConfigNetwork(const std::string& network);
     222             : 
     223             :     NODISCARD bool ParseParameters(int argc, const char* const argv[], std::string& error);
     224             :     NODISCARD bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
     225             : 
     226             :     /**
     227             :      * Log warnings for options in m_section_only_args when
     228             :      * they are specified in the default section but not overridden
     229             :      * on the command line or in a network-specific section in the
     230             :      * config file.
     231             :      */
     232             :     const std::set<std::string> GetUnsuitableSectionOnlyArgs() const;
     233             : 
     234             :     /**
     235             :      * Log warnings for unrecognized section names in the config file.
     236             :      */
     237             :     const std::list<SectionInfo> GetUnrecognizedSections() const;
     238             : 
     239             :     /**
     240             :      * Return a vector of strings of the given argument
     241             :      *
     242             :      * @param strArg Argument to get (e.g. "-foo")
     243             :      * @return command-line arguments
     244             :      */
     245             :     std::vector<std::string> GetArgs(const std::string& strArg) const;
     246             : 
     247             :     /**
     248             :      * Return true if the given argument has been manually set
     249             :      *
     250             :      * @param strArg Argument to get (e.g. "-foo")
     251             :      * @return true if the argument has been set
     252             :      */
     253             :     bool IsArgSet(const std::string& strArg) const;
     254             : 
     255             :     /**
     256             :      * Return true if the argument was originally passed as a negated option,
     257             :      * i.e. -nofoo.
     258             :      *
     259             :      * @param strArg Argument to get (e.g. "-foo")
     260             :      * @return true if the argument was passed negated
     261             :      */
     262             :     bool IsArgNegated(const std::string& strArg) const;
     263             : 
     264             :     /**
     265             :      * Return string argument or default value
     266             :      *
     267             :      * @param strArg Argument to get (e.g. "-foo")
     268             :      * @param strDefault (e.g. "1")
     269             :      * @return command-line argument or default value
     270             :      */
     271             :     std::string GetArg(const std::string& strArg, const std::string& strDefault) const;
     272             : 
     273             :     /**
     274             :      * Return integer argument or default value
     275             :      *
     276             :      * @param strArg Argument to get (e.g. "-foo")
     277             :      * @param nDefault (e.g. 1)
     278             :      * @return command-line argument (0 if invalid number) or default value
     279             :      */
     280             :     int64_t GetArg(const std::string& strArg, int64_t nDefault) const;
     281             : 
     282             :     /**
     283             :      * Return boolean argument or default value
     284             :      *
     285             :      * @param strArg Argument to get (e.g. "-foo")
     286             :      * @param fDefault (true or false)
     287             :      * @return command-line argument or default value
     288             :      */
     289             :     bool GetBoolArg(const std::string& strArg, bool fDefault) const;
     290             : 
     291             :     /**
     292             :      * Set an argument if it doesn't already have a value
     293             :      *
     294             :      * @param strArg Argument to set (e.g. "-foo")
     295             :      * @param strValue Value (e.g. "1")
     296             :      * @return true if argument gets set, false if it already had a value
     297             :      */
     298             :     bool SoftSetArg(const std::string& strArg, const std::string& strValue);
     299             : 
     300             :     /**
     301             :      * Set a boolean argument if it doesn't already have a value
     302             :      *
     303             :      * @param strArg Argument to set (e.g. "-foo")
     304             :      * @param fValue Value (e.g. false)
     305             :      * @return true if argument gets set, false if it already had a value
     306             :      */
     307             :     bool SoftSetBoolArg(const std::string& strArg, bool fValue);
     308             : 
     309             :     // Forces an arg setting. Called by SoftSetArg() if the arg hasn't already
     310             :     // been set. Also called directly in testing.
     311             :     void ForceSetArg(const std::string& strArg, const std::string& strValue);
     312             : 
     313             :     /**
     314             :      * Returns the appropriate chain name from the program arguments.
     315             :      * @return CBaseChainParams::MAIN by default; raises runtime error if an invalid combination is given.
     316             :      */
     317             :     std::string GetChainName() const;
     318             : 
     319             :     /**
     320             :      * Add argument
     321             :      */
     322             :     void AddArg(const std::string& name, const std::string& help, unsigned int flags, const OptionsCategory& cat);
     323             : 
     324             :     /**
     325             :      * Add many hidden arguments
     326             :      */
     327             :     void AddHiddenArgs(const std::vector<std::string>& args);
     328             : 
     329             :     /**
     330             :      * Clear available arguments
     331             :      */
     332         466 :     void ClearArgs() {
     333         466 :         LOCK(cs_args);
     334         466 :         m_available_args.clear();
     335         466 :         m_network_only_args.clear();
     336         466 :     }
     337             : 
     338             :     /**
     339             :      * Get the help string
     340             :      */
     341             :     std::string GetHelpMessage() const;
     342             : 
     343             :     /**
     344             :      * Return Flags for known arg.
     345             :      * Return nullopt for unknown arg.
     346             :      */
     347             :     Optional<unsigned int> GetArgFlags(const std::string& name) const;
     348             : 
     349             :     /**
     350             :      * Read and update settings file with saved settings. This needs to be
     351             :      * called after SelectParams() because the settings file location is
     352             :      * network-specific.
     353             :      */
     354             :     bool InitSettings(std::string& error);
     355             : 
     356             :     /**
     357             :      * Get settings file path, or return false if read-write settings were
     358             :      * disabled with -nosettings.
     359             :      */
     360             :     bool GetSettingsPath(fs::path* filepath = nullptr, bool temp = false) const;
     361             : 
     362             :     /**
     363             :      * Read settings file. Push errors to vector, or log them if null.
     364             :      */
     365             :     bool ReadSettingsFile(std::vector<std::string>* errors = nullptr);
     366             : 
     367             :     /**
     368             :      * Write settings file. Push errors to vector, or log them if null.
     369             :      */
     370             :     bool WriteSettingsFile(std::vector<std::string>* errors = nullptr) const;
     371             : 
     372             :     /**
     373             :      * Access settings with lock held.
     374             :      */
     375             :     template <typename Fn>
     376         327 :     void LockSettings(Fn&& fn)
     377             :     {
     378         327 :         LOCK(cs_args);
     379         327 :         fn(m_settings);
     380         327 :     }
     381             : 
     382             :     /**
     383             :      * Log the config file options and the command line arguments,
     384             :      * useful for troubleshooting.
     385             :      */
     386             :     void LogArgs() const;
     387             : 
     388             : private:
     389             :     // Helper function for LogArgs().
     390             :     void logArgsPrefix(
     391             :         const std::string& prefix,
     392             :         const std::string& section,
     393             :         const std::map<std::string, std::vector<util::SettingsValue>>& args) const;
     394             : };
     395             : 
     396             : extern ArgsManager gArgs;
     397             : 
     398             : /**
     399             :  * @return true if help has been requested via a command-line arg
     400             :  */
     401             : bool HelpRequested(const ArgsManager& args);
     402             : 
     403             : /** Add help options to the args manager */
     404             : void SetupHelpOptions(ArgsManager& args);
     405             : 
     406             : /**
     407             :  * Format a string to be used as group of options in help messages
     408             :  *
     409             :  * @param message Group name (e.g. "RPC server options:")
     410             :  * @return the formatted string
     411             :  */
     412             : std::string HelpMessageGroup(const std::string& message);
     413             : 
     414             : /**
     415             :  * Format a string to be used as option description in help messages
     416             :  *
     417             :  * @param option Option message (e.g. "-rpcuser=<user>")
     418             :  * @param message Option description (e.g. "Username for JSON-RPC connections")
     419             :  * @return the formatted string
     420             :  */
     421             : std::string HelpMessageOpt(const std::string& option, const std::string& message);
     422             : 
     423             : /**
     424             :  * Return the number of cores available on the current system.
     425             :  * @note This does count virtual cores, such as those provided by HyperThreading.
     426             :  */
     427             : int GetNumCores();
     428             : 
     429             : /**
     430             :  * .. and a wrapper that just calls func once
     431             :  */
     432        3100 : template <typename Callable> void TraceThread(const char* name,  Callable func)
     433             : {
     434        3100 :     util::ThreadRename(name);
     435             :     try
     436             :     {
     437        3100 :         LogPrintf("%s thread start\n", name);
     438        3101 :         func();
     439        3100 :         LogPrintf("%s thread exit\n", name);
     440           0 :     }
     441             :     catch (const boost::thread_interrupted&)
     442             :     {
     443           0 :         LogPrintf("%s thread interrupt\n", name);
     444           0 :         throw;
     445           0 :     }
     446             :     catch (const std::exception& e) {
     447           0 :         PrintExceptionContinue(&e, name);
     448           0 :         throw;
     449           0 :     }
     450             :     catch (...) {
     451           0 :         PrintExceptionContinue(nullptr, name);
     452           0 :         throw;
     453           0 :     }
     454        3101 : }
     455             : 
     456             : std::string CopyrightHolders(const std::string& strPrefix);
     457             : 
     458             : /**
     459             :  * On platforms that support it, tell the kernel the calling thread is
     460             :  * CPU-intensive and non-interactive. See SCHED_BATCH in sched(7) for details.
     461             :  *
     462             :  */
     463             : void ScheduleBatchPriority();
     464             : 
     465             : namespace util {
     466             : 
     467             : //! Simplification of std insertion
     468             : template <typename Tdst, typename Tsrc>
     469             : inline void insert(Tdst& dst, const Tsrc& src) {
     470             :     dst.insert(dst.begin(), src.begin(), src.end());
     471             : }
     472             : template <typename TsetT, typename Tsrc>
     473      130470 : inline void insert(std::set<TsetT>& dst, const Tsrc& src) {
     474      130470 :     dst.insert(src.begin(), src.end());
     475      130470 : }
     476             : 
     477             : #ifdef WIN32
     478             : class WinCmdLineArgs
     479             : {
     480             : public:
     481             :     WinCmdLineArgs();
     482             :     ~WinCmdLineArgs();
     483             :     std::pair<int, char**> get();
     484             : 
     485             : private:
     486             :     int argc;
     487             :     char** argv;
     488             :     std::vector<std::string> args;
     489             : };
     490             : #endif
     491             : 
     492             : } // namespace util
     493             : 
     494             : #endif // BITCOIN_UTIL_SYSTEM_H

Generated by: LCOV version 1.15