aboutsummaryrefslogtreecommitdiff
path: root/src/util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.cpp')
-rw-r--r--src/util.cpp502
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;
-}