1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php .
6 #if defined(HAVE_CONFIG_H)
7 #include "config/bitcoin-config.h"
12 #include "chainparamsbase.h"
14 #include "serialize.h"
16 #include "utilstrencodings.h"
18 #include "komodo_defs.h"
25 #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
27 #include <pthread_np.h>
31 // for posix_fallocate
34 #ifdef _POSIX_C_SOURCE
35 #undef _POSIX_C_SOURCE
38 #define _POSIX_C_SOURCE 200112L
44 #include <sys/resource.h>
50 #pragma warning(disable:4786)
51 #pragma warning(disable:4804)
52 #pragma warning(disable:4805)
53 #pragma warning(disable:4717)
59 #define _WIN32_WINNT 0x0501
64 #define _WIN32_IE 0x0501
66 #define WIN32_LEAN_AND_MEAN 1
71 #include <io.h> /* for _commit */
75 #ifdef HAVE_SYS_PRCTL_H
76 #include <sys/prctl.h>
79 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
80 #include <boost/algorithm/string/join.hpp>
81 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
82 #include <boost/filesystem.hpp>
83 #include <boost/filesystem/fstream.hpp>
84 #include <boost/foreach.hpp>
85 #include <boost/program_options/detail/config_file.hpp>
86 #include <boost/program_options/parsers.hpp>
87 #include <boost/thread.hpp>
88 #include <openssl/crypto.h>
89 #include <openssl/conf.h>
91 // Work around clang compilation problem in Boost 1.46:
92 // /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup
93 // See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
94 // http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
97 namespace program_options {
98 std::string to_internal(const std::string&);
105 map<string, string> mapArgs;
106 map<string, vector<string> > mapMultiArgs;
108 bool fPrintToConsole = false;
109 bool fPrintToDebugLog = true;
110 bool fDaemon = false;
111 bool fServer = false;
112 string strMiscWarning;
113 bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
114 bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
115 bool fLogIPs = DEFAULT_LOGIPS;
116 std::atomic<bool> fReopenDebugLog(false);
117 CTranslationInterface translationInterface;
119 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
121 bool _IsVerusActive()
123 return (strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0 || strcmp(ASSETCHAINS_SYMBOL, "VRSCTEST") == 0);
126 bool _IsVerusMainnetActive()
128 return (strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0);
131 /** Init OpenSSL library multithreading support */
132 static CCriticalSection** ppmutexOpenSSL;
133 void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
135 if (mode & CRYPTO_LOCK) {
136 ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
138 LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
148 // Init OpenSSL library multithreading support
149 ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*));
150 for (int i = 0; i < CRYPTO_num_locks(); i++)
151 ppmutexOpenSSL[i] = new CCriticalSection();
152 CRYPTO_set_locking_callback(locking_callback);
154 // OpenSSL can optionally load a config file which lists optional loadable modules and engines.
155 // We don't use them so we don't require the config. However some of our libs may call functions
156 // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing
157 // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
158 // that the config appears to have been loaded and there are no modules/engines available.
163 // Shutdown OpenSSL library multithreading support
164 CRYPTO_set_locking_callback(NULL);
165 for (int i = 0; i < CRYPTO_num_locks(); i++)
166 delete ppmutexOpenSSL[i];
167 OPENSSL_free(ppmutexOpenSSL);
173 * LogPrintf() has been broken a couple of times now
174 * by well-meaning people adding mutexes in the most straightforward way.
175 * It breaks because it may be called by global destructors during shutdown.
176 * Since the order of destruction of static/global objects is undefined,
177 * defining a mutex as a global object doesn't work (the mutex gets
178 * destroyed, and then some later destructor calls OutputDebugStringF,
179 * maybe indirectly, and you get a core dump at shutdown trying to lock
183 static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
186 * We use boost::call_once() to make sure mutexDebugLog and
187 * vMsgsBeforeOpenLog are initialized in a thread-safe manner.
189 * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
190 * are leaked on exit. This is ugly, but will be cleaned up by
191 * the OS/libc. When the shutdown sequence is fully audited and
192 * tested, explicit destruction of these objects can be implemented.
194 static FILE* fileout = NULL;
195 static boost::mutex* mutexDebugLog = NULL;
196 static list<string> *vMsgsBeforeOpenLog;
198 [[noreturn]] void new_handler_terminate()
200 // Rather than throwing std::bad-alloc if allocation fails, terminate
201 // immediately to (try to) avoid chain corruption.
202 // Since LogPrintf may itself allocate memory, set the handler directly
203 // to terminate first.
204 std::set_new_handler(std::terminate);
205 fputs("Error: Out of memory. Terminating.\n", stderr);
206 LogPrintf("Error: Out of memory. Terminating.\n");
208 // The log was successful, terminate now.
212 static int FileWriteStr(const std::string &str, FILE *fp)
214 return fwrite(str.data(), 1, str.size(), fp);
217 static void DebugPrintInit()
219 assert(mutexDebugLog == NULL);
220 mutexDebugLog = new boost::mutex();
221 vMsgsBeforeOpenLog = new list<string>;
226 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
227 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
229 assert(fileout == NULL);
230 assert(vMsgsBeforeOpenLog);
231 boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
232 fileout = fopen(pathDebug.string().c_str(), "a");
233 if (fileout) setbuf(fileout, NULL); // unbuffered
235 // dump buffered messages from before we opened the log
236 while (!vMsgsBeforeOpenLog->empty()) {
237 FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
238 vMsgsBeforeOpenLog->pop_front();
241 delete vMsgsBeforeOpenLog;
242 vMsgsBeforeOpenLog = NULL;
245 bool LogAcceptCategory(const char* category)
247 if (category != NULL)
252 // Give each thread quick access to -debug settings.
253 // This helps prevent issues debugging global destructors,
254 // where mapMultiArgs might be deleted before another
255 // global destructor calls LogPrint()
256 static boost::thread_specific_ptr<set<string>> ptrCategory;
257 if (ptrCategory.get() == NULL)
259 const vector<string>& categories = mapMultiArgs["-debug"];
260 ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
261 // thread_specific_ptr automatically deletes the set when the thread ends.
263 const set<string>& setCategories = *ptrCategory.get();
265 // if not debugging everything and not debugging specific category, LogPrint does nothing.
266 if (setCategories.count(string("")) == 0 &&
267 setCategories.count(string("1")) == 0 &&
268 setCategories.count(string(category)) == 0)
275 * fStartedNewLine is a state variable held by the calling context that will
276 * suppress printing of the timestamp when multiple calls are made that don't
277 * end in a newline. Initialize it to true, and hold it, in the calling context.
279 static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
286 if (*fStartedNewLine)
287 strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
291 if (!str.empty() && str[str.size()-1] == '\n')
292 *fStartedNewLine = true;
294 *fStartedNewLine = false;
299 int LogPrintStr(const std::string &str)
301 int ret = 0; // Returns total number of characters written
302 static bool fStartedNewLine = true;
306 ret = fwrite(str.data(), 1, str.size(), stdout);
309 else if (fPrintToDebugLog)
311 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
312 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
314 string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
316 // buffer if we haven't opened the log yet
317 if (fileout == NULL) {
318 assert(vMsgsBeforeOpenLog);
319 ret = strTimestamped.length();
320 vMsgsBeforeOpenLog->push_back(strTimestamped);
324 // reopen the log file, if requested
325 if (fReopenDebugLog) {
326 fReopenDebugLog = false;
327 boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
328 if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
329 setbuf(fileout, NULL); // unbuffered
332 ret = FileWriteStr(strTimestamped, fileout);
338 static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
340 // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
341 if (name.find("-no") == 0)
343 std::string positive("-");
344 positive.append(name.begin()+3, name.end());
345 if (mapSettingsRet.count(positive) == 0)
347 bool value = !GetBoolArg(name, false);
348 mapSettingsRet[positive] = (value ? "1" : "0");
353 void ParseParameters(int argc, const char* const argv[])
356 mapMultiArgs.clear();
358 for (int i = 1; i < argc; i++)
360 std::string str(argv[i]);
361 std::string strValue;
362 size_t is_index = str.find('=');
363 if (is_index != std::string::npos)
365 strValue = str.substr(is_index+1);
366 str = str.substr(0, is_index);
369 boost::to_lower(str);
370 if (boost::algorithm::starts_with(str, "/"))
371 str = "-" + str.substr(1);
377 // Interpret --foo as -foo.
378 // If both --foo and -foo are set, the last takes effect.
379 if (str.length() > 1 && str[1] == '-')
382 mapArgs[str] = strValue;
383 mapMultiArgs[str].push_back(strValue);
387 BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs)
389 // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
390 InterpretNegativeSetting(entry.first, mapArgs);
394 void Split(const std::string& strVal, uint64_t *outVals, const uint64_t nDefault,int maxElements)
396 stringstream ss(strVal);
397 vector<uint64_t> vec;
399 uint64_t i, nLast, numVals = 0;
401 while ( ss.peek() == ' ' )
404 while ( numVals < maxElements && ss >> i )
406 outVals[numVals] = i;
409 while ( ss.peek() == ' ' )
411 if ( ss.peek() == ',' )
413 while ( ss.peek() == ' ' )
418 nLast = outVals[numVals - 1];
422 for ( i = numVals; i < maxElements; i++ )
428 std::string GetArg(const std::string& strArg, const std::string& strDefault)
430 if (mapArgs.count(strArg))
431 return mapArgs[strArg];
435 int64_t GetArg(const std::string& strArg, int64_t nDefault)
437 if (mapArgs.count(strArg))
438 return atoi64(mapArgs[strArg]);
442 bool GetBoolArg(const std::string& strArg, bool fDefault)
444 if (mapArgs.count(strArg))
446 if (mapArgs[strArg].empty())
448 return (atoi(mapArgs[strArg]) != 0);
453 bool SoftSetArg(const std::string& strArg, const std::string& strValue)
455 if (mapArgs.count(strArg))
457 mapArgs[strArg] = strValue;
461 bool SoftSetBoolArg(const std::string& strArg, bool fValue)
464 return SoftSetArg(strArg, std::string("1"));
466 return SoftSetArg(strArg, std::string("0"));
469 static const int screenWidth = 79;
470 static const int optIndent = 2;
471 static const int msgIndent = 7;
473 std::string HelpMessageGroup(const std::string &message) {
474 return std::string(message) + std::string("\n\n");
477 std::string HelpMessageOpt(const std::string &option, const std::string &message) {
478 return std::string(optIndent,' ') + std::string(option) +
479 std::string("\n") + std::string(msgIndent,' ') +
480 FormatParagraph(message, screenWidth - msgIndent, msgIndent) +
484 static std::string FormatException(const std::exception* pex, const char* pszThread)
487 char pszModule[MAX_PATH] = "";
488 GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
490 const char* pszModule = "Komodo";
494 "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
497 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
500 void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
502 std::string message = FormatException(pex, pszThread);
503 LogPrintf("\n\n************************\n%s\n", message);
504 fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
505 strMiscWarning = message;
508 //int64_t MAX_MONEY = 200000000 * 100000000LL;
510 boost::filesystem::path GetDefaultDataDir()
512 namespace fs = boost::filesystem;
513 char symbol[KOMODO_ASSETCHAIN_MAXLEN];
514 if ( ASSETCHAINS_SYMBOL[0] != 0 )
515 strcpy(symbol,ASSETCHAINS_SYMBOL);
517 // Windows < Vista: C:\Documents and Settings\Username\Application Data\Zcash
518 // Windows >= Vista: C:\Users\Username\AppData\Roaming\Zcash
519 // Mac: ~/Library/Application Support/Zcash
523 if ( symbol[0] == 0 )
524 return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo";
527 if (_IsVerusActive())
529 return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo" / symbol;
533 return GetSpecialFolderPath(CSIDL_APPDATA) / (PBAAS_TESTMODE ? "VerusTest" : "Verus") / "PBAAS" / symbol;
538 char* pszHome = getenv("HOME");
539 if (pszHome == NULL || strlen(pszHome) == 0)
540 pathRet = fs::path("/");
542 pathRet = fs::path(pszHome);
545 pathRet /= "Library/Application Support";
546 TryCreateDirectory(pathRet);
547 if ( symbol[0] == 0 )
548 return pathRet / "Komodo";
551 if (_IsVerusActive())
554 TryCreateDirectory(pathRet);
558 pathRet /= PBAAS_TESTMODE ? "VerusTest" : "Verus";
559 TryCreateDirectory(pathRet);
561 TryCreateDirectory(pathRet);
563 return pathRet / symbol;
567 if ( symbol[0] == 0 )
568 return pathRet / ".komodo";
571 if (_IsVerusActive())
573 return pathRet / ".komodo" / symbol;
577 return pathRet / (PBAAS_TESTMODE ? ".verustest" : ".verus") / "PBAAS" / symbol;
584 boost::filesystem::path GetDefaultDataDir(std::string chainName)
586 char symbol[KOMODO_ASSETCHAIN_MAXLEN];
587 if (chainName.size() >= KOMODO_ASSETCHAIN_MAXLEN)
588 chainName.resize(KOMODO_ASSETCHAIN_MAXLEN - 1);
589 strcpy(symbol, chainName.c_str());
591 namespace fs = boost::filesystem;
593 // Windows < Vista: C:\Documents and Settings\Username\Application Data\Zcash
594 // Windows >= Vista: C:\Users\Username\AppData\Roaming\Zcash
595 // Mac: ~/Library/Application Support/Zcash
599 if (chainName == "VRSC" || chainName == "VRSCTEST")
601 return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo" / symbol;
605 return GetSpecialFolderPath(CSIDL_APPDATA) / (PBAAS_TESTMODE ? "VerusTest" : "Verus") / "PBAAS" / symbol;
609 char* pszHome = getenv("HOME");
610 if (pszHome == NULL || strlen(pszHome) == 0)
611 pathRet = fs::path("/");
613 pathRet = fs::path(pszHome);
616 pathRet /= "Library/Application Support";
617 TryCreateDirectory(pathRet);
618 if (chainName == "VRSC" || chainName == "VRSCTEST")
621 TryCreateDirectory(pathRet);
625 pathRet /= PBAAS_TESTMODE ? "VerusTest" : "Verus";
626 TryCreateDirectory(pathRet);
628 TryCreateDirectory(pathRet);
630 return pathRet / symbol;
633 if (chainName == "VRSC" || chainName == "VRSCTEST")
635 return pathRet / ".komodo" / symbol;
639 return pathRet / (PBAAS_TESTMODE ? ".verustest" : ".verus") / "PBAAS" / symbol;
645 static boost::filesystem::path pathCached;
646 static boost::filesystem::path pathCachedNetSpecific;
647 static boost::filesystem::path zc_paramsPathCached;
648 static CCriticalSection csPathCached;
650 static boost::filesystem::path ZC_GetBaseParamsDir()
652 // Copied from GetDefaultDataDir and adapter for zcash params.
654 namespace fs = boost::filesystem;
655 // Windows < Vista: C:\Documents and Settings\Username\Application Data\ZcashParams
656 // Windows >= Vista: C:\Users\Username\AppData\Roaming\ZcashParams
657 // Mac: ~/Library/Application Support/ZcashParams
658 // Unix: ~/.zcash-params
661 return GetSpecialFolderPath(CSIDL_APPDATA) / "ZcashParams";
663 char* pszHome = getenv("HOME");
664 if (pszHome == NULL || strlen(pszHome) == 0)
665 pathRet = fs::path("/");
667 pathRet = fs::path(pszHome);
670 pathRet /= "Library/Application Support";
671 TryCreateDirectory(pathRet);
672 return pathRet / "ZcashParams";
675 return pathRet / ".zcash-params";
680 const boost::filesystem::path &ZC_GetParamsDir()
682 namespace fs = boost::filesystem;
684 LOCK(csPathCached); // Reuse the same lock as upstream.
686 fs::path &path = zc_paramsPathCached;
688 // This can be called during exceptions by LogPrintf(), so we cache the
689 // value so we don't have to do memory allocations after that.
693 path = ZC_GetBaseParamsDir();
698 // Return the user specified export directory. Create directory if it doesn't exist.
699 // If user did not set option, return an empty path.
700 // If there is a filesystem problem, throw an exception.
701 const boost::filesystem::path GetExportDir()
703 namespace fs = boost::filesystem;
705 if (!mapArgs.count("-exportdir"))
711 path = fs::system_complete(mapArgs["-exportdir"]);
712 if (fs::exists(path) && !fs::is_directory(path)) {
713 throw std::runtime_error(strprintf("The -exportdir '%s' already exists and is not a directory", path.string()));
715 if (!fs::exists(path) && !fs::create_directories(path)) {
716 throw std::runtime_error(strprintf("Failed to create directory at -exportdir '%s'", path.string()));
723 const boost::filesystem::path &GetDataDir(bool fNetSpecific)
725 namespace fs = boost::filesystem;
729 fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
731 // This can be called during exceptions by LogPrintf(), so we cache the
732 // value so we don't have to do memory allocations after that.
736 if (mapArgs.count("-datadir")) {
737 path = fs::system_complete(mapArgs["-datadir"]);
738 if (!fs::is_directory(path)) {
743 path = GetDefaultDataDir();
746 path /= BaseParams().DataDir();
748 fs::create_directories(path);
749 //std::string assetpath = path + "/assets";
750 //boost::filesystem::create_directory(assetpath);
754 const boost::filesystem::path GetDataDir(std::string chainName)
756 namespace fs = boost::filesystem;
759 if ((chainName == "VRSC" || chainName == "VRSCTEST") && mapArgs.count("-datadir")) {
760 path = fs::system_complete(mapArgs["-datadir"]);
761 if (!fs::is_directory(path)) {
762 path = GetDefaultDataDir(chainName);
766 path = GetDefaultDataDir(chainName);
770 void ClearDatadirCache()
772 pathCached = boost::filesystem::path();
773 pathCachedNetSpecific = boost::filesystem::path();
776 boost::filesystem::path GetConfigFile()
779 if ( ASSETCHAINS_SYMBOL[0] != 0 )
780 sprintf(confname,"%s.conf",ASSETCHAINS_SYMBOL);
784 strcpy(confname,"Komodo.conf");
786 strcpy(confname,"komodo.conf");
789 boost::filesystem::path pathConfigFile(GetArg("-conf",confname));
790 if (!pathConfigFile.is_complete())
791 pathConfigFile = GetDataDir(false) / pathConfigFile;
793 return pathConfigFile;
796 boost::filesystem::path GetConfigFile(std::string chainName)
799 if (chainName.size() >= KOMODO_ASSETCHAIN_MAXLEN)
800 chainName.resize(KOMODO_ASSETCHAIN_MAXLEN - 1);
801 sprintf(confname, "%s.conf", chainName.c_str());
802 boost::filesystem::path pathConfigFile(GetArg("-conf",confname));
803 if (!pathConfigFile.is_complete())
804 pathConfigFile = GetDataDir(chainName) / pathConfigFile;
806 return pathConfigFile;
809 void ReadConfigFile(map<string, string>& mapSettingsRet,
810 map<string, vector<string> >& mapMultiSettingsRet)
812 boost::filesystem::ifstream streamConfig(GetConfigFile());
813 if (!streamConfig.good())
814 throw missing_zcash_conf();
816 set<string> setOptions;
817 setOptions.insert("*");
819 for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
821 // Don't overwrite existing settings so command line settings override komodo.conf
822 string strKey = string("-") + it->string_key;
823 if (mapSettingsRet.count(strKey) == 0)
825 mapSettingsRet[strKey] = it->value[0];
826 // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
827 InterpretNegativeSetting(strKey, mapSettingsRet);
829 mapMultiSettingsRet[strKey].push_back(it->value[0]);
831 // If datadir is changed in .conf file:
833 extern uint16_t BITCOIND_RPCPORT;
834 BITCOIND_RPCPORT = GetArg("-rpcport",BaseParams().RPCPort());
837 // for reading an external config file. does not clear the data dir cache
838 bool ReadConfigFile(std::string chainName,
839 map<string, string>& mapSettingsRet,
840 map<string, vector<string> >& mapMultiSettingsRet)
842 boost::filesystem::ifstream streamConfig(GetConfigFile(chainName));
843 if (!streamConfig.good())
846 set<string> setOptions;
847 setOptions.insert("*");
849 for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
851 // Don't overwrite existing settings so command line settings override komodo.conf
852 string strKey = string("-") + it->string_key;
853 if (mapSettingsRet.count(strKey) == 0)
855 mapSettingsRet[strKey] = it->value[0];
856 // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
857 InterpretNegativeSetting(strKey, mapSettingsRet);
859 mapMultiSettingsRet[strKey].push_back(it->value[0]);
865 boost::filesystem::path GetPidFile()
867 boost::filesystem::path pathPidFile(GetArg("-pid", "verusd.pid"));
868 if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
872 void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
874 FILE* file = fopen(path.string().c_str(), "w");
877 fprintf(file, "%d\n", pid);
883 bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
886 return MoveFileExA(src.string().c_str(), dest.string().c_str(),
887 MOVEFILE_REPLACE_EXISTING) != 0;
889 int rc = std::rename(src.string().c_str(), dest.string().c_str());
895 * Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
896 * Specifically handles case where path p exists, but it wasn't possible for the user to
897 * write to the parent directory.
899 bool TryCreateDirectory(const boost::filesystem::path& p)
903 return boost::filesystem::create_directory(p);
904 } catch (const boost::filesystem::filesystem_error&) {
905 if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p))
909 // create_directory didn't create the directory, it had to have existed already
913 void FileCommit(FILE *fileout)
915 fflush(fileout); // harmless if redundantly called
917 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout));
918 FlushFileBuffers(hFile);
920 #if defined(__linux__) || defined(__NetBSD__)
921 fdatasync(fileno(fileout));
922 #elif defined(__APPLE__) && defined(F_FULLFSYNC)
923 fcntl(fileno(fileout), F_FULLFSYNC, 0);
925 fsync(fileno(fileout));
930 bool TruncateFile(FILE *file, unsigned int length) {
932 return _chsize(_fileno(file), length) == 0;
934 return ftruncate(fileno(file), length) == 0;
939 * this function tries to raise the file descriptor limit to the requested number.
940 * It returns the actual file descriptor limit (which may be more or less than nMinFD)
942 int RaiseFileDescriptorLimit(int nMinFD) {
946 struct rlimit limitFD;
947 if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
948 if (limitFD.rlim_cur < (rlim_t)nMinFD) {
949 limitFD.rlim_cur = nMinFD;
950 if (limitFD.rlim_cur > limitFD.rlim_max)
951 limitFD.rlim_cur = limitFD.rlim_max;
952 setrlimit(RLIMIT_NOFILE, &limitFD);
953 getrlimit(RLIMIT_NOFILE, &limitFD);
955 return limitFD.rlim_cur;
957 return nMinFD; // getrlimit failed, assume it's fine
962 * this function tries to make a particular range of a file allocated (corresponding to disk space)
963 * it is advisory, and the range specified in the arguments will never contain live data
965 void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
967 // Windows-specific version
968 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
969 LARGE_INTEGER nFileSize;
970 int64_t nEndPos = (int64_t)offset + length;
971 nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
972 nFileSize.u.HighPart = nEndPos >> 32;
973 SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
975 #elif defined(MAC_OSX)
976 // OSX specific version
978 fst.fst_flags = F_ALLOCATECONTIG;
979 fst.fst_posmode = F_PEOFPOSMODE;
981 fst.fst_length = (off_t)offset + length;
982 fst.fst_bytesalloc = 0;
983 if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
984 fst.fst_flags = F_ALLOCATEALL;
985 fcntl(fileno(file), F_PREALLOCATE, &fst);
987 ftruncate(fileno(file), fst.fst_length);
988 #elif defined(__linux__)
989 // Version using posix_fallocate
990 off_t nEndPos = (off_t)offset + length;
991 posix_fallocate(fileno(file), 0, nEndPos);
994 // TODO: just write one byte per block
995 static const char buf[65536] = {};
996 fseek(file, offset, SEEK_SET);
998 unsigned int now = 65536;
1001 fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
1007 void ShrinkDebugFile()
1009 // Scroll debug.log if it's getting too big
1010 boost::filesystem::path pathLog = GetDataDir() / "debug.log";
1011 FILE* file = fopen(pathLog.string().c_str(), "r");
1012 if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000)
1014 // Restart the file with some of the end
1015 std::vector <char> vch(200000,0);
1016 fseek(file, -((long)vch.size()), SEEK_END);
1017 int nBytes = fread(begin_ptr(vch), 1, vch.size(), file);
1020 file = fopen(pathLog.string().c_str(), "w");
1023 fwrite(begin_ptr(vch), 1, nBytes, file);
1027 else if (file != NULL)
1032 boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
1034 namespace fs = boost::filesystem;
1036 char pszPath[MAX_PATH] = "";
1038 if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
1040 return fs::path(pszPath);
1043 LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
1044 return fs::path("");
1048 boost::filesystem::path GetTempPath() {
1049 #if BOOST_FILESYSTEM_VERSION == 3
1050 return boost::filesystem::temp_directory_path();
1052 // TODO: remove when we don't support filesystem v2 anymore
1053 boost::filesystem::path path;
1055 char pszPath[MAX_PATH] = "";
1057 if (GetTempPathA(MAX_PATH, pszPath))
1058 path = boost::filesystem::path(pszPath);
1060 path = boost::filesystem::path("/tmp");
1062 if (path.empty() || !boost::filesystem::is_directory(path)) {
1063 LogPrintf("GetTempPath(): failed to find temp path\n");
1064 return boost::filesystem::path("");
1070 void runCommand(const std::string& strCommand)
1072 int nErr = ::system(strCommand.c_str());
1074 LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
1077 void RenameThread(const char* name)
1079 #if defined(PR_SET_NAME)
1080 // Only the first 15 characters are used (16 - NUL terminator)
1081 ::prctl(PR_SET_NAME, name, 0, 0, 0);
1082 #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
1083 pthread_set_name_np(pthread_self(), name);
1085 #elif defined(MAC_OSX)
1086 pthread_setname_np(name);
1088 // Prevent warnings for unused parameters...
1093 void SetupEnvironment()
1095 // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
1096 // may be invalid, in which case the "C" locale is used as fallback.
1097 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
1099 std::locale(""); // Raises a runtime error if current locale is invalid
1100 } catch (const std::runtime_error&) {
1101 setenv("LC_ALL", "C", 1);
1104 // The path locale is lazy initialized and to avoid deinitialization errors
1105 // in multithreading environments, it is set explicitly by the main thread.
1106 // A dummy locale is used to extract the internal default locale, used by
1107 // boost::filesystem::path, which is then used to explicitly imbue the path.
1108 std::locale loc = boost::filesystem::path::imbue(std::locale::classic());
1109 boost::filesystem::path::imbue(loc);
1112 bool SetupNetworking()
1115 // Initialize Windows Sockets
1117 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1118 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
1124 void SetThreadPriority(int nPriority)
1127 SetThreadPriority(GetCurrentThread(), nPriority);
1130 setpriority(PRIO_THREAD, 0, nPriority);
1131 #else // PRIO_THREAD
1132 setpriority(PRIO_PROCESS, 0, nPriority);
1133 #endif // PRIO_THREAD
1137 std::string PrivacyInfo()
1140 FormatParagraph(strprintf(_("In order to ensure you are adequately protecting your privacy when using Zcash, please see <%s>."),
1141 "https://z.cash/support/security/")) + "\n";
1144 std::string LicenseInfo()
1147 FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" +
1148 FormatParagraph(strprintf(_("Copyright (C) 2015-%i The Zcash Developers"), COPYRIGHT_YEAR)) + "\n" +
1149 FormatParagraph(strprintf(_("Copyright (C) 2015-%i jl777 and SuperNET developers"), COPYRIGHT_YEAR)) + "\n" +
1150 FormatParagraph(strprintf(_("Copyright (C) 2018-%i The Verus developers"), COPYRIGHT_YEAR)) + "\n" +
1152 FormatParagraph(_("This is experimental software.")) + "\n" +
1154 FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or <https://www.opensource.org/licenses/mit-license.php>.")) + "\n" +
1156 FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young.")) +
1162 return boost::thread::physical_concurrency();