diff options
Diffstat (limited to 'src/util.cpp')
| -rw-r--r-- | src/util.cpp | 502 |
1 files changed, 276 insertions, 226 deletions
diff --git a/src/util.cpp b/src/util.cpp index d8f05cb9f..8cfd1c2e0 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,80 +1,101 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "util.h" + +#include "chainparams.h" +#include "netbase.h" #include "sync.h" -#include "version.h" #include "ui_interface.h" -#include <boost/algorithm/string/join.hpp> -#include <boost/algorithm/string/case_conv.hpp> // for to_lower() -#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith() - -// Work around clang compilation problem in Boost 1.46: -// /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 -// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options -// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION -namespace boost { - namespace program_options { - std::string to_internal(const std::string&); - } -} +#include "uint256.h" +#include "version.h" -#include <boost/program_options/detail/config_file.hpp> -#include <boost/program_options/parsers.hpp> -#include <boost/filesystem.hpp> -#include <boost/filesystem/fstream.hpp> -#include <boost/foreach.hpp> -#include <boost/thread.hpp> -#include <openssl/crypto.h> -#include <openssl/rand.h> #include <stdarg.h> -#ifdef WIN32 +#ifndef WIN32 +// for posix_fallocate +#ifdef __linux_ + +#ifdef _POSIX_C_SOURCE +#undef _POSIX_C_SOURCE +#endif + +#define _POSIX_C_SOURCE 200112L +#include <sys/prctl.h> + +#endif + +#include <algorithm> +#include <fcntl.h> +#include <sys/resource.h> +#include <sys/stat.h> + +#else + #ifdef _MSC_VER #pragma warning(disable:4786) #pragma warning(disable:4804) #pragma warning(disable:4805) #pragma warning(disable:4717) #endif + #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif #define _WIN32_WINNT 0x0501 + #ifdef _WIN32_IE #undef _WIN32_IE #endif #define _WIN32_IE 0x0501 + #define WIN32_LEAN_AND_MEAN 1 #ifndef NOMINMAX #define NOMINMAX #endif + #include <io.h> /* for _commit */ -#include "shlobj.h" -#elif defined(__linux__) -# include <sys/prctl.h> +#include <shlobj.h> #endif +#include <boost/algorithm/string/case_conv.hpp> // for to_lower() +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith() +#include <boost/filesystem.hpp> +#include <boost/filesystem/fstream.hpp> +#include <boost/foreach.hpp> +#include <boost/program_options/detail/config_file.hpp> +#include <boost/program_options/parsers.hpp> +#include <openssl/crypto.h> +#include <openssl/rand.h> + +// Work around clang compilation problem in Boost 1.46: +// /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 +// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options +// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION +namespace boost { + namespace program_options { + std::string to_internal(const std::string&); + } +} + + using namespace std; map<string, string> mapArgs; map<string, vector<string> > mapMultiArgs; bool fDebug = false; -bool fDebugNet = false; bool fPrintToConsole = false; -bool fPrintToDebugger = false; -volatile bool fRequestShutdown = false; -bool fShutdown = false; +bool fPrintToDebugLog = true; bool fDaemon = false; bool fServer = false; -bool fCommandLine = false; string strMiscWarning; -bool fTestNet = false; bool fNoListen = false; bool fLogTimestamps = false; -CMedianFilter<int64> vTimeOffsets(200,0); volatile bool fReopenDebugLog = false; +CClientUIInterface uiInterface; // Init OpenSSL library multithreading support static CCriticalSection** ppmutexOpenSSL; @@ -87,8 +108,6 @@ void locking_callback(int mode, int i, const char* file, int line) } } -LockedPageManager LockedPageManager::instance; - // Init class CInit { @@ -130,7 +149,7 @@ instance_of_cinit; void RandAddSeed() { // Seed with CPU performance counter - int64 nCounter = GetPerformanceCounter(); + int64_t nCounter = GetPerformanceCounter(); RAND_add(&nCounter, sizeof(nCounter), 1.5); memset(&nCounter, 0, sizeof(nCounter)); } @@ -140,7 +159,7 @@ void RandAddSeedPerfmon() RandAddSeed(); // This can take up to 2 seconds, so only do it every 10 minutes - static int64 nLastPerfmon; + static int64_t nLastPerfmon; if (GetTime() < nLastPerfmon + 10 * 60) return; nLastPerfmon = GetTime(); @@ -157,20 +176,20 @@ void RandAddSeedPerfmon() { RAND_add(pdata, nSize, nSize/100.0); OPENSSL_cleanse(pdata, nSize); - printf("RandAddSeed() %lu bytes\n", nSize); + LogPrint("rand", "RandAddSeed() %lu bytes\n", nSize); } #endif } -uint64 GetRand(uint64 nMax) +uint64_t GetRand(uint64_t nMax) { if (nMax == 0) return 0; // The range of the random source must be a multiple of the modulus // to give every possible output value an equal possibility - uint64 nRange = (std::numeric_limits<uint64>::max() / nMax) * nMax; - uint64 nRand = 0; + uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax; + uint64_t nRand = 0; do RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); while (nRand >= nRange); @@ -189,15 +208,7 @@ uint256 GetRandHash() return hash; } - - - - - - -// -// OutputDebugStringF (aka printf -- there is a #define that we really -// should get rid of one day) has been broken a couple of times now +// LogPrintf() has been broken a couple of times now // by well-meaning people adding mutexes in the most straightforward way. // It breaks because it may be called by global destructors during shutdown. // Since the order of destruction of static/global objects is undefined, @@ -224,18 +235,43 @@ static void DebugPrintInit() mutexDebugLog = new boost::mutex(); } -int OutputDebugStringF(const char* pszFormat, ...) +bool LogAcceptCategory(const char* category) +{ + if (category != NULL) + { + if (!fDebug) + return false; + + // Give each thread quick access to -debug settings. + // This helps prevent issues debugging global destructors, + // where mapMultiArgs might be deleted before another + // global destructor calls LogPrint() + static boost::thread_specific_ptr<set<string> > ptrCategory; + if (ptrCategory.get() == NULL) + { + const vector<string>& categories = mapMultiArgs["-debug"]; + ptrCategory.reset(new set<string>(categories.begin(), categories.end())); + // thread_specific_ptr automatically deletes the set when the thread ends. + } + const set<string>& setCategories = *ptrCategory.get(); + + // if not debugging everything and not debugging specific category, LogPrint does nothing. + if (setCategories.count(string("")) == 0 && + setCategories.count(string(category)) == 0) + return false; + } + return true; +} + +int LogPrintStr(const std::string &str) { int ret = 0; // Returns total number of characters written if (fPrintToConsole) { // print to console - va_list arg_ptr; - va_start(arg_ptr, pszFormat); - ret += vprintf(pszFormat, arg_ptr); - va_end(arg_ptr); + ret = fwrite(str.data(), 1, str.size(), stdout); } - else if (!fPrintToDebugger) + else if (fPrintToDebugLog) { static bool fStartedNewLine = true; boost::call_once(&DebugPrintInit, debugPrintInitFlag); @@ -256,113 +292,24 @@ int OutputDebugStringF(const char* pszFormat, ...) // Debug print useful for profiling if (fLogTimestamps && fStartedNewLine) ret += fprintf(fileout, "%s ", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str()); - if (pszFormat[strlen(pszFormat) - 1] == '\n') + if (!str.empty() && str[str.size()-1] == '\n') fStartedNewLine = true; else fStartedNewLine = false; - va_list arg_ptr; - va_start(arg_ptr, pszFormat); - ret += vfprintf(fileout, pszFormat, arg_ptr); - va_end(arg_ptr); + ret = fwrite(str.data(), 1, str.size(), fileout); } -#ifdef WIN32 - if (fPrintToDebugger) - { - static CCriticalSection cs_OutputDebugStringF; - - // accumulate and output a line at a time - { - LOCK(cs_OutputDebugStringF); - static std::string buffer; - - va_list arg_ptr; - va_start(arg_ptr, pszFormat); - buffer += vstrprintf(pszFormat, arg_ptr); - va_end(arg_ptr); - - int line_start = 0, line_end; - while((line_end = buffer.find('\n', line_start)) != -1) - { - OutputDebugStringA(buffer.substr(line_start, line_end - line_start).c_str()); - line_start = line_end + 1; - ret += line_end-line_start; - } - buffer.erase(0, line_start); - } - } -#endif return ret; } -string vstrprintf(const char *format, va_list ap) -{ - char buffer[50000]; - char* p = buffer; - int limit = sizeof(buffer); - int ret; - loop - { - va_list arg_ptr; - va_copy(arg_ptr, ap); -#ifdef WIN32 - ret = _vsnprintf(p, limit, format, arg_ptr); -#else - ret = vsnprintf(p, limit, format, arg_ptr); -#endif - va_end(arg_ptr); - if (ret >= 0 && ret < limit) - break; - if (p != buffer) - delete[] p; - limit *= 2; - p = new char[limit]; - if (p == NULL) - throw std::bad_alloc(); - } - string str(p, p+ret); - if (p != buffer) - delete[] p; - return str; -} - -string real_strprintf(const char *format, int dummy, ...) -{ - va_list arg_ptr; - va_start(arg_ptr, dummy); - string str = vstrprintf(format, arg_ptr); - va_end(arg_ptr); - return str; -} - -string real_strprintf(const std::string &format, int dummy, ...) -{ - va_list arg_ptr; - va_start(arg_ptr, dummy); - string str = vstrprintf(format.c_str(), arg_ptr); - va_end(arg_ptr); - return str; -} - -bool error(const char *format, ...) -{ - va_list arg_ptr; - va_start(arg_ptr, format); - std::string str = vstrprintf(format, arg_ptr); - va_end(arg_ptr); - printf("ERROR: %s\n", str.c_str()); - return false; -} - - void ParseString(const string& str, char c, vector<string>& v) { if (str.empty()) return; string::size_type i1 = 0; string::size_type i2; - loop + while (true) { i2 = str.find(c, i1); if (i2 == str.npos) @@ -376,14 +323,14 @@ void ParseString(const string& str, char c, vector<string>& v) } -string FormatMoney(int64 n, bool fPlus) +string FormatMoney(int64_t n, bool fPlus) { // Note: not using straight sprintf here because we do NOT want // localized number formatting. - int64 n_abs = (n > 0 ? n : -n); - int64 quotient = n_abs/COIN; - int64 remainder = n_abs%COIN; - string str = strprintf("%"PRI64d".%08"PRI64d, quotient, remainder); + int64_t n_abs = (n > 0 ? n : -n); + int64_t quotient = n_abs/COIN; + int64_t remainder = n_abs%COIN; + string str = strprintf("%"PRId64".%08"PRId64, quotient, remainder); // Right-trim excess zeros before the decimal point: int nTrim = 0; @@ -400,15 +347,15 @@ string FormatMoney(int64 n, bool fPlus) } -bool ParseMoney(const string& str, int64& nRet) +bool ParseMoney(const string& str, int64_t& nRet) { return ParseMoney(str.c_str(), nRet); } -bool ParseMoney(const char* pszIn, int64& nRet) +bool ParseMoney(const char* pszIn, int64_t& nRet) { string strWhole; - int64 nUnits = 0; + int64_t nUnits = 0; const char* p = pszIn; while (isspace(*p)) p++; @@ -417,7 +364,7 @@ bool ParseMoney(const char* pszIn, int64& nRet) if (*p == '.') { p++; - int64 nMult = CENT*10; + int64_t nMult = CENT*10; while (isdigit(*p) && (nMult > 0)) { nUnits += nMult * (*p++ - '0'); @@ -438,15 +385,28 @@ bool ParseMoney(const char* pszIn, int64& nRet) return false; if (nUnits < 0 || nUnits > COIN) return false; - int64 nWhole = atoi64(strWhole); - int64 nValue = nWhole*COIN + nUnits; + int64_t nWhole = atoi64(strWhole); + int64_t nValue = nWhole*COIN + nUnits; nRet = nValue; return true; } +// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything +// even possibly remotely dangerous like & or > +static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@"); +string SanitizeString(const string& str) +{ + string strResult; + for (std::string::size_type i = 0; i < str.size(); i++) + { + if (safeChars.find(str[i]) != std::string::npos) + strResult.push_back(str[i]); + } + return strResult; +} -static const signed char phexdigit[256] = +const signed char p_util_hexdigit[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, @@ -466,9 +426,9 @@ static const signed char phexdigit[256] = bool IsHex(const string& str) { - BOOST_FOREACH(unsigned char c, str) + BOOST_FOREACH(char c, str) { - if (phexdigit[c] < 0) + if (HexDigit(c) < 0) return false; } return (str.size() > 0) && (str.size()%2 == 0); @@ -478,15 +438,15 @@ vector<unsigned char> ParseHex(const char* psz) { // convert hex dump to vector vector<unsigned char> vch; - loop + while (true) { while (isspace(*psz)) psz++; - signed char c = phexdigit[(unsigned char)*psz++]; + signed char c = HexDigit(*psz++); if (c == (signed char)-1) break; unsigned char n = (c << 4); - c = phexdigit[(unsigned char)*psz++]; + c = HexDigit(*psz++); if (c == (signed char)-1) break; n |= c; @@ -509,7 +469,7 @@ static void InterpretNegativeSetting(string name, map<string, string>& mapSettin positive.append(name.begin()+3, name.end()); if (mapSettingsRet.count(positive) == 0) { - bool value = !GetBoolArg(name); + bool value = !GetBoolArg(name, false); mapSettingsRet[positive] = (value ? "1" : "0"); } } @@ -567,7 +527,7 @@ std::string GetArg(const std::string& strArg, const std::string& strDefault) return strDefault; } -int64 GetArg(const std::string& strArg, int64 nDefault) +int64_t GetArg(const std::string& strArg, int64_t nDefault) { if (mapArgs.count(strArg)) return atoi64(mapArgs[strArg]); @@ -932,7 +892,7 @@ string DecodeBase32(const string& str) bool WildcardMatch(const char* psz, const char* mask) { - loop + while (true) { switch (*mask) { @@ -985,13 +945,13 @@ static std::string FormatException(std::exception* pex, const char* pszThread) void LogException(std::exception* pex, const char* pszThread) { std::string message = FormatException(pex, pszThread); - printf("\n%s", message.c_str()); + LogPrintf("\n%s", message); } void PrintException(std::exception* pex, const char* pszThread) { std::string message = FormatException(pex, pszThread); - printf("\n\n************************\n%s\n", message.c_str()); + LogPrintf("\n\n************************\n%s\n", message); fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); strMiscWarning = message; throw; @@ -1000,7 +960,7 @@ void PrintException(std::exception* pex, const char* pszThread) void PrintExceptionContinue(std::exception* pex, const char* pszThread) { std::string message = FormatException(pex, pszThread); - printf("\n\n************************\n%s\n", message.c_str()); + LogPrintf("\n\n************************\n%s\n", message); fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); strMiscWarning = message; } @@ -1034,23 +994,25 @@ boost::filesystem::path GetDefaultDataDir() #endif } +static boost::filesystem::path pathCached[CChainParams::MAX_NETWORK_TYPES+1]; +static CCriticalSection csPathCached; + const boost::filesystem::path &GetDataDir(bool fNetSpecific) { namespace fs = boost::filesystem; - static fs::path pathCached[2]; - static CCriticalSection csPathCached; - static bool cachedPath[2] = {false, false}; + LOCK(csPathCached); + + int nNet = CChainParams::MAX_NETWORK_TYPES; + if (fNetSpecific) nNet = Params().NetworkID(); - fs::path &path = pathCached[fNetSpecific]; + fs::path &path = pathCached[nNet]; - // This can be called during exceptions by printf, so we cache the + // This can be called during exceptions by LogPrintf(), so we cache the // value so we don't have to do memory allocations after that. - if (cachedPath[fNetSpecific]) + if (!path.empty()) return path; - LOCK(csPathCached); - if (mapArgs.count("-datadir")) { path = fs::system_complete(mapArgs["-datadir"]); if (!fs::is_directory(path)) { @@ -1060,15 +1022,20 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) } else { path = GetDefaultDataDir(); } - if (fNetSpecific && GetBoolArg("-testnet", false)) - path /= "testnet3"; + if (fNetSpecific) + path /= Params().DataDir(); - fs::create_directory(path); + fs::create_directories(path); - cachedPath[fNetSpecific]=true; return path; } +void ClearDatadirCache() +{ + std::fill(&pathCached[0], &pathCached[CChainParams::MAX_NETWORK_TYPES+1], + boost::filesystem::path()); +} + boost::filesystem::path GetConfigFile() { boost::filesystem::path pathConfigFile(GetArg("-conf", "bitcoin.conf")); @@ -1098,6 +1065,8 @@ void ReadConfigFile(map<string, string>& mapSettingsRet, } mapMultiSettingsRet[strKey].push_back(it->value[0]); } + // If datadir is changed in .conf file: + ClearDatadirCache(); } boost::filesystem::path GetPidFile() @@ -1107,6 +1076,7 @@ boost::filesystem::path GetPidFile() return pathPidFile; } +#ifndef WIN32 void CreatePidFile(const boost::filesystem::path &path, pid_t pid) { FILE* file = fopen(path.string().c_str(), "w"); @@ -1116,6 +1086,7 @@ void CreatePidFile(const boost::filesystem::path &path, pid_t pid) fclose(file); } } +#endif bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) { @@ -1130,12 +1101,15 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) void FileCommit(FILE *fileout) { - fflush(fileout); // harmless if redundantly called + fflush(fileout); // harmless if redundantly called #ifdef WIN32 - _commit(_fileno(fileout)); + HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout)); + FlushFileBuffers(hFile); #else #if defined(__linux__) || defined(__NetBSD__) fdatasync(fileno(fileout)); + #elif defined(__APPLE__) && defined(F_FULLFSYNC) + fcntl(fileno(fileout), F_FULLFSYNC, 0); #else fsync(fileno(fileout)); #endif @@ -1152,9 +1126,67 @@ int GetFilesize(FILE* file) return nFilesize; } +bool TruncateFile(FILE *file, unsigned int length) { +#if defined(WIN32) + return _chsize(_fileno(file), length) == 0; +#else + return ftruncate(fileno(file), length) == 0; +#endif +} + +// this function tries to raise the file descriptor limit to the requested number. +// It returns the actual file descriptor limit (which may be more or less than nMinFD) +int RaiseFileDescriptorLimit(int nMinFD) { +#if defined(WIN32) + return 2048; +#else + struct rlimit limitFD; + if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) { + if (limitFD.rlim_cur < (rlim_t)nMinFD) { + limitFD.rlim_cur = nMinFD; + if (limitFD.rlim_cur > limitFD.rlim_max) + limitFD.rlim_cur = limitFD.rlim_max; + setrlimit(RLIMIT_NOFILE, &limitFD); + getrlimit(RLIMIT_NOFILE, &limitFD); + } + return limitFD.rlim_cur; + } + return nMinFD; // getrlimit failed, assume it's fine +#endif +} + // this function tries to make a particular range of a file allocated (corresponding to disk space) // it is advisory, and the range specified in the arguments will never contain live data void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) { +#if defined(WIN32) + // Windows-specific version + HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file)); + LARGE_INTEGER nFileSize; + int64_t nEndPos = (int64_t)offset + length; + nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF; + nFileSize.u.HighPart = nEndPos >> 32; + SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN); + SetEndOfFile(hFile); +#elif defined(MAC_OSX) + // OSX specific version + fstore_t fst; + fst.fst_flags = F_ALLOCATECONTIG; + fst.fst_posmode = F_PEOFPOSMODE; + fst.fst_offset = 0; + fst.fst_length = (off_t)offset + length; + fst.fst_bytesalloc = 0; + if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) { + fst.fst_flags = F_ALLOCATEALL; + fcntl(fileno(file), F_PREALLOCATE, &fst); + } + ftruncate(fileno(file), fst.fst_length); +#elif defined(__linux__) + // Version using posix_fallocate + off_t nEndPos = (off_t)offset + length; + posix_fallocate(fileno(file), 0, nEndPos); +#else + // Fallback version + // TODO: just write one byte per block static const char buf[65536] = {}; fseek(file, offset, SEEK_SET); while (length > 0) { @@ -1164,6 +1196,7 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) { fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway length -= now; } +#endif } void ShrinkDebugFile() @@ -1186,6 +1219,8 @@ void ShrinkDebugFile() fclose(file); } } + else if (file != NULL) + fclose(file); } @@ -1202,43 +1237,52 @@ void ShrinkDebugFile() // - Median of other nodes clocks // - The user (asking the user to fix the system clock if the first two disagree) // -static int64 nMockTime = 0; // For unit testing +static int64_t nMockTime = 0; // For unit testing -int64 GetTime() +int64_t GetTime() { if (nMockTime) return nMockTime; return time(NULL); } -void SetMockTime(int64 nMockTimeIn) +void SetMockTime(int64_t nMockTimeIn) { nMockTime = nMockTimeIn; } -static int64 nTimeOffset = 0; +static CCriticalSection cs_nTimeOffset; +static int64_t nTimeOffset = 0; + +int64_t GetTimeOffset() +{ + LOCK(cs_nTimeOffset); + return nTimeOffset; +} -int64 GetAdjustedTime() +int64_t GetAdjustedTime() { - return GetTime() + nTimeOffset; + return GetTime() + GetTimeOffset(); } -void AddTimeData(const CNetAddr& ip, int64 nTime) +void AddTimeData(const CNetAddr& ip, int64_t nTime) { - int64 nOffsetSample = nTime - GetTime(); + int64_t nOffsetSample = nTime - GetTime(); + LOCK(cs_nTimeOffset); // Ignore duplicates static set<CNetAddr> setKnown; if (!setKnown.insert(ip).second) return; // Add data + static CMedianFilter<int64_t> vTimeOffsets(200,0); vTimeOffsets.input(nOffsetSample); - printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); + LogPrintf("Added time data, samples %d, offset %+"PRId64" (%+"PRId64" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) { - int64 nMedian = vTimeOffsets.median(); - std::vector<int64> vSorted = vTimeOffsets.sorted(); + int64_t nMedian = vTimeOffsets.median(); + std::vector<int64_t> vSorted = vTimeOffsets.sorted(); // Only let other nodes change our time by so much if (abs64(nMedian) < 70 * 60) { @@ -1253,7 +1297,7 @@ void AddTimeData(const CNetAddr& ip, int64 nTime) { // If nobody has a time different than ours but within 5 minutes of ours, give a warning bool fMatch = false; - BOOST_FOREACH(int64 nOffset, vSorted) + BOOST_FOREACH(int64_t nOffset, vSorted) if (nOffset != 0 && abs64(nOffset) < 5 * 60) fMatch = true; @@ -1262,26 +1306,40 @@ void AddTimeData(const CNetAddr& ip, int64 nTime) fDone = true; string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly."); strMiscWarning = strMessage; - printf("*** %s\n", strMessage.c_str()); + LogPrintf("*** %s\n", strMessage); uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING); } } } if (fDebug) { - BOOST_FOREACH(int64 n, vSorted) - printf("%+"PRI64d" ", n); - printf("| "); + BOOST_FOREACH(int64_t n, vSorted) + LogPrintf("%+"PRId64" ", n); + LogPrintf("| "); } - printf("nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60); + LogPrintf("nTimeOffset = %+"PRId64" (%+"PRId64" minutes)\n", nTimeOffset, nTimeOffset/60); } } - - - - - - +uint32_t insecure_rand_Rz = 11; +uint32_t insecure_rand_Rw = 11; +void seed_insecure_rand(bool fDeterministic) +{ + //The seed values have some unlikely fixed points which we avoid. + if(fDeterministic) + { + insecure_rand_Rz = insecure_rand_Rw = 11; + } else { + uint32_t tmp; + do { + RAND_bytes((unsigned char*)&tmp, 4); + } while(tmp == 0 || tmp == 0x9068ffffU); + insecure_rand_Rz = tmp; + do { + RAND_bytes((unsigned char*)&tmp, 4); + } while(tmp == 0 || tmp == 0x464fffffU); + insecure_rand_Rw = tmp; + } +} string FormatVersion(int nVersion) { @@ -1320,7 +1378,7 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate) return fs::path(pszPath); } - printf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n"); + LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n"); return fs::path(""); } #endif @@ -1340,7 +1398,7 @@ boost::filesystem::path GetTempPath() { path = boost::filesystem::path("/tmp"); #endif if (path.empty() || !boost::filesystem::is_directory(path)) { - printf("GetTempPath(): failed to find temp path\n"); + LogPrintf("GetTempPath(): failed to find temp path\n"); return boost::filesystem::path(""); } return path; @@ -1351,7 +1409,7 @@ void runCommand(std::string strCommand) { int nErr = ::system(strCommand.c_str()); if (nErr) - printf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr); + LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr); } void RenameThread(const char* name) @@ -1365,9 +1423,12 @@ void RenameThread(const char* name) // removed. pthread_set_name_np(pthread_self(), name); -// This is XCode 10.6-and-later; bring back if we drop 10.5 support: -// #elif defined(MAC_OSX) -// pthread_setname_np(name); +#elif defined(MAC_OSX) && defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + +// pthread_setname_np is XCode 10.6-and-later +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 + pthread_setname_np(name); +#endif #else // Prevent warnings for unused parameters... @@ -1375,14 +1436,3 @@ void RenameThread(const char* name) #endif } -bool NewThread(void(*pfn)(void*), void* parg) -{ - try - { - boost::thread(pfn, parg); // thread detaches when out of scope - } catch(boost::thread_resource_error &e) { - printf("Error creating thread: %s\n", e.what()); - return false; - } - return true; -} |