2017-03-22 11:56:18 -04:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# ifndef WIN32
// for posix_fallocate
# ifdef __linux__
# define _POSIX_C_SOURCE 200112L
# endif
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/resource.h>
# endif
2017-09-30 15:55:05 +08:00
# if defined(ANDROID)
# include <QDebug>
# include <QtAndroidExtras/QtAndroidExtras>
# include <QString>
# endif
2017-03-22 11:56:18 -04:00
# include "base58.h"
# include "util.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()
// Anoncoin
// For writing config file
# include <boost/property_tree/ptree.hpp>
# include <boost/property_tree/ini_parser.hpp>
# include <boost/property_tree/detail/info_parser_error.hpp>
// 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 <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
# 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>
# endif
using namespace std ;
map < string , string > mapArgs ;
map < string , vector < string > > mapMultiArgs ;
bool fDebug = false ;
bool fDebugNet = false ;
bool fPrintToConsole = false ;
bool fPrintToDebugger = false ;
bool fDaemon = false ;
bool fServer = false ;
bool fCommandLine = false ;
string strMiscWarning ;
bool fTestNet = false ;
bool fBloomFilters = true ;
bool fNoListen = false ;
bool fLogTimestamps = false ;
CMedianFilter < int64 > vTimeOffsets ( 200 , 0 ) ;
volatile bool fReopenDebugLog = false ;
bool fCachedPath [ 2 ] = { false , false } ;
// Init OpenSSL library multithreading support
static CCriticalSection * * ppmutexOpenSSL ;
void locking_callback ( int mode , int i , const char * file , int line )
{
if ( mode & CRYPTO_LOCK ) {
ENTER_CRITICAL_SECTION ( * ppmutexOpenSSL [ i ] ) ;
} else {
LEAVE_CRITICAL_SECTION ( * ppmutexOpenSSL [ i ] ) ;
}
}
LockedPageManager LockedPageManager : : instance ;
// Init
class CInit
{
public :
CInit ( )
{
// Init OpenSSL library multithreading support
ppmutexOpenSSL = ( CCriticalSection * * ) OPENSSL_malloc ( CRYPTO_num_locks ( ) * sizeof ( CCriticalSection * ) ) ;
for ( int i = 0 ; i < CRYPTO_num_locks ( ) ; i + + )
ppmutexOpenSSL [ i ] = new CCriticalSection ( ) ;
CRYPTO_set_locking_callback ( locking_callback ) ;
# ifdef WIN32
// Seed random number generator with screen scrape and other hardware sources
RAND_screen ( ) ;
# endif
// Seed random number generator with performance counter
RandAddSeed ( ) ;
}
~ CInit ( )
{
// Shutdown OpenSSL library multithreading support
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
int64 nCounter = GetPerformanceCounter ( ) ;
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
static int64 nLastPerfmon ;
if ( GetTime ( ) < nLastPerfmon + 10 * 60 )
return ;
nLastPerfmon = GetTime ( ) ;
# ifdef WIN32
// 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 ) ;
OPENSSL_cleanse ( pdata , nSize ) ;
printf ( " RandAddSeed() %lu bytes \n " , nSize ) ;
}
# endif
}
uint64 GetRand ( uint64 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 ;
do
RAND_bytes ( ( unsigned char * ) & nRand , sizeof ( nRand ) ) ;
while ( nRand > = nRange ) ;
return ( nRand % nMax ) ;
}
int GetRandInt ( int nMax )
{
return GetRand ( nMax ) ;
}
uint256 GetRandHash ( )
{
uint256 hash ;
RAND_bytes ( ( unsigned char * ) & hash , sizeof ( hash ) ) ;
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
// 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).
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 ( )
{
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
if ( fPrintToConsole )
{
// print to console
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
ret + = vprintf ( pszFormat , arg_ptr ) ;
va_end ( arg_ptr ) ;
}
else if ( ! fPrintToDebugger )
{
static bool fStartedNewLine = true ;
boost : : call_once ( & DebugPrintInit , debugPrintInitFlag ) ;
if ( fileout = = NULL )
return ret ;
boost : : mutex : : scoped_lock scoped_lock ( * mutexDebugLog ) ;
// reopen the log file, if requested
if ( fReopenDebugLog ) {
fReopenDebugLog = false ;
boost : : filesystem : : path pathDebug = GetDataDir ( ) / " debug.log " ;
if ( freopen ( pathDebug . string ( ) . c_str ( ) , " a " , fileout ) ! = NULL )
setbuf ( fileout , NULL ) ; // unbuffered
}
// 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 ;
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
ret + = vfprintf ( fileout , pszFormat , arg_ptr ) ;
va_end ( arg_ptr ) ;
}
# 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
{
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 ;
}
}
string FormatMoney ( int64 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 ;
2017-03-28 20:54:08 +03:00
string str = strprintf ( " % " PRI64d " .%08 " PRI64d , quotient , remainder ) ;
2017-03-22 11:56:18 -04:00
// Right-trim excess zeros before the decimal point:
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 ;
}
bool ParseMoney ( const string & str , int64 & nRet )
{
return ParseMoney ( str . c_str ( ) , nRet ) ;
}
bool ParseMoney ( const char * pszIn , int64 & nRet )
{
string strWhole ;
int64 nUnits = 0 ;
const char * p = pszIn ;
while ( isspace ( * p ) )
p + + ;
for ( ; * p ; p + + )
{
if ( * p = = ' . ' )
{
p + + ;
int64 nMult = CENT * 10 ;
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 ;
if ( strWhole . size ( ) > 10 ) // guard against 63 bit overflow
return false ;
if ( nUnits < 0 | | nUnits > COIN )
return false ;
int64 nWhole = atoi64 ( strWhole ) ;
int64 nValue = nWhole * COIN + nUnits ;
nRet = nValue ;
return true ;
}
static const signed char phexdigit [ 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 ,
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 ,
- 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 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 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 )
{
BOOST_FOREACH ( unsigned char c , str )
{
if ( phexdigit [ c ] < 0 )
return false ;
}
return ( str . size ( ) > 0 ) & & ( str . size ( ) % 2 = = 0 ) ;
}
vector < unsigned char > ParseHex ( const char * psz )
{
// convert hex dump to vector
vector < unsigned char > vch ;
loop
{
while ( isspace ( * psz ) )
psz + + ;
signed char c = phexdigit [ ( unsigned char ) * psz + + ] ;
if ( c = = ( signed char ) - 1 )
break ;
unsigned char n = ( c < < 4 ) ;
c = phexdigit [ ( unsigned char ) * psz + + ] ;
if ( c = = ( signed char ) - 1 )
break ;
n | = c ;
vch . push_back ( n ) ;
}
return vch ;
}
vector < unsigned char > ParseHex ( const string & str )
{
return ParseHex ( str . c_str ( ) ) ;
}
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 " ) ;
}
}
}
void ParseParameters ( int argc , const char * const argv [ ] )
{
mapArgs . clear ( ) ;
mapMultiArgs . clear ( ) ;
for ( int i = 1 ; i < argc ; i + + )
{
std : : string str ( argv [ i ] ) ;
std : : string strValue ;
size_t is_index = str . find ( ' = ' ) ;
if ( is_index ! = std : : string : : npos )
{
strValue = str . substr ( is_index + 1 ) ;
str = str . substr ( 0 , is_index ) ;
}
# ifdef WIN32
boost : : to_lower ( str ) ;
if ( boost : : algorithm : : starts_with ( str , " / " ) )
str = " - " + str . substr ( 1 ) ;
# endif
if ( str [ 0 ] ! = ' - ' )
break ;
mapArgs [ str ] = strValue ;
mapMultiArgs [ str ] . push_back ( strValue ) ;
}
// 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 ;
}
// interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
InterpretNegativeSetting ( name , mapArgs ) ;
}
}
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 ;
}
bool SoftSetArg ( const std : : string & strArg , const std : : string & strValue )
{
if ( mapArgs . count ( strArg ) )
return false ;
mapArgs [ strArg ] = strValue ;
return true ;
}
bool SoftSetBoolArg ( const std : : string & strArg , bool fValue )
{
if ( fValue )
return SoftSetArg ( strArg , std : : string ( " 1 " ) ) ;
else
return SoftSetArg ( strArg , std : : string ( " 0 " ) ) ;
}
string EncodeBase64 ( const unsigned char * pch , size_t len )
{
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 )
{
return EncodeBase64 ( ( const unsigned char * ) str . c_str ( ) , str . size ( ) ) ;
}
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 )
{
int dec = decode64_table [ ( unsigned char ) * p ] ;
if ( dec = = - 1 ) break ;
p + + ;
switch ( mode )
{
case 0 : // we have no bits and get 6
left = dec ;
mode = 1 ;
break ;
case 1 : // we have 6 bits and keep 4
vchRet . push_back ( ( left < < 2 ) | ( dec > > 4 ) ) ;
left = dec & 15 ;
mode = 2 ;
break ;
case 2 : // we have 4 bits and get 6, we keep 2
vchRet . push_back ( ( left < < 4 ) | ( dec > > 2 ) ) ;
left = dec & 3 ;
mode = 3 ;
break ;
case 3 : // we have 2 bits and get 6
vchRet . push_back ( ( left < < 6 ) | dec ) ;
mode = 0 ;
break ;
}
}
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 '=='
if ( left | | p [ 0 ] ! = ' = ' | | p [ 1 ] ! = ' = ' | | decode64_table [ ( unsigned char ) p [ 2 ] ] ! = - 1 )
* pfInvalid = true ;
break ;
case 3 : // 4n+3 base64 characters processed: require '='
if ( left | | p [ 0 ] ! = ' = ' | | decode64_table [ ( unsigned char ) p [ 1 ] ] ! = - 1 )
* pfInvalid = true ;
break ;
}
return vchRet ;
}
string DecodeBase64 ( const string & str )
{
vector < unsigned char > vchRet = DecodeBase64 ( str . c_str ( ) ) ;
return string ( ( const char * ) & vchRet [ 0 ] , vchRet . size ( ) ) ;
}
string EncodeBase32 ( const unsigned char * pch , size_t len )
{
static const char * pbase32 = " abcdefghijklmnopqrstuvwxyz234567 " ;
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 ( ) ) ;
}
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 ( ) ) ;
}
// Anoncoin
// Write config file
bool writeConfig ( boost : : filesystem : : path configFile , boost : : property_tree : : ptree data )
{
// Write file
try
{
write_ini ( configFile . string ( ) , data ) ;
}
catch ( boost : : property_tree : : info_parser : : info_parser_error & e )
{
printf ( " Error writing config file: %s \n " , e . what ( ) ) ;
return false ;
}
return true ;
}
2017-05-04 16:15:09 -04:00
// call upon first run
2017-06-30 11:40:54 -04:00
bool writeFirstConfig ( bool i2pOnlyEnabled , bool i2pEnabled )
2017-03-22 11:56:18 -04:00
{
using boost : : property_tree : : ptree ;
ptree pt ;
2017-06-30 11:40:54 -04:00
if ( i2pOnlyEnabled )
pt . put ( " onlynet " , " i2p " ) ;
if ( i2pEnabled )
pt . put ( " i2p " , 1 ) ;
2017-03-22 11:56:18 -04:00
unsigned char rand_pwd [ 32 ] ;
RAND_bytes ( rand_pwd , 32 ) ;
2017-03-27 14:28:23 -04:00
pt . put ( " rpcuser " , " gostcoinrpc " ) ;
2017-03-22 11:56:18 -04:00
pt . put ( " rpcpassword " , EncodeBase58 ( & rand_pwd [ 0 ] , & rand_pwd [ 0 ] + 32 ) . c_str ( ) ) ;
pt . put ( " daemon " , 1 ) ;
pt . put ( " server " , 1 ) ;
// Write file
return writeConfig ( GetConfigFile ( ) . string ( ) . c_str ( ) , pt ) ;
}
static std : : string FormatException ( std : : exception * pex , const char * pszThread )
{
# ifdef WIN32
char pszModule [ MAX_PATH ] = " " ;
GetModuleFileNameA ( NULL , pszModule , sizeof ( pszModule ) ) ;
# else
2017-03-27 14:28:23 -04:00
const char * pszModule = " gostcoin " ;
2017-03-22 11:56:18 -04:00
# endif
if ( pex )
return strprintf (
" EXCEPTION: %s \n %s \n %s in %s \n " , typeid ( * pex ) . name ( ) , pex - > what ( ) , pszModule , pszThread ) ;
else
return strprintf (
" UNKNOWN EXCEPTION \n %s in %s \n " , pszModule , pszThread ) ;
}
void LogException ( std : : exception * pex , const char * pszThread )
{
std : : string message = FormatException ( pex , pszThread ) ;
printf ( " \n %s " , message . c_str ( ) ) ;
}
void PrintException ( std : : exception * pex , const char * pszThread )
{
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 ;
throw ;
}
void PrintExceptionContinue ( std : : exception * pex , const char * pszThread )
{
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 ;
}
boost : : filesystem : : path GetDefaultDataDir ( )
{
namespace fs = boost : : filesystem ;
2017-10-05 16:25:19 +03:00
// Windows < Vista: C:\Documents and Settings\Username\Application Data\Gostcoin
// Windows >= Vista: C:\Users\Username\AppData\Roaming\Gostcoin
// Mac: ~/Library/Application Support/Gostcoin
// Unix: ~/.gostcoin
2017-03-22 11:56:18 -04:00
# ifdef WIN32
// Windows
2017-03-27 14:28:23 -04:00
return GetSpecialFolderPath ( CSIDL_APPDATA ) / " Gostcoin " ;
2017-03-22 11:56:18 -04:00
# else
fs : : path pathRet ;
2017-09-30 15:55:05 +08:00
# if defined(ANDROID)
QAndroidJniObject mediaDir = QAndroidJniObject : : callStaticObjectMethod ( " android/os/Environment " , " getExternalStorageDirectory " , " ()Ljava/io/File; " ) ;
QAndroidJniObject mediaPath = mediaDir . callObjectMethod ( " getAbsolutePath " , " ()Ljava/lang/String; " ) ;
QString dataAbsPath = mediaPath . toString ( ) ;
QAndroidJniEnvironment env ;
if ( env - > ExceptionCheck ( ) ) {
// Handle exception here.
env - > ExceptionClear ( ) ;
}
std : : string ext = dataAbsPath . toStdString ( ) ;
//if (!ext) ext = "/sdcard";
if ( boost : : filesystem : : exists ( ext ) )
{
fs : : path canonical = fs : : canonical ( fs : : path ( std : : string ( ext ) ) ) ;
pathRet = fs : : path ( std : : string ( canonical . c_str ( ) ) + " /gostcoin " ) ;
boost : : filesystem : : path dir = pathRet ;
2017-10-01 01:34:27 +08:00
if ( ! boost : : filesystem : : exists ( dir ) ) {
qDebug ( ) < < " creating dir ' " < < pathRet . c_str ( ) < < " ' " ;
boost : : filesystem : : create_directory ( dir ) ;
} else {
qDebug ( ) < < " dir exists: ' " < < pathRet . c_str ( ) < < " ' " ;
}
2017-09-30 15:55:05 +08:00
return pathRet ;
}
// otherwise use /data/.../files
# endif
2017-03-22 11:56:18 -04:00
char * pszHome = getenv ( " HOME " ) ;
if ( pszHome = = NULL | | strlen ( pszHome ) = = 0 )
pathRet = fs : : path ( " / " ) ;
else
pathRet = fs : : path ( pszHome ) ;
# ifdef MAC_OSX
// Mac
pathRet / = " Library/Application Support " ;
fs : : create_directory ( pathRet ) ;
2017-03-27 14:28:23 -04:00
return pathRet / " Gostcoin " ;
2017-03-22 11:56:18 -04:00
# else
// Unix
2017-03-27 14:28:23 -04:00
return pathRet / " .gostcoin " ;
2017-03-22 11:56:18 -04:00
# endif
# endif
}
const boost : : filesystem : : path & GetDataDir ( bool fNetSpecific )
{
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.
if ( fCachedPath [ fNetSpecific ] )
return path ;
LOCK ( csPathCached ) ;
if ( mapArgs . count ( " -datadir " ) ) {
path = fs : : system_complete ( mapArgs [ " -datadir " ] ) ;
if ( ! fs : : is_directory ( path ) ) {
path = " " ;
return path ;
}
} else {
path = GetDefaultDataDir ( ) ;
}
if ( fNetSpecific & & GetBoolArg ( " -testnet " , false ) )
2017-10-05 16:25:19 +03:00
{
fs : : create_directory ( path ) ;
2017-03-22 11:56:18 -04:00
path / = " testnet3 " ;
2017-10-05 16:25:19 +03:00
}
2017-03-22 11:56:18 -04:00
fs : : create_directory ( path ) ;
fCachedPath [ fNetSpecific ] = true ;
return path ;
}
boost : : filesystem : : path GetConfigFile ( )
{
2017-03-27 14:28:23 -04:00
boost : : filesystem : : path pathConfigFile ( GetArg ( " -conf " , " gostcoin.conf " ) ) ;
2017-03-22 11:56:18 -04:00
if ( ! pathConfigFile . is_complete ( ) ) pathConfigFile = GetDataDir ( false ) / pathConfigFile ;
return pathConfigFile ;
}
void ReadConfigFile ( map < string , string > & mapSettingsRet ,
map < string , vector < string > > & mapMultiSettingsRet )
{
boost : : filesystem : : ifstream streamConfig ( GetConfigFile ( ) ) ;
if ( ! streamConfig . good ( ) )
return ; // No bitcoin.conf file is OK
// clear path cache after loading config file
fCachedPath [ 0 ] = fCachedPath [ 1 ] = false ;
set < string > setOptions ;
setOptions . insert ( " * " ) ;
for ( boost : : program_options : : detail : : config_file_iterator it ( streamConfig , setOptions ) , end ; it ! = end ; + + it )
{
// Don't overwrite existing settings so command line settings override bitcoin.conf
string strKey = string ( " - " ) + it - > string_key ;
if ( mapSettingsRet . count ( strKey ) = = 0 )
{
mapSettingsRet [ strKey ] = it - > value [ 0 ] ;
// interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
InterpretNegativeSetting ( strKey , mapSettingsRet ) ;
}
mapMultiSettingsRet [ strKey ] . push_back ( it - > value [ 0 ] ) ;
}
}
boost : : filesystem : : path GetPidFile ( )
{
2017-03-27 14:28:23 -04:00
boost : : filesystem : : path pathPidFile ( GetArg ( " -pid " , " gostcoind.pid " ) ) ;
2017-03-22 11:56:18 -04:00
if ( ! pathPidFile . is_complete ( ) ) pathPidFile = GetDataDir ( ) / pathPidFile ;
return pathPidFile ;
}
# ifndef WIN32
void CreatePidFile ( const boost : : filesystem : : path & path , pid_t pid )
{
FILE * file = fopen ( path . string ( ) . c_str ( ) , " w " ) ;
if ( file )
{
fprintf ( file , " %d \n " , pid ) ;
fclose ( file ) ;
}
}
# endif
bool RenameOver ( boost : : filesystem : : path src , boost : : filesystem : : path dest )
{
# ifdef WIN32
return MoveFileExA ( src . string ( ) . c_str ( ) , dest . string ( ) . c_str ( ) ,
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
# 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
# endif
}
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 ;
}
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 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 ) ;
2017-09-24 22:46:37 +08:00
# elif defined(__linux__) && !defined(ANDROID)
//android doesn't have posix_fallocate
2017-03-22 11:56:18 -04:00
// 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 ) {
unsigned int now = 65536 ;
if ( length < now )
now = length ;
fwrite ( buf , 1 , now , file ) ; // allowed to fail; this function is advisory anyway
length - = now ;
}
# endif
}
void ShrinkDebugFile ( )
{
// Scroll debug.log if it's getting too big
boost : : filesystem : : path pathLog = GetDataDir ( ) / " debug.log " ;
FILE * file = fopen ( pathLog . string ( ) . c_str ( ) , " r " ) ;
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 ) ;
file = fopen ( pathLog . string ( ) . c_str ( ) , " w " ) ;
if ( file )
{
fwrite ( pch , 1 , nBytes , file ) ;
fclose ( file ) ;
}
}
else if ( file ! = NULL )
fclose ( file ) ;
}
//
// "Never go to sea with two chronometers; take one or three."
// Our three time sources are:
// - System clock
// - 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
int64 GetTime ( )
{
if ( nMockTime ) return nMockTime ;
return time ( NULL ) ;
}
void SetMockTime ( int64 nMockTimeIn )
{
nMockTime = nMockTimeIn ;
}
static int64 nTimeOffset = 0 ;
int64 GetTimeOffset ( )
{
return nTimeOffset ;
}
int64 GetAdjustedTime ( )
{
return GetTime ( ) + GetTimeOffset ( ) ;
}
void AddTimeData ( const CNetAddr & ip , int64 nTime )
{
int64 nOffsetSample = nTime - GetTime ( ) ;
// Ignore duplicates
static set < CNetAddr > setKnown ;
if ( ! setKnown . insert ( ip ) . second )
return ;
// Add data
vTimeOffsets . input ( nOffsetSample ) ;
2017-03-28 20:54:08 +03:00
printf ( " Added time data, samples %d, offset %+ " PRI64d " (%+ " PRI64d " minutes) \n " , vTimeOffsets . size ( ) , nOffsetSample , nOffsetSample / 60 ) ;
2017-03-22 11:56:18 -04:00
if ( vTimeOffsets . size ( ) > = 5 & & vTimeOffsets . size ( ) % 2 = = 1 )
{
int64 nMedian = vTimeOffsets . median ( ) ;
std : : vector < int64 > vSorted = vTimeOffsets . sorted ( ) ;
// Only let other nodes change our time by so much
if ( abs64 ( nMedian ) < 35 * 60 ) // Litecoin: changed maximum adjust to 35 mins to avoid letting peers change our time too much in case of an attack.
{
nTimeOffset = nMedian ;
}
else
{
nTimeOffset = 0 ;
static bool fDone ;
if ( ! fDone )
{
// 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 )
if ( nOffset ! = 0 & & abs64 ( nOffset ) < 5 * 60 )
fMatch = true ;
if ( ! fMatch )
{
fDone = true ;
2017-03-22 21:42:40 -04:00
string strMessage = _ ( " Warning: Please check that your computer's date and time are correct! If your clock is wrong Unioncoin will not work properly. " ) ;
2017-03-22 11:56:18 -04:00
strMiscWarning = strMessage ;
printf ( " *** %s \n " , strMessage . c_str ( ) ) ;
uiInterface . ThreadSafeMessageBox ( strMessage , " " , CClientUIInterface : : MSG_WARNING ) ;
}
}
}
if ( fDebug ) {
BOOST_FOREACH ( int64 n , vSorted )
2017-03-28 20:54:08 +03:00
printf ( " %+ " PRI64d " " , n ) ;
2017-03-22 11:56:18 -04:00
printf ( " | " ) ;
}
2017-03-28 20:54:08 +03:00
printf ( " nTimeOffset = %+ " PRI64d " (%+ " PRI64d " minutes) \n " , nTimeOffset , nTimeOffset / 60 ) ;
2017-03-22 11:56:18 -04: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 ;
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 )
{
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 ( )
{
return CLIENT_BUILD ;
}
std : : string FormatI2PNativeFullVersion ( )
{
return I2P_MODULE_VERSION ;
}
// 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 ( ) ;
}
# ifdef WIN32
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 ( " " ) ;
}
# endif
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
}
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 ) ;
}
void RenameThread ( const char * name )
{
# if defined(PR_SET_NAME)
// Only the first 15 characters are used (16 - NUL terminator)
: : prctl ( PR_SET_NAME , name , 0 , 0 , 0 ) ;
# 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 ) ;
# 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...
( void ) 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 ;
}