2011-05-14 15:25:05 +00:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2012-02-07 16:28:30 +00:00
// Copyright (c) 2009-2012 The Bitcoin developers
2013-06-19 21:16:25 +00:00
// Copyright (c) 2013 The Primecoin developers
2011-05-14 15:25:05 +00:00
// Distributed under the MIT/X11 software license, see the accompanying
2012-05-18 14:02:28 +00:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2012-03-31 13:22:45 +00:00
2013-01-27 23:07:51 +00:00
# ifndef WIN32
// for posix_fallocate
# ifdef __linux__
# define _POSIX_C_SOURCE 200112L
# endif
# include <fcntl.h>
# include <sys/stat.h>
2013-04-25 22:46:47 +00:00
# include <sys/resource.h>
2013-01-27 23:07:51 +00:00
# endif
2012-04-15 20:10:54 +00:00
# include "util.h"
# include "version.h"
2014-01-26 13:43:02 +00:00
# include "allocators.h"
2011-12-16 21:26:14 +00:00
# include <boost/algorithm/string/join.hpp>
2012-10-02 19:36:39 +00:00
# include <boost/algorithm/string/case_conv.hpp> // for to_lower()
# include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
2012-04-15 09:42:40 +00:00
// 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 & ) ;
}
}
2011-06-18 16:46:01 +00:00
# include <boost/program_options/detail/config_file.hpp>
# include <boost/program_options/parsers.hpp>
2011-06-26 17:23:24 +00:00
# include <boost/filesystem.hpp>
2011-06-18 16:46:01 +00:00
# include <boost/filesystem/fstream.hpp>
# include <boost/foreach.hpp>
2012-03-02 19:24:38 +00:00
# include <boost/thread.hpp>
2012-04-15 20:10:54 +00:00
# include <openssl/crypto.h>
# include <openssl/rand.h>
2012-05-13 15:55:23 +00:00
# include <stdarg.h>
2012-04-15 20:10:54 +00:00
# ifdef WIN32
# 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
2012-05-03 00:21:43 +00:00
# define _WIN32_IE 0x0501
2012-04-15 20:10:54 +00:00
# define WIN32_LEAN_AND_MEAN 1
# ifndef NOMINMAX
# define NOMINMAX
# endif
2012-05-17 16:30:09 +00:00
# include <io.h> /* for _commit */
2012-04-15 20:10:54 +00:00
# include "shlobj.h"
2012-06-24 15:03:57 +00:00
# elif defined(__linux__)
# include <sys / prctl.h>
2012-04-15 20:10:54 +00:00
# endif
2011-05-14 15:25:05 +00:00
using namespace std ;
2014-01-26 13:43:02 +00:00
using namespace boost ;
2011-05-14 15:25:05 +00:00
map < string , string > mapArgs ;
map < string , vector < string > > mapMultiArgs ;
bool fDebug = false ;
2012-06-22 17:11:57 +00:00
bool fDebugNet = false ;
2011-05-14 15:25:05 +00:00
bool fPrintToConsole = false ;
bool fPrintToDebugger = false ;
bool fDaemon = false ;
bool fServer = false ;
bool fCommandLine = false ;
string strMiscWarning ;
bool fTestNet = false ;
bool fNoListen = false ;
bool fLogTimestamps = false ;
2011-12-21 21:33:19 +00:00
CMedianFilter < int64 > vTimeOffsets ( 200 , 0 ) ;
2013-01-01 22:12:30 +00:00
volatile bool fReopenDebugLog = false ;
2013-05-02 16:55:25 +00:00
bool fCachedPath [ 2 ] = { false , false } ;
2011-05-14 15:25:05 +00:00
2012-07-21 10:44:54 +00:00
// Init OpenSSL library multithreading support
2012-05-11 15:00:03 +00:00
static CCriticalSection * * ppmutexOpenSSL ;
2011-05-14 15:25:05 +00:00
void locking_callback ( int mode , int i , const char * file , int line )
{
2012-05-11 15:00:03 +00:00
if ( mode & CRYPTO_LOCK ) {
ENTER_CRITICAL_SECTION ( * ppmutexOpenSSL [ i ] ) ;
} else {
LEAVE_CRITICAL_SECTION ( * ppmutexOpenSSL [ i ] ) ;
}
2011-05-14 15:25:05 +00:00
}
2012-08-22 09:34:32 +00:00
LockedPageManager LockedPageManager : : instance ;
2011-05-14 15:25:05 +00:00
// Init
class CInit
{
public :
CInit ( )
{
2012-07-21 10:44:54 +00:00
// Init OpenSSL library multithreading support
2012-05-11 15:00:03 +00:00
ppmutexOpenSSL = ( CCriticalSection * * ) OPENSSL_malloc ( CRYPTO_num_locks ( ) * sizeof ( CCriticalSection * ) ) ;
2011-05-14 15:25:05 +00:00
for ( int i = 0 ; i < CRYPTO_num_locks ( ) ; i + + )
2012-05-11 15:00:03 +00:00
ppmutexOpenSSL [ i ] = new CCriticalSection ( ) ;
2011-05-14 15:25:05 +00:00
CRYPTO_set_locking_callback ( locking_callback ) ;
2011-10-07 15:02:21 +00:00
# ifdef WIN32
2011-05-14 15:25:05 +00:00
// Seed random number generator with screen scrape and other hardware sources
RAND_screen ( ) ;
# endif
// Seed random number generator with performance counter
RandAddSeed ( ) ;
}
~ CInit ( )
{
2012-07-21 10:44:54 +00:00
// Shutdown OpenSSL library multithreading support
2011-05-14 15:25:05 +00:00
CRYPTO_set_locking_callback ( NULL ) ;
for ( int i = 0 ; i < CRYPTO_num_locks ( ) ; i + + )
delete ppmutexOpenSSL [ i ] ;
OPENSSL_free ( ppmutexOpenSSL ) ;
}
}
instance_of_cinit ;
void RandAddSeed ( )
{
// Seed with CPU performance counter
2011-12-21 21:33:19 +00:00
int64 nCounter = GetPerformanceCounter ( ) ;
2011-05-14 15:25:05 +00:00
RAND_add ( & nCounter , sizeof ( nCounter ) , 1.5 ) ;
memset ( & nCounter , 0 , sizeof ( nCounter ) ) ;
}
void RandAddSeedPerfmon ( )
{
RandAddSeed ( ) ;
// This can take up to 2 seconds, so only do it every 10 minutes
2011-12-21 21:33:19 +00:00
static int64 nLastPerfmon ;
2011-05-14 15:25:05 +00:00
if ( GetTime ( ) < nLastPerfmon + 10 * 60 )
return ;
nLastPerfmon = GetTime ( ) ;
2011-10-07 15:02:21 +00:00
# ifdef WIN32
2011-05-14 15:25:05 +00:00
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
unsigned char pdata [ 250000 ] ;
memset ( pdata , 0 , sizeof ( pdata ) ) ;
unsigned long nSize = sizeof ( pdata ) ;
long ret = RegQueryValueExA ( HKEY_PERFORMANCE_DATA , " Global " , NULL , NULL , pdata , & nSize ) ;
RegCloseKey ( HKEY_PERFORMANCE_DATA ) ;
if ( ret = = ERROR_SUCCESS )
{
RAND_add ( pdata , nSize , nSize / 100.0 ) ;
2012-11-08 18:38:49 +00:00
OPENSSL_cleanse ( pdata , nSize ) ;
2012-09-29 09:57:44 +00:00
printf ( " RandAddSeed() %lu bytes \n " , nSize ) ;
2011-05-14 15:25:05 +00:00
}
# endif
}
2011-12-21 21:33:19 +00:00
uint64 GetRand ( uint64 nMax )
2011-05-14 15:25:05 +00:00
{
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
2011-12-21 21:33:19 +00:00
uint64 nRange = ( std : : numeric_limits < uint64 > : : max ( ) / nMax ) * nMax ;
uint64 nRand = 0 ;
2011-05-14 15:25:05 +00:00
do
RAND_bytes ( ( unsigned char * ) & nRand , sizeof ( nRand ) ) ;
while ( nRand > = nRange ) ;
return ( nRand % nMax ) ;
}
int GetRandInt ( int nMax )
{
return GetRand ( nMax ) ;
}
2012-05-17 16:13:14 +00:00
uint256 GetRandHash ( )
{
uint256 hash ;
RAND_bytes ( ( unsigned char * ) & hash , sizeof ( hash ) ) ;
return hash ;
}
2011-05-14 15:25:05 +00:00
2013-01-01 22:12:30 +00:00
//
// OutputDebugStringF (aka printf -- there is a #define that we really
// should get rid of one day) 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,
// defining a mutex as a global object doesn't work (the mutex gets
// destroyed, and then some later destructor calls OutputDebugStringF,
// maybe indirectly, and you get a core dump at shutdown trying to lock
// the mutex).
2011-05-14 15:25:05 +00:00
2013-01-01 22:12:30 +00:00
static boost : : once_flag debugPrintInitFlag = BOOST_ONCE_INIT ;
// We use boost::call_once() to make sure these are initialized in
// in a thread-safe manner the first time it is called:
static FILE * fileout = NULL ;
static boost : : mutex * mutexDebugLog = NULL ;
static void DebugPrintInit ( )
2011-05-14 15:25:05 +00:00
{
2013-01-01 22:12:30 +00:00
assert ( fileout = = NULL ) ;
assert ( mutexDebugLog = = NULL ) ;
boost : : filesystem : : path pathDebug = GetDataDir ( ) / " debug.log " ;
fileout = fopen ( pathDebug . string ( ) . c_str ( ) , " a " ) ;
if ( fileout ) setbuf ( fileout , NULL ) ; // unbuffered
mutexDebugLog = new boost : : mutex ( ) ;
}
int OutputDebugStringF ( const char * pszFormat , . . . )
{
int ret = 0 ; // Returns total number of characters written
2011-05-14 15:25:05 +00:00
if ( fPrintToConsole )
{
// print to console
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
2013-01-01 22:12:30 +00:00
ret + = vprintf ( pszFormat , arg_ptr ) ;
2011-05-14 15:25:05 +00:00
va_end ( arg_ptr ) ;
}
2012-08-20 15:33:20 +00:00
else if ( ! fPrintToDebugger )
2011-05-14 15:25:05 +00:00
{
2013-01-01 22:12:30 +00:00
static bool fStartedNewLine = true ;
boost : : call_once ( & DebugPrintInit , debugPrintInitFlag ) ;
2011-05-14 15:25:05 +00:00
2013-01-01 22:12:30 +00:00
if ( fileout = = NULL )
return ret ;
boost : : mutex : : scoped_lock scoped_lock ( * mutexDebugLog ) ;
// reopen the log file, if requested
if ( fReopenDebugLog ) {
fReopenDebugLog = false ;
2012-04-09 21:50:56 +00:00
boost : : filesystem : : path pathDebug = GetDataDir ( ) / " debug.log " ;
2013-01-01 22:12:30 +00:00
if ( freopen ( pathDebug . string ( ) . c_str ( ) , " a " , fileout ) ! = NULL )
setbuf ( fileout , NULL ) ; // unbuffered
2011-05-14 15:25:05 +00:00
}
2013-01-01 22:12:30 +00:00
// 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 ' )
fStartedNewLine = true ;
else
fStartedNewLine = false ;
2011-05-14 15:25:05 +00:00
2013-01-01 22:12:30 +00:00
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
ret + = vfprintf ( fileout , pszFormat , arg_ptr ) ;
va_end ( arg_ptr ) ;
2011-05-14 15:25:05 +00:00
}
2011-10-07 15:02:21 +00:00
# ifdef WIN32
2011-05-14 15:25:05 +00:00
if ( fPrintToDebugger )
{
static CCriticalSection cs_OutputDebugStringF ;
2012-05-14 17:53:02 +00:00
// accumulate and output a line at a time
2011-05-14 15:25:05 +00:00
{
2012-04-06 16:39:12 +00:00
LOCK ( cs_OutputDebugStringF ) ;
2012-05-14 17:53:02 +00:00
static std : : string buffer ;
2011-05-14 15:25:05 +00:00
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
2012-05-14 17:53:02 +00:00
buffer + = vstrprintf ( pszFormat , arg_ptr ) ;
2011-05-14 15:25:05 +00:00
va_end ( arg_ptr ) ;
2012-05-14 17:53:02 +00:00
int line_start = 0 , line_end ;
while ( ( line_end = buffer . find ( ' \n ' , line_start ) ) ! = - 1 )
2011-05-14 15:25:05 +00:00
{
2012-05-14 17:53:02 +00:00
OutputDebugStringA ( buffer . substr ( line_start , line_end - line_start ) . c_str ( ) ) ;
line_start = line_end + 1 ;
2013-01-01 22:12:30 +00:00
ret + = line_end - line_start ;
2011-05-14 15:25:05 +00:00
}
2012-05-14 17:53:02 +00:00
buffer . erase ( 0 , line_start ) ;
2011-05-14 15:25:05 +00:00
}
}
# endif
return ret ;
}
2012-09-09 12:43:06 +00:00
string vstrprintf ( const char * format , va_list ap )
2011-05-14 15:25:05 +00:00
{
char buffer [ 50000 ] ;
char * p = buffer ;
int limit = sizeof ( buffer ) ;
int ret ;
loop
{
va_list arg_ptr ;
2012-05-14 17:53:02 +00:00
va_copy ( arg_ptr , ap ) ;
2012-09-09 12:50:31 +00:00
# ifdef WIN32
2012-09-09 12:43:06 +00:00
ret = _vsnprintf ( p , limit , format , arg_ptr ) ;
2012-09-09 12:50:31 +00:00
# else
ret = vsnprintf ( p , limit , format , arg_ptr ) ;
# endif
2011-05-14 15:25:05 +00:00
va_end ( arg_ptr ) ;
if ( ret > = 0 & & ret < limit )
break ;
if ( p ! = buffer )
2011-06-05 17:15:15 +00:00
delete [ ] p ;
2011-05-14 15:25:05 +00:00
limit * = 2 ;
p = new char [ limit ] ;
if ( p = = NULL )
throw std : : bad_alloc ( ) ;
}
string str ( p , p + ret ) ;
if ( p ! = buffer )
2011-06-05 17:15:15 +00:00
delete [ ] p ;
2011-05-14 15:25:05 +00:00
return str ;
}
2012-09-09 12:43:06 +00:00
string real_strprintf ( const char * format , int dummy , . . . )
2012-05-14 17:53:02 +00:00
{
va_list arg_ptr ;
va_start ( arg_ptr , dummy ) ;
string str = vstrprintf ( format , arg_ptr ) ;
va_end ( arg_ptr ) ;
return str ;
}
2012-09-09 12:43:06 +00:00
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 ;
}
2012-03-18 22:14:03 +00:00
bool error ( const char * format , . . . )
2011-05-14 15:25:05 +00:00
{
va_list arg_ptr ;
va_start ( arg_ptr , format ) ;
2012-05-14 17:53:02 +00:00
std : : string str = vstrprintf ( format , arg_ptr ) ;
2011-05-14 15:25:05 +00:00
va_end ( arg_ptr ) ;
2012-05-14 17:53:02 +00:00
printf ( " ERROR: %s \n " , str . c_str ( ) ) ;
2011-05-14 15:25:05 +00:00
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
{
i2 = str . find ( c , i1 ) ;
if ( i2 = = str . npos )
{
v . push_back ( str . substr ( i1 ) ) ;
return ;
}
v . push_back ( str . substr ( i1 , i2 - i1 ) ) ;
i1 = i2 + 1 ;
}
}
2011-12-21 21:33:19 +00:00
string FormatMoney ( int64 n , bool fPlus )
2011-05-14 15:25:05 +00:00
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
2011-12-21 21:33:19 +00:00
int64 n_abs = ( n > 0 ? n : - n ) ;
int64 quotient = n_abs / COIN ;
int64 remainder = n_abs % COIN ;
2011-05-14 15:25:05 +00:00
string str = strprintf ( " % " PRI64d " .%08 " PRI64d , quotient , remainder ) ;
2012-07-26 03:25:26 +00:00
// Right-trim excess zeros before the decimal point:
2011-05-14 15:25:05 +00:00
int nTrim = 0 ;
for ( int i = str . size ( ) - 1 ; ( str [ i ] = = ' 0 ' & & isdigit ( str [ i - 2 ] ) ) ; - - i )
+ + nTrim ;
if ( nTrim )
str . erase ( str . size ( ) - nTrim , nTrim ) ;
if ( n < 0 )
str . insert ( ( unsigned int ) 0 , 1 , ' - ' ) ;
else if ( fPlus & & n > 0 )
str . insert ( ( unsigned int ) 0 , 1 , ' + ' ) ;
return str ;
}
2011-12-21 21:33:19 +00:00
bool ParseMoney ( const string & str , int64 & nRet )
2011-05-14 15:25:05 +00:00
{
return ParseMoney ( str . c_str ( ) , nRet ) ;
}
2011-12-21 21:33:19 +00:00
bool ParseMoney ( const char * pszIn , int64 & nRet )
2011-05-14 15:25:05 +00:00
{
string strWhole ;
2011-12-21 21:33:19 +00:00
int64 nUnits = 0 ;
2011-05-14 15:25:05 +00:00
const char * p = pszIn ;
while ( isspace ( * p ) )
p + + ;
for ( ; * p ; p + + )
{
if ( * p = = ' . ' )
{
p + + ;
2011-12-21 21:33:19 +00:00
int64 nMult = CENT * 10 ;
2011-05-14 15:25:05 +00:00
while ( isdigit ( * p ) & & ( nMult > 0 ) )
{
nUnits + = nMult * ( * p + + - ' 0 ' ) ;
nMult / = 10 ;
}
break ;
}
if ( isspace ( * p ) )
break ;
if ( ! isdigit ( * p ) )
return false ;
strWhole . insert ( strWhole . end ( ) , * p ) ;
}
for ( ; * p ; p + + )
if ( ! isspace ( * p ) )
return false ;
2011-10-01 00:47:47 +00:00
if ( strWhole . size ( ) > 10 ) // guard against 63 bit overflow
2011-05-14 15:25:05 +00:00
return false ;
if ( nUnits < 0 | | nUnits > COIN )
return false ;
2011-12-21 21:33:19 +00:00
int64 nWhole = atoi64 ( strWhole ) ;
int64 nValue = nWhole * COIN + nUnits ;
2011-05-14 15:25:05 +00:00
nRet = nValue ;
return true ;
}
2012-09-09 12:52:07 +00:00
static const signed char phexdigit [ 256 ] =
2012-01-05 02:40:52 +00:00
{ - 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 ,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , 0xa , 0xb , 0xc , 0xd , 0xe , 0xf , - 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 ,
2012-04-16 05:31:38 +00:00
- 1 , 0xa , 0xb , 0xc , 0xd , 0xe , 0xf , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
2012-01-05 02:40:52 +00:00
- 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 ,
- 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 ,
- 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 , } ;
bool IsHex ( const string & str )
2011-05-14 15:25:05 +00:00
{
2012-01-05 02:40:52 +00:00
BOOST_FOREACH ( unsigned char c , str )
{
if ( phexdigit [ c ] < 0 )
return false ;
}
return ( str . size ( ) > 0 ) & & ( str . size ( ) % 2 = = 0 ) ;
}
2011-05-14 15:25:05 +00:00
2012-01-05 02:40:52 +00:00
vector < unsigned char > ParseHex ( const char * psz )
{
2011-05-14 15:25:05 +00:00
// convert hex dump to vector
vector < unsigned char > vch ;
loop
{
while ( isspace ( * psz ) )
psz + + ;
2012-04-16 05:32:55 +00:00
signed char c = phexdigit [ ( unsigned char ) * psz + + ] ;
if ( c = = ( signed char ) - 1 )
2011-05-14 15:25:05 +00:00
break ;
unsigned char n = ( c < < 4 ) ;
c = phexdigit [ ( unsigned char ) * psz + + ] ;
2012-04-16 05:32:55 +00:00
if ( c = = ( signed char ) - 1 )
2011-05-14 15:25:05 +00:00
break ;
n | = c ;
vch . push_back ( n ) ;
}
return vch ;
}
vector < unsigned char > ParseHex ( const string & str )
{
return ParseHex ( str . c_str ( ) ) ;
}
2012-02-16 20:08:32 +00:00
static void InterpretNegativeSetting ( string name , map < string , string > & mapSettingsRet )
{
// interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
if ( name . find ( " -no " ) = = 0 )
{
std : : string positive ( " - " ) ;
positive . append ( name . begin ( ) + 3 , name . end ( ) ) ;
if ( mapSettingsRet . count ( positive ) = = 0 )
{
bool value = ! GetBoolArg ( name ) ;
mapSettingsRet [ positive ] = ( value ? " 1 " : " 0 " ) ;
}
}
}
2012-04-22 14:22:45 +00:00
void ParseParameters ( int argc , const char * const argv [ ] )
2011-05-14 15:25:05 +00:00
{
mapArgs . clear ( ) ;
mapMultiArgs . clear ( ) ;
for ( int i = 1 ; i < argc ; i + + )
{
2012-10-02 19:36:39 +00:00
std : : string str ( argv [ i ] ) ;
std : : string strValue ;
size_t is_index = str . find ( ' = ' ) ;
if ( is_index ! = std : : string : : npos )
2011-05-14 15:25:05 +00:00
{
2012-10-02 19:36:39 +00:00
strValue = str . substr ( is_index + 1 ) ;
str = str . substr ( 0 , is_index ) ;
2011-05-14 15:25:05 +00:00
}
2012-10-02 19:36:39 +00:00
# ifdef WIN32
boost : : to_lower ( str ) ;
if ( boost : : algorithm : : starts_with ( str , " / " ) )
str = " - " + str . substr ( 1 ) ;
# endif
if ( str [ 0 ] ! = ' - ' )
2011-05-14 15:25:05 +00:00
break ;
2012-02-06 18:55:11 +00:00
2012-10-02 19:36:39 +00:00
mapArgs [ str ] = strValue ;
mapMultiArgs [ str ] . push_back ( strValue ) ;
2011-05-14 15:25:05 +00:00
}
2012-02-06 18:55:11 +00:00
// New 0.6 features:
BOOST_FOREACH ( const PAIRTYPE ( string , string ) & entry , mapArgs )
{
string name = entry . first ;
// interpret --foo as -foo (as long as both are not set)
if ( name . find ( " -- " ) = = 0 )
{
std : : string singleDash ( name . begin ( ) + 1 , name . end ( ) ) ;
if ( mapArgs . count ( singleDash ) = = 0 )
mapArgs [ singleDash ] = entry . second ;
name = singleDash ;
}
2012-02-16 20:08:32 +00:00
// interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
InterpretNegativeSetting ( name , mapArgs ) ;
2012-02-06 18:55:11 +00:00
}
2011-05-14 15:25:05 +00:00
}
2012-02-06 17:37:49 +00:00
std : : string GetArg ( const std : : string & strArg , const std : : string & strDefault )
{
if ( mapArgs . count ( strArg ) )
return mapArgs [ strArg ] ;
return strDefault ;
}
int64 GetArg ( const std : : string & strArg , int64 nDefault )
{
if ( mapArgs . count ( strArg ) )
return atoi64 ( mapArgs [ strArg ] ) ;
return nDefault ;
}
bool GetBoolArg ( const std : : string & strArg , bool fDefault )
{
if ( mapArgs . count ( strArg ) )
{
if ( mapArgs [ strArg ] . empty ( ) )
return true ;
return ( atoi ( mapArgs [ strArg ] ) ! = 0 ) ;
}
return fDefault ;
}
2012-01-03 15:14:22 +00:00
bool SoftSetArg ( const std : : string & strArg , const std : : string & strValue )
{
if ( mapArgs . count ( strArg ) )
return false ;
mapArgs [ strArg ] = strValue ;
return true ;
}
2012-02-06 20:48:00 +00:00
bool SoftSetBoolArg ( const std : : string & strArg , bool fValue )
2012-01-03 15:14:22 +00:00
{
if ( fValue )
return SoftSetArg ( strArg , std : : string ( " 1 " ) ) ;
else
return SoftSetArg ( strArg , std : : string ( " 0 " ) ) ;
}
2011-09-20 13:38:29 +00:00
string EncodeBase64 ( const unsigned char * pch , size_t len )
2011-07-25 22:13:55 +00:00
{
2011-09-20 13:38:29 +00:00
static const char * pbase64 = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ " ;
string strRet = " " ;
strRet . reserve ( ( len + 2 ) / 3 * 4 ) ;
int mode = 0 , left = 0 ;
const unsigned char * pchEnd = pch + len ;
while ( pch < pchEnd )
{
int enc = * ( pch + + ) ;
switch ( mode )
{
case 0 : // we have no bits
strRet + = pbase64 [ enc > > 2 ] ;
left = ( enc & 3 ) < < 4 ;
mode = 1 ;
break ;
case 1 : // we have two bits
strRet + = pbase64 [ left | ( enc > > 4 ) ] ;
left = ( enc & 15 ) < < 2 ;
mode = 2 ;
break ;
case 2 : // we have four bits
strRet + = pbase64 [ left | ( enc > > 6 ) ] ;
strRet + = pbase64 [ enc & 63 ] ;
mode = 0 ;
break ;
}
}
if ( mode )
{
strRet + = pbase64 [ left ] ;
strRet + = ' = ' ;
if ( mode = = 1 )
strRet + = ' = ' ;
}
return strRet ;
}
string EncodeBase64 ( const string & str )
2011-07-25 22:13:55 +00:00
{
2011-09-20 13:38:29 +00:00
return EncodeBase64 ( ( const unsigned char * ) str . c_str ( ) , str . size ( ) ) ;
}
2011-07-25 22:13:55 +00:00
2011-09-20 13:38:29 +00:00
vector < unsigned char > DecodeBase64 ( const char * p , bool * pfInvalid )
{
static const int decode64_table [ 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 , 62 , - 1 , - 1 , - 1 , 63 , 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 ,
15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , 26 , 27 , 28 ,
29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 ,
49 , 50 , 51 , - 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 , - 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 , - 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
} ;
if ( pfInvalid )
* pfInvalid = false ;
vector < unsigned char > vchRet ;
vchRet . reserve ( strlen ( p ) * 3 / 4 ) ;
int mode = 0 ;
int left = 0 ;
while ( 1 )
2011-07-25 22:13:55 +00:00
{
2012-04-15 10:22:30 +00:00
int dec = decode64_table [ ( unsigned char ) * p ] ;
2011-09-20 13:38:29 +00:00
if ( dec = = - 1 ) break ;
p + + ;
switch ( mode )
2011-07-25 22:13:55 +00:00
{
case 0 : // we have no bits and get 6
left = dec ;
mode = 1 ;
break ;
case 1 : // we have 6 bits and keep 4
2011-09-20 13:38:29 +00:00
vchRet . push_back ( ( left < < 2 ) | ( dec > > 4 ) ) ;
2011-07-25 22:13:55 +00:00
left = dec & 15 ;
mode = 2 ;
break ;
2011-09-20 13:38:29 +00:00
case 2 : // we have 4 bits and get 6, we keep 2
vchRet . push_back ( ( left < < 4 ) | ( dec > > 2 ) ) ;
2011-07-25 22:13:55 +00:00
left = dec & 3 ;
mode = 3 ;
break ;
2011-09-20 13:38:29 +00:00
2011-07-25 22:13:55 +00:00
case 3 : // we have 2 bits and get 6
2011-09-20 13:38:29 +00:00
vchRet . push_back ( ( left < < 6 ) | dec ) ;
mode = 0 ;
2011-07-25 22:13:55 +00:00
break ;
}
}
2011-09-20 13:38:29 +00:00
if ( pfInvalid )
switch ( mode )
{
case 0 : // 4n base64 characters processed: ok
break ;
case 1 : // 4n+1 base64 character processed: impossible
* pfInvalid = true ;
break ;
case 2 : // 4n+2 base64 characters processed: require '=='
2012-04-15 10:22:30 +00:00
if ( left | | p [ 0 ] ! = ' = ' | | p [ 1 ] ! = ' = ' | | decode64_table [ ( unsigned char ) p [ 2 ] ] ! = - 1 )
2011-09-20 13:38:29 +00:00
* pfInvalid = true ;
break ;
case 3 : // 4n+3 base64 characters processed: require '='
2012-04-15 10:22:30 +00:00
if ( left | | p [ 0 ] ! = ' = ' | | decode64_table [ ( unsigned char ) p [ 1 ] ] ! = - 1 )
2011-09-20 13:38:29 +00:00
* pfInvalid = true ;
break ;
}
return vchRet ;
2011-07-25 22:13:55 +00:00
}
2011-09-20 13:38:29 +00:00
string DecodeBase64 ( const string & str )
{
vector < unsigned char > vchRet = DecodeBase64 ( str . c_str ( ) ) ;
return string ( ( const char * ) & vchRet [ 0 ] , vchRet . size ( ) ) ;
}
2011-05-14 15:25:05 +00:00
2012-01-22 19:32:58 +00:00
string EncodeBase32 ( const unsigned char * pch , size_t len )
{
2012-04-29 00:11:56 +00:00
static const char * pbase32 = " abcdefghijklmnopqrstuvwxyz234567 " ;
2012-01-22 19:32:58 +00:00
string strRet = " " ;
strRet . reserve ( ( len + 4 ) / 5 * 8 ) ;
int mode = 0 , left = 0 ;
const unsigned char * pchEnd = pch + len ;
while ( pch < pchEnd )
{
int enc = * ( pch + + ) ;
switch ( mode )
{
case 0 : // we have no bits
strRet + = pbase32 [ enc > > 3 ] ;
left = ( enc & 7 ) < < 2 ;
mode = 1 ;
break ;
case 1 : // we have three bits
strRet + = pbase32 [ left | ( enc > > 6 ) ] ;
strRet + = pbase32 [ ( enc > > 1 ) & 31 ] ;
left = ( enc & 1 ) < < 4 ;
mode = 2 ;
break ;
case 2 : // we have one bit
strRet + = pbase32 [ left | ( enc > > 4 ) ] ;
left = ( enc & 15 ) < < 1 ;
mode = 3 ;
break ;
case 3 : // we have four bits
strRet + = pbase32 [ left | ( enc > > 7 ) ] ;
strRet + = pbase32 [ ( enc > > 2 ) & 31 ] ;
left = ( enc & 3 ) < < 3 ;
mode = 4 ;
break ;
case 4 : // we have two bits
strRet + = pbase32 [ left | ( enc > > 5 ) ] ;
strRet + = pbase32 [ enc & 31 ] ;
mode = 0 ;
}
}
static const int nPadding [ 5 ] = { 0 , 6 , 4 , 3 , 1 } ;
if ( mode )
{
strRet + = pbase32 [ left ] ;
for ( int n = 0 ; n < nPadding [ mode ] ; n + + )
strRet + = ' = ' ;
}
return strRet ;
}
string EncodeBase32 ( const string & str )
{
return EncodeBase32 ( ( const unsigned char * ) str . c_str ( ) , str . size ( ) ) ;
}
vector < unsigned char > DecodeBase32 ( const char * p , bool * pfInvalid )
{
static const int decode32_table [ 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 , - 1 , - 1 , 26 , 27 , 28 , 29 , 30 , 31 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 ,
15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , 0 , 1 , 2 ,
3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 ,
23 , 24 , 25 , - 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 , - 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 , - 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
} ;
if ( pfInvalid )
* pfInvalid = false ;
vector < unsigned char > vchRet ;
vchRet . reserve ( ( strlen ( p ) ) * 5 / 8 ) ;
int mode = 0 ;
int left = 0 ;
while ( 1 )
{
int dec = decode32_table [ ( unsigned char ) * p ] ;
if ( dec = = - 1 ) break ;
p + + ;
switch ( mode )
{
case 0 : // we have no bits and get 5
left = dec ;
mode = 1 ;
break ;
case 1 : // we have 5 bits and keep 2
vchRet . push_back ( ( left < < 3 ) | ( dec > > 2 ) ) ;
left = dec & 3 ;
mode = 2 ;
break ;
case 2 : // we have 2 bits and keep 7
left = left < < 5 | dec ;
mode = 3 ;
break ;
case 3 : // we have 7 bits and keep 4
vchRet . push_back ( ( left < < 1 ) | ( dec > > 4 ) ) ;
left = dec & 15 ;
mode = 4 ;
break ;
case 4 : // we have 4 bits, and keep 1
vchRet . push_back ( ( left < < 4 ) | ( dec > > 1 ) ) ;
left = dec & 1 ;
mode = 5 ;
break ;
case 5 : // we have 1 bit, and keep 6
left = left < < 5 | dec ;
mode = 6 ;
break ;
case 6 : // we have 6 bits, and keep 3
vchRet . push_back ( ( left < < 2 ) | ( dec > > 3 ) ) ;
left = dec & 7 ;
mode = 7 ;
break ;
case 7 : // we have 3 bits, and keep 0
vchRet . push_back ( ( left < < 5 ) | dec ) ;
mode = 0 ;
break ;
}
}
if ( pfInvalid )
switch ( mode )
{
case 0 : // 8n base32 characters processed: ok
break ;
case 1 : // 8n+1 base32 characters processed: impossible
case 3 : // +3
case 6 : // +6
* pfInvalid = true ;
break ;
case 2 : // 8n+2 base32 characters processed: require '======'
if ( left | | p [ 0 ] ! = ' = ' | | p [ 1 ] ! = ' = ' | | p [ 2 ] ! = ' = ' | | p [ 3 ] ! = ' = ' | | p [ 4 ] ! = ' = ' | | p [ 5 ] ! = ' = ' | | decode32_table [ ( unsigned char ) p [ 6 ] ] ! = - 1 )
* pfInvalid = true ;
break ;
case 4 : // 8n+4 base32 characters processed: require '===='
if ( left | | p [ 0 ] ! = ' = ' | | p [ 1 ] ! = ' = ' | | p [ 2 ] ! = ' = ' | | p [ 3 ] ! = ' = ' | | decode32_table [ ( unsigned char ) p [ 4 ] ] ! = - 1 )
* pfInvalid = true ;
break ;
case 5 : // 8n+5 base32 characters processed: require '==='
if ( left | | p [ 0 ] ! = ' = ' | | p [ 1 ] ! = ' = ' | | p [ 2 ] ! = ' = ' | | decode32_table [ ( unsigned char ) p [ 3 ] ] ! = - 1 )
* pfInvalid = true ;
break ;
case 7 : // 8n+7 base32 characters processed: require '='
if ( left | | p [ 0 ] ! = ' = ' | | decode32_table [ ( unsigned char ) p [ 1 ] ] ! = - 1 )
* pfInvalid = true ;
break ;
}
return vchRet ;
}
string DecodeBase32 ( const string & str )
{
vector < unsigned char > vchRet = DecodeBase32 ( str . c_str ( ) ) ;
return string ( ( const char * ) & vchRet [ 0 ] , vchRet . size ( ) ) ;
}
2011-05-14 15:25:05 +00:00
bool WildcardMatch ( const char * psz , const char * mask )
{
loop
{
switch ( * mask )
{
case ' \0 ' :
return ( * psz = = ' \0 ' ) ;
case ' * ' :
return WildcardMatch ( psz , mask + 1 ) | | ( * psz & & WildcardMatch ( psz + 1 , mask ) ) ;
case ' ? ' :
if ( * psz = = ' \0 ' )
return false ;
break ;
default :
if ( * psz ! = * mask )
return false ;
break ;
}
psz + + ;
mask + + ;
}
}
bool WildcardMatch ( const string & str , const string & mask )
{
return WildcardMatch ( str . c_str ( ) , mask . c_str ( ) ) ;
}
2012-05-14 17:53:02 +00:00
static std : : string FormatException ( std : : exception * pex , const char * pszThread )
2011-05-14 15:25:05 +00:00
{
2011-10-07 15:02:21 +00:00
# ifdef WIN32
2012-04-22 14:22:45 +00:00
char pszModule [ MAX_PATH ] = " " ;
2011-05-14 15:25:05 +00:00
GetModuleFileNameA ( NULL , pszModule , sizeof ( pszModule ) ) ;
# else
2013-06-19 21:16:25 +00:00
const char * pszModule = " primecoin " ;
2011-05-14 15:25:05 +00:00
# endif
if ( pex )
2012-05-14 17:53:02 +00:00
return strprintf (
2011-05-14 15:25:05 +00:00
" EXCEPTION: %s \n %s \n %s in %s \n " , typeid ( * pex ) . name ( ) , pex - > what ( ) , pszModule , pszThread ) ;
else
2012-05-14 17:53:02 +00:00
return strprintf (
2011-05-14 15:25:05 +00:00
" UNKNOWN EXCEPTION \n %s in %s \n " , pszModule , pszThread ) ;
}
void LogException ( std : : exception * pex , const char * pszThread )
{
2012-05-14 17:53:02 +00:00
std : : string message = FormatException ( pex , pszThread ) ;
printf ( " \n %s " , message . c_str ( ) ) ;
2011-05-14 15:25:05 +00:00
}
void PrintException ( std : : exception * pex , const char * pszThread )
{
2012-05-14 17:53:02 +00:00
std : : string message = FormatException ( pex , pszThread ) ;
printf ( " \n \n ************************ \n %s \n " , message . c_str ( ) ) ;
fprintf ( stderr , " \n \n ************************ \n %s \n " , message . c_str ( ) ) ;
strMiscWarning = message ;
2011-05-14 15:25:05 +00:00
throw ;
}
void PrintExceptionContinue ( std : : exception * pex , const char * pszThread )
{
2012-05-14 17:53:02 +00:00
std : : string message = FormatException ( pex , pszThread ) ;
printf ( " \n \n ************************ \n %s \n " , message . c_str ( ) ) ;
fprintf ( stderr , " \n \n ************************ \n %s \n " , message . c_str ( ) ) ;
strMiscWarning = message ;
2011-05-14 15:25:05 +00:00
}
2012-04-09 21:50:56 +00:00
boost : : filesystem : : path GetDefaultDataDir ( )
2011-05-14 15:25:05 +00:00
{
2012-04-09 21:50:56 +00:00
namespace fs = boost : : filesystem ;
2013-03-14 01:12:46 +00:00
// Windows < Vista: C:\Documents and Settings\Username\Application Data\Primecoin
// Windows >= Vista: C:\Users\Username\AppData\Roaming\Primecoin
// Mac: ~/Library/Application Support/Primecoin
// Unix: ~/.primecoin
2011-10-07 15:02:21 +00:00
# ifdef WIN32
2011-05-14 15:25:05 +00:00
// Windows
2013-03-14 01:12:46 +00:00
return GetSpecialFolderPath ( CSIDL_APPDATA ) / " Primecoin " ;
2011-05-14 15:25:05 +00:00
# else
2012-04-09 21:50:56 +00:00
fs : : path pathRet ;
2011-05-14 15:25:05 +00:00
char * pszHome = getenv ( " HOME " ) ;
if ( pszHome = = NULL | | strlen ( pszHome ) = = 0 )
2012-04-09 21:50:56 +00:00
pathRet = fs : : path ( " / " ) ;
else
pathRet = fs : : path ( pszHome ) ;
2011-10-07 15:02:21 +00:00
# ifdef MAC_OSX
2011-05-14 15:25:05 +00:00
// Mac
2012-04-12 15:14:46 +00:00
pathRet / = " Library/Application Support " ;
2012-05-09 17:56:53 +00:00
fs : : create_directory ( pathRet ) ;
2013-03-14 01:12:46 +00:00
return pathRet / " Primecoin " ;
2011-05-14 15:25:05 +00:00
# else
// Unix
2013-03-14 01:12:46 +00:00
return pathRet / " .primecoin " ;
2011-05-14 15:25:05 +00:00
# endif
# endif
}
2012-04-09 21:50:56 +00:00
const boost : : filesystem : : path & GetDataDir ( bool fNetSpecific )
2011-05-14 15:25:05 +00:00
{
2012-04-09 21:50:56 +00:00
namespace fs = boost : : filesystem ;
static fs : : path pathCached [ 2 ] ;
static CCriticalSection csPathCached ;
fs : : path & path = pathCached [ fNetSpecific ] ;
// This can be called during exceptions by printf, so we cache the
// value so we don't have to do memory allocations after that.
2013-05-02 16:55:25 +00:00
if ( fCachedPath [ fNetSpecific ] )
2012-04-09 21:50:56 +00:00
return path ;
LOCK ( csPathCached ) ;
if ( mapArgs . count ( " -datadir " ) ) {
2012-04-22 12:35:22 +00:00
path = fs : : system_complete ( mapArgs [ " -datadir " ] ) ;
if ( ! fs : : is_directory ( path ) ) {
path = " " ;
return path ;
}
2012-04-09 21:50:56 +00:00
} else {
path = GetDefaultDataDir ( ) ;
2011-05-14 15:25:05 +00:00
}
2012-04-13 01:11:14 +00:00
if ( fNetSpecific & & GetBoolArg ( " -testnet " , false ) )
2013-03-14 01:12:46 +00:00
path / = " testnet " ;
2011-05-14 15:25:05 +00:00
2012-04-09 21:50:56 +00:00
fs : : create_directory ( path ) ;
2013-05-02 16:55:25 +00:00
fCachedPath [ fNetSpecific ] = true ;
2012-04-09 21:50:56 +00:00
return path ;
2011-05-14 15:25:05 +00:00
}
2012-04-09 21:50:56 +00:00
boost : : filesystem : : path GetConfigFile ( )
2011-05-14 15:25:05 +00:00
{
2013-03-14 01:12:46 +00:00
boost : : filesystem : : path pathConfigFile ( GetArg ( " -conf " , " primecoin.conf " ) ) ;
2012-04-09 21:50:56 +00:00
if ( ! pathConfigFile . is_complete ( ) ) pathConfigFile = GetDataDir ( false ) / pathConfigFile ;
return pathConfigFile ;
2011-05-14 15:25:05 +00:00
}
2012-04-22 12:35:22 +00:00
void ReadConfigFile ( map < string , string > & mapSettingsRet ,
2011-05-14 15:25:05 +00:00
map < string , vector < string > > & mapMultiSettingsRet )
{
2012-04-22 14:22:45 +00:00
boost : : filesystem : : ifstream streamConfig ( GetConfigFile ( ) ) ;
2011-05-14 15:25:05 +00:00
if ( ! streamConfig . good ( ) )
2012-04-22 12:35:22 +00:00
return ; // No bitcoin.conf file is OK
2011-05-14 15:25:05 +00:00
2013-05-02 16:55:25 +00:00
// clear path cache after loading config file
fCachedPath [ 0 ] = fCachedPath [ 1 ] = false ;
2011-05-14 15:25:05 +00:00
set < string > setOptions ;
setOptions . insert ( " * " ) ;
2012-04-09 21:50:56 +00:00
2012-04-22 14:22:45 +00:00
for ( boost : : program_options : : detail : : config_file_iterator it ( streamConfig , setOptions ) , end ; it ! = end ; + + it )
2011-05-14 15:25:05 +00:00
{
// Don't overwrite existing settings so command line settings override bitcoin.conf
string strKey = string ( " - " ) + it - > string_key ;
if ( mapSettingsRet . count ( strKey ) = = 0 )
2012-02-16 20:08:32 +00:00
{
2011-05-14 15:25:05 +00:00
mapSettingsRet [ strKey ] = it - > value [ 0 ] ;
2012-04-22 14:22:45 +00:00
// interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
2012-02-16 20:08:32 +00:00
InterpretNegativeSetting ( strKey , mapSettingsRet ) ;
}
2011-05-14 15:25:05 +00:00
mapMultiSettingsRet [ strKey ] . push_back ( it - > value [ 0 ] ) ;
}
}
2012-04-09 21:50:56 +00:00
boost : : filesystem : : path GetPidFile ( )
2011-05-14 15:25:05 +00:00
{
2013-03-14 01:12:46 +00:00
boost : : filesystem : : path pathPidFile ( GetArg ( " -pid " , " primecoind.pid " ) ) ;
2012-04-09 21:50:56 +00:00
if ( ! pathPidFile . is_complete ( ) ) pathPidFile = GetDataDir ( ) / pathPidFile ;
return pathPidFile ;
2011-05-14 15:25:05 +00:00
}
2012-04-09 21:50:56 +00:00
void CreatePidFile ( const boost : : filesystem : : path & path , pid_t pid )
2011-05-14 15:25:05 +00:00
{
2012-04-09 21:50:56 +00:00
FILE * file = fopen ( path . string ( ) . c_str ( ) , " w " ) ;
2011-06-24 18:03:16 +00:00
if ( file )
2011-05-14 15:25:05 +00:00
{
fprintf ( file , " %d \n " , pid ) ;
fclose ( file ) ;
}
}
2012-05-12 05:24:27 +00:00
bool RenameOver ( boost : : filesystem : : path src , boost : : filesystem : : path dest )
{
# ifdef WIN32
2012-05-17 16:30:09 +00:00
return MoveFileExA ( src . string ( ) . c_str ( ) , dest . string ( ) . c_str ( ) ,
2012-05-12 05:24:27 +00:00
MOVEFILE_REPLACE_EXISTING ) ;
# else
int rc = std : : rename ( src . string ( ) . c_str ( ) , dest . string ( ) . c_str ( ) ) ;
return ( rc = = 0 ) ;
# endif /* WIN32 */
}
void FileCommit ( FILE * fileout )
{
fflush ( fileout ) ; // harmless if redundantly called
# ifdef WIN32
_commit ( _fileno ( fileout ) ) ;
# else
2012-09-28 12:27:20 +00:00
# if defined(__linux__) || defined(__NetBSD__)
fdatasync ( fileno ( fileout ) ) ;
# else
2012-05-12 05:24:27 +00:00
fsync ( fileno ( fileout ) ) ;
2012-09-28 12:27:20 +00:00
# endif
2012-05-12 05:24:27 +00:00
# endif
}
2011-05-14 15:25:05 +00:00
int GetFilesize ( FILE * file )
{
int nSavePos = ftell ( file ) ;
int nFilesize = - 1 ;
if ( fseek ( file , 0 , SEEK_END ) = = 0 )
nFilesize = ftell ( file ) ;
fseek ( file , nSavePos , SEEK_SET ) ;
return nFilesize ;
}
2013-01-30 03:17:33 +00:00
bool TruncateFile ( FILE * file , unsigned int length ) {
# if defined(WIN32)
return _chsize ( _fileno ( file ) , length ) = = 0 ;
# else
return ftruncate ( fileno ( file ) , length ) = = 0 ;
# endif
}
2013-04-25 22:46:47 +00:00
// 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
}
2012-08-16 00:21:28 +00:00
// 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 ) {
2013-01-27 23:07:51 +00:00
# if defined(WIN32)
// Windows-specific version
HANDLE hFile = ( HANDLE ) _get_osfhandle ( _fileno ( file ) ) ;
LARGE_INTEGER nFileSize ;
int64 nEndPos = ( int64 ) 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
2012-08-16 00:21:28 +00:00
static const char buf [ 65536 ] = { } ;
fseek ( file , offset , SEEK_SET ) ;
while ( length > 0 ) {
unsigned int now = 65536 ;
if ( length < now )
now = length ;
fwrite ( buf , 1 , now , file ) ; // allowed to fail; this function is advisory anyway
length - = now ;
}
2013-01-27 23:07:51 +00:00
# endif
2012-08-16 00:21:28 +00:00
}
2011-05-14 15:25:05 +00:00
void ShrinkDebugFile ( )
{
// Scroll debug.log if it's getting too big
2012-04-09 21:50:56 +00:00
boost : : filesystem : : path pathLog = GetDataDir ( ) / " debug.log " ;
FILE * file = fopen ( pathLog . string ( ) . c_str ( ) , " r " ) ;
2011-05-14 15:25:05 +00:00
if ( file & & GetFilesize ( file ) > 10 * 1000000 )
{
// Restart the file with some of the end
char pch [ 200000 ] ;
fseek ( file , - sizeof ( pch ) , SEEK_END ) ;
int nBytes = fread ( pch , 1 , sizeof ( pch ) , file ) ;
fclose ( file ) ;
2011-06-24 18:03:16 +00:00
2012-04-09 21:50:56 +00:00
file = fopen ( pathLog . string ( ) . c_str ( ) , " w " ) ;
2011-06-24 18:03:16 +00:00
if ( file )
2011-05-14 15:25:05 +00:00
{
fwrite ( pch , 1 , nBytes , file ) ;
fclose ( file ) ;
}
}
2013-04-06 22:24:53 +00:00
else if ( file ! = NULL )
fclose ( file ) ;
2011-05-14 15:25:05 +00:00
}
//
// "Never go to sea with two chronometers; take one or three."
// Our three time sources are:
// - System clock
2012-06-29 09:26:45 +00:00
// - Median of other nodes clocks
2011-05-14 15:25:05 +00:00
// - The user (asking the user to fix the system clock if the first two disagree)
//
2011-12-21 21:33:19 +00:00
static int64 nMockTime = 0 ; // For unit testing
2011-09-15 12:55:15 +00:00
2011-12-21 21:33:19 +00:00
int64 GetTime ( )
2011-05-14 15:25:05 +00:00
{
2011-09-15 12:55:15 +00:00
if ( nMockTime ) return nMockTime ;
2011-05-14 15:25:05 +00:00
return time ( NULL ) ;
}
2011-12-21 21:33:19 +00:00
void SetMockTime ( int64 nMockTimeIn )
2011-09-15 12:55:15 +00:00
{
nMockTime = nMockTimeIn ;
}
2011-12-21 21:33:19 +00:00
static int64 nTimeOffset = 0 ;
2011-05-14 15:25:05 +00:00
2013-01-11 11:11:34 +00:00
int64 GetTimeOffset ( )
{
return nTimeOffset ;
}
2011-12-21 21:33:19 +00:00
int64 GetAdjustedTime ( )
2011-05-14 15:25:05 +00:00
{
2013-01-11 11:11:34 +00:00
return GetTime ( ) + GetTimeOffset ( ) ;
2011-05-14 15:25:05 +00:00
}
2013-02-15 23:27:57 +00:00
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 ;
2013-04-04 09:30:55 +00:00
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 ;
2013-02-15 23:27:57 +00:00
}
}
2011-05-14 15:25:05 +00:00
string FormatVersion ( int nVersion )
{
if ( nVersion % 100 = = 0 )
return strprintf ( " %d.%d.%d " , nVersion / 1000000 , ( nVersion / 10000 ) % 100 , ( nVersion / 100 ) % 100 ) ;
else
return strprintf ( " %d.%d.%d.%d " , nVersion / 1000000 , ( nVersion / 10000 ) % 100 , ( nVersion / 100 ) % 100 , nVersion % 100 ) ;
}
string FormatFullVersion ( )
{
2012-04-07 00:06:53 +00:00
return CLIENT_BUILD ;
2011-05-14 15:25:05 +00:00
}
2011-12-16 21:26:14 +00:00
// Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
std : : string FormatSubVersion ( const std : : string & name , int nClientVersion , const std : : vector < std : : string > & comments )
{
std : : ostringstream ss ;
ss < < " / " ;
ss < < name < < " : " < < FormatVersion ( nClientVersion ) ;
if ( ! comments . empty ( ) )
ss < < " ( " < < boost : : algorithm : : join ( comments , " ; " ) < < " ) " ;
ss < < " / " ;
return ss . str ( ) ;
}
2011-05-14 15:25:05 +00:00
2012-04-15 20:10:54 +00:00
# ifdef WIN32
2012-04-22 14:22:45 +00:00
boost : : filesystem : : path GetSpecialFolderPath ( int nFolder , bool fCreate )
{
namespace fs = boost : : filesystem ;
char pszPath [ MAX_PATH ] = " " ;
if ( SHGetSpecialFolderPathA ( NULL , pszPath , nFolder , fCreate ) )
{
return fs : : path ( pszPath ) ;
}
printf ( " SHGetSpecialFolderPathA() failed, could not obtain requested path. \n " ) ;
return fs : : path ( " " ) ;
}
2012-04-15 20:10:54 +00:00
# endif
2012-05-24 03:10:59 +00:00
2012-11-28 23:33:12 +00:00
boost : : filesystem : : path GetTempPath ( ) {
# if BOOST_FILESYSTEM_VERSION == 3
return boost : : filesystem : : temp_directory_path ( ) ;
# else
// TODO: remove when we don't support filesystem v2 anymore
boost : : filesystem : : path path ;
# ifdef WIN32
char pszPath [ MAX_PATH ] = " " ;
if ( GetTempPathA ( MAX_PATH , pszPath ) )
path = boost : : filesystem : : path ( pszPath ) ;
# else
path = boost : : filesystem : : path ( " /tmp " ) ;
# endif
if ( path . empty ( ) | | ! boost : : filesystem : : is_directory ( path ) ) {
printf ( " GetTempPath(): failed to find temp path \n " ) ;
return boost : : filesystem : : path ( " " ) ;
}
return path ;
# endif
}
2012-05-24 03:10:59 +00:00
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 ) ;
}
2012-06-24 15:03:57 +00:00
void RenameThread ( const char * name )
{
2012-06-30 18:11:27 +00:00
# if defined(PR_SET_NAME)
2012-06-24 15:03:57 +00:00
// Only the first 15 characters are used (16 - NUL terminator)
: : prctl ( PR_SET_NAME , name , 0 , 0 , 0 ) ;
2012-06-30 15:23:04 +00:00
# elif 0 && (defined(__FreeBSD__) || defined(__OpenBSD__))
// TODO: This is currently disabled because it needs to be verified to work
// on FreeBSD or OpenBSD first. When verified the '0 &&' part can be
// removed.
pthread_set_name_np ( pthread_self ( ) , name ) ;
2012-08-21 15:59:24 +00:00
2013-03-07 03:16:05 +00:00
# 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
2012-08-21 15:59:24 +00:00
2012-06-24 15:03:57 +00:00
# else
// Prevent warnings for unused parameters...
( void ) name ;
# endif
}
2012-08-28 16:26:35 +00:00
2012-08-29 18:25:37 +00:00
bool NewThread ( void ( * pfn ) ( void * ) , void * parg )
2012-08-28 16:26:35 +00:00
{
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 ;
}