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
|