7 #if defined(HAVE_CONFIG_H) 23 #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) 25 #include <pthread_np.h> 33 #ifdef _POSIX_C_SOURCE 34 #undef _POSIX_C_SOURCE 37 #define _POSIX_C_SOURCE 200112L 43 #include <sys/resource.h> 49 #pragma warning(disable:4786) 50 #pragma warning(disable:4804) 51 #pragma warning(disable:4805) 52 #pragma warning(disable:4717) 58 #define _WIN32_WINNT 0x0501 63 #define _WIN32_IE 0x0501 65 #define WIN32_LEAN_AND_MEAN 1 74 #ifdef HAVE_SYS_PRCTL_H 75 #include <sys/prctl.h> 78 #include <boost/algorithm/string/case_conv.hpp> 79 #include <boost/algorithm/string/join.hpp> 80 #include <boost/algorithm/string/predicate.hpp> 81 #include <boost/algorithm/string/split.hpp> 82 #include <boost/algorithm/string/classification.hpp> 83 #include <boost/filesystem.hpp> 84 #include <boost/filesystem/fstream.hpp> 85 #include <boost/foreach.hpp> 86 #include <boost/program_options/detail/config_file.hpp> 87 #include <boost/program_options/parsers.hpp> 88 #include <boost/thread.hpp> 89 #include <openssl/crypto.h> 90 #include <openssl/rand.h> 91 #include <openssl/conf.h> 99 namespace program_options {
100 std::string to_internal(
const std::string&);
141 if (mode & CRYPTO_LOCK) {
156 for (
int i = 0; i < CRYPTO_num_locks(); i++)
180 CRYPTO_set_locking_callback(NULL);
181 for (
int i = 0; i < CRYPTO_num_locks(); i++)
216 return fwrite(str.data(), 1, str.size(),
fp);
233 boost::filesystem::path pathDebug =
GetDataDir() /
"debug.log";
234 fileout = fopen(pathDebug.string().c_str(),
"a");
249 if (category != NULL)
255 static boost::thread_specific_ptr<set<string> > ptrCategory;
258 if (ptrCategory.get() != NULL) {
260 ptrCategory.release();
265 if (ptrCategory.get() == NULL)
269 for (
int i = 0; i < (int)
mapMultiArgs[
"-debug"].size(); ++i)
271 const vector<string>& categories =
mapMultiArgs[
"-debug"];
272 ptrCategory.reset(
new set<string>(categories.begin(), categories.end()));
275 if(ptrCategory->count(
string(
"dash"))) {
276 ptrCategory->insert(
string(
"privatesend"));
277 ptrCategory->insert(
string(
"instantsend"));
278 ptrCategory->insert(
string(
"masternode"));
279 ptrCategory->insert(
string(
"spork"));
280 ptrCategory->insert(
string(
"keepass"));
281 ptrCategory->insert(
string(
"mnpayments"));
282 ptrCategory->insert(
string(
"gobject"));
285 const set<string>& setCategories = *ptrCategory.get();
288 if (setCategories.count(
string(
"")) == 0 &&
289 setCategories.count(
string(
"1")) == 0 &&
290 setCategories.count(
string(category)) == 0)
308 if (*fStartedNewLine) {
312 strStamped +=
strprintf(
".%06d", nTimeMicros%1000000);
313 strStamped +=
' ' + str;
327 string strThreadLogged;
334 if (*fStartedNewLine)
335 strThreadLogged =
strprintf(
"%16s | %s", strThreadName.c_str(), str.c_str());
337 strThreadLogged = str;
339 return strThreadLogged;
345 static bool fStartedNewLine =
true;
348 std::string strTimestamped =
LogTimestampStr(strThreadLogged, &fStartedNewLine);
350 if (!str.empty() && str[str.size()-1] ==
'\n')
351 fStartedNewLine =
true;
353 fStartedNewLine =
false;
358 ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(),
stdout);
369 ret = strTimestamped.length();
377 boost::filesystem::path pathDebug =
GetDataDir() /
"debug.log";
378 if (freopen(pathDebug.string().c_str(),
"a",
fileout) != NULL)
391 if (strValue.empty())
393 return (
atoi(strValue) != 0);
399 if (strKey.length()>3 && strKey[0]==
'-' && strKey[1]==
'n' && strKey[2]==
'o')
401 strKey =
"-" + strKey.substr(3);
411 for (
int i = 1; i < argc; i++)
413 std::string str(argv[i]);
414 std::string strValue;
415 size_t is_index = str.find(
'=');
416 if (is_index != std::string::npos)
418 strValue = str.substr(is_index+1);
419 str = str.substr(0, is_index);
422 boost::to_lower(str);
423 if (boost::algorithm::starts_with(str,
"/"))
424 str =
"-" + str.substr(1);
432 if (str.length() > 1 && str[1] ==
'-')
441 std::string
GetArg(
const std::string& strArg,
const std::string& strDefault)
448 int64_t
GetArg(
const std::string& strArg, int64_t nDefault)
462 bool SoftSetArg(
const std::string& strArg,
const std::string& strValue)
483 return std::string(message) + std::string(
"\n\n");
486 std::string
HelpMessageOpt(
const std::string &option,
const std::string &message) {
487 return std::string(
optIndent,
' ') + std::string(option) +
488 std::string(
"\n") + std::string(
msgIndent,
' ') +
497 GetModuleFileNameA(NULL, pszModule,
sizeof(pszModule));
499 const char* pszModule =
"dash";
503 "EXCEPTION: %s \n%s \n%s in %s \n",
typeid(*pex).name(), pex->what(), pszModule, pszThread);
506 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
512 LogPrintf(
"\n\n************************\n%s\n", message);
513 fprintf(
stderr,
"\n\n************************\n%s\n", message.c_str());
518 namespace fs = boost::filesystem;
525 return GetSpecialFolderPath(CSIDL_APPDATA) /
"DashCore";
528 char* pszHome = getenv(
"HOME");
529 if (pszHome == NULL || strlen(pszHome) == 0)
530 pathRet = fs::path(
"/");
532 pathRet = fs::path(pszHome);
535 return pathRet /
"Library/Application Support/DashCore";
538 return pathRet /
".dashcore";
549 namespace fs = boost::filesystem;
560 if (
mapArgs.count(
"-datadir")) {
561 path = fs::system_complete(
mapArgs[
"-datadir"]);
562 if (!fs::is_directory(path)) {
572 fs::create_directories(path);
582 namespace fs = boost::filesystem;
588 if (!backupsDir.empty())
591 if (
mapArgs.count(
"-walletbackupsdir")) {
592 backupsDir = fs::absolute(
mapArgs[
"-walletbackupsdir"]);
594 if (fs::is_directory(backupsDir))
return backupsDir;
596 LogPrintf(
"%s: Warning: incorrect parameter -walletbackupsdir, path must exist! Using default path.\n", __func__);
597 strMiscWarning =
_(
"Warning: incorrect parameter -walletbackupsdir, path must exist! Using default path.");
614 if (!pathConfigFile.is_complete())
615 pathConfigFile =
GetDataDir(
false) / pathConfigFile;
617 return pathConfigFile;
622 boost::filesystem::path pathConfigFile(
GetArg(
"-mnconf",
"masternode.conf"));
623 if (!pathConfigFile.is_complete()) pathConfigFile =
GetDataDir() / pathConfigFile;
624 return pathConfigFile;
628 map<
string, vector<string> >& mapMultiSettingsRet)
631 if (!streamConfig.good()){
633 FILE* configFile = fopen(
GetConfigFile().
string().c_str(),
"a");
634 if (configFile != NULL)
639 set<string> setOptions;
640 setOptions.insert(
"*");
642 for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
645 string strKey = string(
"-") + it->string_key;
646 string strValue = it->value[0];
648 if (mapSettingsRet.count(strKey) == 0)
649 mapSettingsRet[strKey] = strValue;
650 mapMultiSettingsRet[strKey].push_back(strValue);
660 if (!pathPidFile.is_complete()) pathPidFile =
GetDataDir() / pathPidFile;
666 FILE*
file = fopen(path.string().c_str(),
"w");
669 fprintf(
file,
"%d\n", pid);
675 bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
678 return MoveFileExA(src.string().c_str(), dest.string().c_str(),
679 MOVEFILE_REPLACE_EXISTING) != 0;
681 int rc = std::rename(src.string().c_str(), dest.string().c_str());
695 return boost::filesystem::create_directory(
p);
696 }
catch (
const boost::filesystem::filesystem_error&) {
697 if (!boost::filesystem::exists(
p) || !boost::filesystem::is_directory(
p))
709 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(
fileout));
710 FlushFileBuffers(hFile);
712 #if defined(__linux__) || defined(__NetBSD__) 714 #elif defined(__APPLE__) && defined(F_FULLFSYNC) 715 fcntl(fileno(
fileout), F_FULLFSYNC, 0);
724 return _chsize(_fileno(
file), length) == 0;
726 return ftruncate(fileno(
file), length) == 0;
738 struct rlimit limitFD;
739 if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
740 if (limitFD.rlim_cur < (rlim_t)nMinFD) {
741 limitFD.rlim_cur = nMinFD;
742 if (limitFD.rlim_cur > limitFD.rlim_max)
743 limitFD.rlim_cur = limitFD.rlim_max;
744 setrlimit(RLIMIT_NOFILE, &limitFD);
745 getrlimit(RLIMIT_NOFILE, &limitFD);
747 return limitFD.rlim_cur;
760 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(
file));
761 LARGE_INTEGER nFileSize;
762 int64_t nEndPos = (int64_t)offset + length;
763 nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
764 nFileSize.u.HighPart = nEndPos >> 32;
765 SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
767 #elif defined(MAC_OSX) 770 fst.fst_flags = F_ALLOCATECONTIG;
771 fst.fst_posmode = F_PEOFPOSMODE;
773 fst.fst_length = (off_t)offset + length;
774 fst.fst_bytesalloc = 0;
775 if (fcntl(fileno(
file), F_PREALLOCATE, &fst) == -1) {
776 fst.fst_flags = F_ALLOCATEALL;
777 fcntl(fileno(
file), F_PREALLOCATE, &fst);
779 ftruncate(fileno(
file), fst.fst_length);
780 #elif defined(__linux__) 782 off_t nEndPos = (off_t)offset + length;
783 posix_fallocate(fileno(
file), 0, nEndPos);
787 static const char buf[65536] = {};
788 fseek(
file, offset, SEEK_SET);
790 unsigned int now = 65536;
793 fwrite(buf, 1, now,
file);
802 constexpr
size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
804 boost::filesystem::path pathLog =
GetDataDir() /
"debug.log";
805 FILE*
file = fopen(pathLog.string().c_str(),
"r");
808 if (
file && boost::filesystem::file_size(pathLog) > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10))
811 std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
812 fseek(
file, -((
long)vch.size()), SEEK_END);
816 file = fopen(pathLog.string().c_str(),
"w");
823 else if (
file != NULL)
828 boost::filesystem::path GetSpecialFolderPath(
int nFolder,
bool fCreate)
830 namespace fs = boost::filesystem;
834 if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
836 return fs::path(pszPath);
839 LogPrintf(
"SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
845 #if BOOST_FILESYSTEM_VERSION == 3 846 return boost::filesystem::temp_directory_path();
849 boost::filesystem::path path;
853 if (GetTempPathA(
MAX_PATH, pszPath))
854 path = boost::filesystem::path(pszPath);
856 path = boost::filesystem::path(
"/tmp");
858 if (path.empty() || !boost::filesystem::is_directory(path)) {
859 LogPrintf(
"GetTempPath(): failed to find temp path\n");
860 return boost::filesystem::path(
"");
868 int nErr = ::system(strCommand.c_str());
870 LogPrintf(
"runCommand error: system(%s) returned %d\n", strCommand, nErr);
875 #if defined(PR_SET_NAME) 877 ::prctl(PR_SET_NAME,
name, 0, 0, 0);
878 #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) 879 pthread_set_name_np(pthread_self(),
name);
881 #elif defined(MAC_OSX) 882 pthread_setname_np(
name);
892 #if defined(PR_GET_NAME) 894 ::prctl(PR_GET_NAME,
name, 0, 0, 0);
895 #elif defined(MAC_OSX) 896 pthread_getname_np(pthread_self(),
name, 16);
901 return std::string(
name);
908 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) 911 }
catch (
const std::runtime_error&) {
912 setenv(
"LC_ALL",
"C", 1);
919 std::locale loc = boost::filesystem::path::imbue(std::locale::classic());
920 boost::filesystem::path::imbue(loc);
928 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
929 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
941 setpriority(PRIO_THREAD, 0, nPriority);
943 setpriority(PRIO_PROCESS, 0, nPriority);
944 #endif // PRIO_THREAD 950 #if BOOST_VERSION >= 105600 951 return boost::thread::physical_concurrency();
952 #else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores 953 return boost::thread::hardware_concurrency();
960 std::vector<std::string> tokens;
961 boost::split(tokens, strVersion, boost::is_any_of(
"."));
962 if(tokens.size() != 3)
963 throw std::bad_cast();
964 uint32_t nVersion = 0;
965 for(
unsigned idx = 0; idx < 3; idx++)
967 if(tokens[idx].length() == 0)
968 throw std::bad_cast();
969 uint32_t value = boost::lexical_cast<uint32_t>(tokens[idx]);
971 throw std::bad_cast();
980 if((nVersion >> 24) > 0)
981 throw std::bad_cast();
983 throw std::bad_cast();
984 std::array<std::string, 3> tokens;
985 for(
unsigned idx = 0; idx < 3; idx++)
987 unsigned shift = (2 - idx) * 8;
988 uint32_t byteValue = (nVersion >> shift) & 0xff;
989 tokens[idx] = boost::lexical_cast<std::string>(byteValue);
991 return boost::join(tokens,
".");
1000 catch(
const std::bad_cast&)
1002 return "invalid_version";
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
std::string HelpMessageOpt(const std::string &option, const std::string &message)
const std::string & DataDir() const
#define NO_THREAD_SAFETY_ANALYSIS
static list< string > * vMsgsBeforeOpenLog
void SetThreadPriority(int nPriority)
int64_t GetLogTimeMicros()
const char *const BITCOIN_CONF_FILENAME
void FileCommit(FILE *fileout)
void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
const char *const BITCOIN_PID_FILENAME
static boost::filesystem::path backupsDirCached
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
boost::filesystem::path GetTempPath()
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)
boost::filesystem::path GetPidFile()
static boost::once_flag debugPrintInitFlag
const CBaseChainParams & BaseParams()
static const int msgIndent
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
void locking_callback(int mode, int i, const char *file, int line) NO_THREAD_SAFETY_ANALYSIS
static const bool DEFAULT_LOGTIMEMICROS
void RenameThread(const char *name)
static const int screenWidth
volatile bool fReopenDebugLog
static const bool DEFAULT_LOGTIMESTAMPS
static boost::filesystem::path pathCachedNetSpecific
int RaiseFileDescriptorLimit(int nMinFD)
uint32_t StringVersionToInt(const std::string &strVersion)
Converts version strings to 4-byte unsigned integer.
class CInit instance_of_cinit
std::string SafeIntVersionToString(uint32_t nVersion)
Copy of the IntVersionToString, that returns "Invalid version" string instead of throwing std::bad_ca...
CTranslationInterface translationInterface
static boost::filesystem::path pathCached
static const bool DEFAULT_LOGIPS
bool TruncateFile(FILE *file, unsigned int length)
bool GetBoolArg(const std::string &strArg, bool fDefault)
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
#define LEAVE_CRITICAL_SECTION(cs)
static int FileWriteStr(const std::string &str, FILE *fp)
bool TryCreateDirectory(const boost::filesystem::path &p)
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length)
static const int optIndent
std::string FormatParagraph(const std::string &in, size_t width, size_t indent)
static std::string FormatException(const std::exception *pex, const char *pszThread)
std::string IntVersionToString(uint32_t nVersion)
Converts version as 4-byte unsigned integer to string.
std::string GetThreadName()
static CCriticalSection csBackupsDirCached
static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
static CCriticalSection csPathCached
static const bool DEFAULT_LOGTHREADNAMES
void ParseParameters(int argc, const char *const argv[])
V::value_type * begin_ptr(V &v)
static boost::mutex * mutexDebugLog
#define ENTER_CRITICAL_SECTION(cs)
const boost::filesystem::path & GetBackupsDir()
void ReadConfigFile(map< string, string > &mapSettingsRet, map< string, vector< string > > &mapMultiSettingsRet)
static void InterpretNegativeSetting(std::string &strKey, std::string &strValue)
void runCommand(const std::string &strCommand)
bool LogAcceptCategory(const char *category)
int64_t atoi64(const char *psz)
boost::filesystem::path GetMasternodeConfigFile()
AnnotatedMixin< boost::recursive_mutex > CCriticalSection
static CCriticalSection ** ppmutexOpenSSL
std::string GetArg(const std::string &strArg, const std::string &strDefault)
static bool InterpretBool(const std::string &strValue)
static std::string LogThreadNameStr(const std::string &str, bool *fStartedNewLine)
static void DebugPrintInit()
map< string, vector< string > > mapMultiArgs
std::string HelpMessageGroup(const std::string &message)
int LogPrintStr(const std::string &str)
std::string _(const char *psz)
int atoi(const std::string &str)
map< string, string > mapArgs
boost::filesystem::path GetDefaultDataDir()
boost::filesystem::path GetConfigFile()