2011-05-14 17:25:05 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2014-02-08 22:50:24 +01:00
// Copyright (c) 2009-2014 The Bitcoin developers
2011-05-14 17:25:05 +02:00
// Distributed under the MIT/X11 software license, see the accompanying
2012-05-18 16:02:28 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2012-03-31 15:22:45 +02:00
2013-04-13 07:13:08 +02:00
# include "util.h"
2014-06-19 15:10:04 +02:00
# include "chainparamsbase.h"
2014-06-26 14:41:53 +02:00
# include "random.h"
2013-04-13 07:13:08 +02:00
# include "sync.h"
# include "uint256.h"
# include "version.h"
# include <stdarg.h>
2014-05-08 18:01:10 +02:00
# include <boost/date_time/posix_time/posix_time.hpp>
2013-01-28 00:07:51 +01:00
# ifndef WIN32
// for posix_fallocate
2013-04-13 07:13:08 +02:00
# ifdef __linux_
# ifdef _POSIX_C_SOURCE
# undef _POSIX_C_SOURCE
# endif
2013-01-28 00:07:51 +01:00
# define _POSIX_C_SOURCE 200112L
2013-04-13 07:13:08 +02:00
# include <sys/prctl.h>
2013-01-28 00:07:51 +01:00
# endif
2013-04-13 07:13:08 +02:00
2013-07-17 04:20:09 +02:00
# include <algorithm>
2013-01-28 00:07:51 +01:00
# include <fcntl.h>
2013-04-26 00:46:47 +02:00
# include <sys/resource.h>
2013-04-13 07:13:08 +02:00
# include <sys/stat.h>
2012-04-15 11:42:40 +02:00
2013-04-13 07:13:08 +02:00
# else
2012-04-15 22:10:54 +02:00
# ifdef _MSC_VER
# pragma warning(disable:4786)
# pragma warning(disable:4804)
# pragma warning(disable:4805)
# pragma warning(disable:4717)
# endif
2013-04-13 07:13:08 +02:00
2012-04-15 22:10:54 +02:00
# ifdef _WIN32_WINNT
# undef _WIN32_WINNT
# endif
# define _WIN32_WINNT 0x0501
2013-04-13 07:13:08 +02:00
2012-04-15 22:10:54 +02:00
# ifdef _WIN32_IE
# undef _WIN32_IE
# endif
2012-05-03 02:21:43 +02:00
# define _WIN32_IE 0x0501
2013-04-13 07:13:08 +02:00
2012-04-15 22:10:54 +02:00
# define WIN32_LEAN_AND_MEAN 1
# ifndef NOMINMAX
# define NOMINMAX
# endif
2013-04-13 07:13:08 +02:00
2012-05-17 18:30:09 +02:00
# include <io.h> /* for _commit */
2013-04-13 07:13:08 +02:00
# include <shlobj.h>
2012-04-15 22:10:54 +02:00
# endif
2011-05-14 17:25:05 +02:00
2013-04-13 07:13:08 +02:00
# include <boost/algorithm/string/case_conv.hpp> // for to_lower()
# include <boost/algorithm/string/join.hpp>
# include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
# include <boost/filesystem.hpp>
# include <boost/filesystem/fstream.hpp>
# include <boost/foreach.hpp>
# include <boost/program_options/detail/config_file.hpp>
# include <boost/program_options/parsers.hpp>
# include <openssl/crypto.h>
# include <openssl/rand.h>
// Work around clang compilation problem in Boost 1.46:
// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup
// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
namespace boost {
2014-06-24 14:17:43 +02:00
2013-04-13 07:13:08 +02:00
namespace program_options {
std : : string to_internal ( const std : : string & ) ;
}
2014-06-24 14:17:43 +02:00
} // namespace boost
2013-04-13 07:13:08 +02:00
2011-05-14 17:25:05 +02:00
using namespace std ;
map < string , string > mapArgs ;
map < string , vector < string > > mapMultiArgs ;
bool fDebug = false ;
bool fPrintToConsole = false ;
2013-12-14 13:51:11 +01:00
bool fPrintToDebugLog = true ;
2011-05-14 17:25:05 +02:00
bool fDaemon = false ;
bool fServer = false ;
string strMiscWarning ;
bool fLogTimestamps = false ;
2014-02-27 02:55:04 +01:00
bool fLogIPs = false ;
2013-01-01 23:12:30 +01:00
volatile bool fReopenDebugLog = false ;
2011-05-14 17:25:05 +02:00
2012-07-21 12:44:54 +02:00
// Init OpenSSL library multithreading support
2012-05-11 17:00:03 +02:00
static CCriticalSection * * ppmutexOpenSSL ;
2011-05-14 17:25:05 +02:00
void locking_callback ( int mode , int i , const char * file , int line )
{
2012-05-11 17:00:03 +02:00
if ( mode & CRYPTO_LOCK ) {
ENTER_CRITICAL_SECTION ( * ppmutexOpenSSL [ i ] ) ;
} else {
LEAVE_CRITICAL_SECTION ( * ppmutexOpenSSL [ i ] ) ;
}
2011-05-14 17:25:05 +02:00
}
// Init
class CInit
{
public :
CInit ( )
{
2012-07-21 12:44:54 +02:00
// Init OpenSSL library multithreading support
2012-05-11 17:00:03 +02:00
ppmutexOpenSSL = ( CCriticalSection * * ) OPENSSL_malloc ( CRYPTO_num_locks ( ) * sizeof ( CCriticalSection * ) ) ;
2011-05-14 17:25:05 +02:00
for ( int i = 0 ; i < CRYPTO_num_locks ( ) ; i + + )
2012-05-11 17:00:03 +02:00
ppmutexOpenSSL [ i ] = new CCriticalSection ( ) ;
2011-05-14 17:25:05 +02:00
CRYPTO_set_locking_callback ( locking_callback ) ;
2011-10-07 17:02:21 +02:00
# ifdef WIN32
2014-06-24 14:41:26 +02:00
// Seed OpenSSL PRNG with current contents of the screen
2011-05-14 17:25:05 +02:00
RAND_screen ( ) ;
# endif
2014-06-24 14:41:26 +02:00
// Seed OpenSSL PRNG with performance counter
2011-05-14 17:25:05 +02:00
RandAddSeed ( ) ;
}
~ CInit ( )
{
2014-06-24 14:41:26 +02:00
// Securely erase the memory used by the PRNG
RAND_cleanup ( ) ;
2012-07-21 12:44:54 +02:00
// Shutdown OpenSSL library multithreading support
2011-05-14 17:25:05 +02:00
CRYPTO_set_locking_callback ( NULL ) ;
for ( int i = 0 ; i < CRYPTO_num_locks ( ) ; i + + )
delete ppmutexOpenSSL [ i ] ;
OPENSSL_free ( ppmutexOpenSSL ) ;
}
}
instance_of_cinit ;
2013-09-19 14:47:21 +02:00
// LogPrintf() has been broken a couple of times now
2013-01-01 23:12:30 +01:00
// 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 17:25:05 +02:00
2013-01-01 23:12:30 +01: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 17:25:05 +02:00
{
2013-01-01 23:12:30 +01: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 ( ) ;
}
2014-01-16 15:52:37 +01:00
bool LogAcceptCategory ( const char * category )
2013-01-01 23:12:30 +01:00
{
2013-09-18 10:03:21 +02:00
if ( category ! = NULL )
{
2013-10-08 12:09:40 +02:00
if ( ! fDebug )
2014-01-16 15:52:37 +01:00
return false ;
2013-10-08 12:09:40 +02:00
2013-12-10 04:19:18 +01:00
// Give each thread quick access to -debug settings.
// This helps prevent issues debugging global destructors,
// where mapMultiArgs might be deleted before another
// global destructor calls LogPrint()
static boost : : thread_specific_ptr < set < string > > ptrCategory ;
if ( ptrCategory . get ( ) = = NULL )
2013-10-08 12:09:40 +02:00
{
2013-12-10 04:19:18 +01:00
const vector < string > & categories = mapMultiArgs [ " -debug " ] ;
ptrCategory . reset ( new set < string > ( categories . begin ( ) , categories . end ( ) ) ) ;
// thread_specific_ptr automatically deletes the set when the thread ends.
2013-10-08 12:09:40 +02:00
}
2013-12-10 04:19:18 +01:00
const set < string > & setCategories = * ptrCategory . get ( ) ;
// if not debugging everything and not debugging specific category, LogPrint does nothing.
if ( setCategories . count ( string ( " " ) ) = = 0 & &
setCategories . count ( string ( category ) ) = = 0 )
2014-01-16 15:52:37 +01:00
return false ;
2013-09-18 10:03:21 +02:00
}
2014-01-16 15:52:37 +01:00
return true ;
}
2013-09-18 10:03:21 +02:00
2014-01-16 15:52:37 +01:00
int LogPrintStr ( const std : : string & str )
{
2013-01-01 23:12:30 +01:00
int ret = 0 ; // Returns total number of characters written
2011-05-14 17:25:05 +02:00
if ( fPrintToConsole )
{
// print to console
2014-01-16 15:52:37 +01:00
ret = fwrite ( str . data ( ) , 1 , str . size ( ) , stdout ) ;
2011-05-14 17:25:05 +02:00
}
2014-07-15 10:22:27 +02:00
else if ( fPrintToDebugLog & & AreBaseParamsConfigured ( ) )
2011-05-14 17:25:05 +02:00
{
2013-01-01 23:12:30 +01:00
static bool fStartedNewLine = true ;
boost : : call_once ( & DebugPrintInit , debugPrintInitFlag ) ;
2011-05-14 17:25:05 +02:00
2013-01-01 23:12:30 +01: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 23:50:56 +02:00
boost : : filesystem : : path pathDebug = GetDataDir ( ) / " debug.log " ;
2013-01-01 23:12:30 +01:00
if ( freopen ( pathDebug . string ( ) . c_str ( ) , " a " , fileout ) ! = NULL )
setbuf ( fileout , NULL ) ; // unbuffered
2011-05-14 17:25:05 +02:00
}
2013-01-01 23:12:30 +01:00
// Debug print useful for profiling
if ( fLogTimestamps & & fStartedNewLine )
ret + = fprintf ( fileout , " %s " , DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , GetTime ( ) ) . c_str ( ) ) ;
2014-01-16 15:52:37 +01:00
if ( ! str . empty ( ) & & str [ str . size ( ) - 1 ] = = ' \n ' )
2013-01-01 23:12:30 +01:00
fStartedNewLine = true ;
else
fStartedNewLine = false ;
2011-05-14 17:25:05 +02:00
2014-01-16 15:52:37 +01:00
ret = fwrite ( str . data ( ) , 1 , str . size ( ) , fileout ) ;
2011-05-14 17:25:05 +02:00
}
return ret ;
}
2013-04-13 07:13:08 +02:00
string FormatMoney ( int64_t n , bool fPlus )
2011-05-14 17:25:05 +02:00
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
2013-04-13 07:13:08 +02:00
int64_t n_abs = ( n > 0 ? n : - n ) ;
int64_t quotient = n_abs / COIN ;
int64_t remainder = n_abs % COIN ;
2014-02-24 09:08:56 +01:00
string str = strprintf ( " %d.%08d " , quotient , remainder ) ;
2011-05-14 17:25:05 +02:00
2012-07-26 05:25:26 +02:00
// Right-trim excess zeros before the decimal point:
2011-05-14 17:25:05 +02: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 ;
}
2013-04-13 07:13:08 +02:00
bool ParseMoney ( const string & str , int64_t & nRet )
2011-05-14 17:25:05 +02:00
{
return ParseMoney ( str . c_str ( ) , nRet ) ;
}
2013-04-13 07:13:08 +02:00
bool ParseMoney ( const char * pszIn , int64_t & nRet )
2011-05-14 17:25:05 +02:00
{
string strWhole ;
2013-04-13 07:13:08 +02:00
int64_t nUnits = 0 ;
2011-05-14 17:25:05 +02:00
const char * p = pszIn ;
while ( isspace ( * p ) )
p + + ;
for ( ; * p ; p + + )
{
if ( * p = = ' . ' )
{
p + + ;
2013-04-13 07:13:08 +02:00
int64_t nMult = CENT * 10 ;
2011-05-14 17:25:05 +02: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 02:47:47 +02:00
if ( strWhole . size ( ) > 10 ) // guard against 63 bit overflow
2011-05-14 17:25:05 +02:00
return false ;
if ( nUnits < 0 | | nUnits > COIN )
return false ;
2013-04-13 07:13:08 +02:00
int64_t nWhole = atoi64 ( strWhole ) ;
int64_t nValue = nWhole * COIN + nUnits ;
2011-05-14 17:25:05 +02:00
nRet = nValue ;
return true ;
}
2013-11-01 20:27:42 +01:00
// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
// even possibly remotely dangerous like & or >
static string safeChars ( " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@ " ) ;
string SanitizeString ( const string & str )
{
string strResult ;
for ( std : : string : : size_type i = 0 ; i < str . size ( ) ; i + + )
{
if ( safeChars . find ( str [ i ] ) ! = std : : string : : npos )
strResult . push_back ( str [ i ] ) ;
}
return strResult ;
}
2011-05-14 17:25:05 +02:00
2013-10-10 18:35:51 +02:00
const signed char p_util_hexdigit [ 256 ] =
2012-01-05 03:40:52 +01: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 07:31:38 +02:00
- 1 , 0xa , 0xb , 0xc , 0xd , 0xe , 0xf , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
2012-01-05 03:40:52 +01: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 , } ;
2014-06-28 17:35:22 +02:00
signed char HexDigit ( char c )
{
return p_util_hexdigit [ ( unsigned char ) c ] ;
}
2012-01-05 03:40:52 +01:00
bool IsHex ( const string & str )
2011-05-14 17:25:05 +02:00
{
2013-10-10 18:35:51 +02:00
BOOST_FOREACH ( char c , str )
2012-01-05 03:40:52 +01:00
{
2013-10-10 18:35:51 +02:00
if ( HexDigit ( c ) < 0 )
2012-01-05 03:40:52 +01:00
return false ;
}
return ( str . size ( ) > 0 ) & & ( str . size ( ) % 2 = = 0 ) ;
}
2011-05-14 17:25:05 +02:00
2012-01-05 03:40:52 +01:00
vector < unsigned char > ParseHex ( const char * psz )
{
2011-05-14 17:25:05 +02:00
// convert hex dump to vector
vector < unsigned char > vch ;
2013-07-31 06:06:44 +02:00
while ( true )
2011-05-14 17:25:05 +02:00
{
while ( isspace ( * psz ) )
psz + + ;
2013-10-10 18:35:51 +02:00
signed char c = HexDigit ( * psz + + ) ;
2012-04-16 07:32:55 +02:00
if ( c = = ( signed char ) - 1 )
2011-05-14 17:25:05 +02:00
break ;
unsigned char n = ( c < < 4 ) ;
2013-10-10 18:35:51 +02:00
c = HexDigit ( * psz + + ) ;
2012-04-16 07:32:55 +02:00
if ( c = = ( signed char ) - 1 )
2011-05-14 17:25:05 +02: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 21:08:32 +01: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 )
{
2013-04-28 17:37:50 +02:00
bool value = ! GetBoolArg ( name , false ) ;
2012-02-16 21:08:32 +01:00
mapSettingsRet [ positive ] = ( value ? " 1 " : " 0 " ) ;
}
}
}
2012-04-22 16:22:45 +02:00
void ParseParameters ( int argc , const char * const argv [ ] )
2011-05-14 17:25:05 +02:00
{
mapArgs . clear ( ) ;
mapMultiArgs . clear ( ) ;
2014-06-04 06:36:45 +02:00
2011-05-14 17:25:05 +02:00
for ( int i = 1 ; i < argc ; i + + )
{
2012-10-02 21:36:39 +02:00
std : : string str ( argv [ i ] ) ;
std : : string strValue ;
size_t is_index = str . find ( ' = ' ) ;
if ( is_index ! = std : : string : : npos )
2011-05-14 17:25:05 +02:00
{
2012-10-02 21:36:39 +02:00
strValue = str . substr ( is_index + 1 ) ;
str = str . substr ( 0 , is_index ) ;
2011-05-14 17:25:05 +02:00
}
2012-10-02 21:36:39 +02:00
# ifdef WIN32
boost : : to_lower ( str ) ;
if ( boost : : algorithm : : starts_with ( str , " / " ) )
str = " - " + str . substr ( 1 ) ;
# endif
2014-06-04 06:36:45 +02:00
2012-10-02 21:36:39 +02:00
if ( str [ 0 ] ! = ' - ' )
2011-05-14 17:25:05 +02:00
break ;
2012-02-06 19:55:11 +01:00
2014-06-04 06:36:45 +02:00
// Interpret --foo as -foo.
// If both --foo and -foo are set, the last takes effect.
if ( str . length ( ) > 1 & & str [ 1 ] = = ' - ' )
str = str . substr ( 1 ) ;
2012-10-02 21:36:39 +02:00
mapArgs [ str ] = strValue ;
mapMultiArgs [ str ] . push_back ( strValue ) ;
2011-05-14 17:25:05 +02:00
}
2012-02-06 19:55:11 +01:00
// New 0.6 features:
BOOST_FOREACH ( const PAIRTYPE ( string , string ) & entry , mapArgs )
{
2012-02-16 21:08:32 +01:00
// interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
2014-06-04 06:36:45 +02:00
InterpretNegativeSetting ( entry . first , mapArgs ) ;
2012-02-06 19:55:11 +01:00
}
2011-05-14 17:25:05 +02:00
}
2012-02-06 18:37:49 +01:00
std : : string GetArg ( const std : : string & strArg , const std : : string & strDefault )
{
if ( mapArgs . count ( strArg ) )
return mapArgs [ strArg ] ;
return strDefault ;
}
2013-04-13 07:13:08 +02:00
int64_t GetArg ( const std : : string & strArg , int64_t nDefault )
2012-02-06 18:37:49 +01:00
{
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 16:14:22 +01: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 21:48:00 +01:00
bool SoftSetBoolArg ( const std : : string & strArg , bool fValue )
2012-01-03 16:14:22 +01:00
{
if ( fValue )
return SoftSetArg ( strArg , std : : string ( " 1 " ) ) ;
else
return SoftSetArg ( strArg , std : : string ( " 0 " ) ) ;
}
2011-09-20 15:38:29 +02:00
string EncodeBase64 ( const unsigned char * pch , size_t len )
2011-07-26 00:13:55 +02:00
{
2011-09-20 15:38:29 +02: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-26 00:13:55 +02:00
{
2011-09-20 15:38:29 +02:00
return EncodeBase64 ( ( const unsigned char * ) str . c_str ( ) , str . size ( ) ) ;
}
2011-07-26 00:13:55 +02:00
2011-09-20 15:38:29 +02: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-26 00:13:55 +02:00
{
2012-04-15 12:22:30 +02:00
int dec = decode64_table [ ( unsigned char ) * p ] ;
2011-09-20 15:38:29 +02:00
if ( dec = = - 1 ) break ;
p + + ;
switch ( mode )
2011-07-26 00:13:55 +02: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 15:38:29 +02:00
vchRet . push_back ( ( left < < 2 ) | ( dec > > 4 ) ) ;
2011-07-26 00:13:55 +02:00
left = dec & 15 ;
mode = 2 ;
break ;
2011-09-20 15:38:29 +02:00
case 2 : // we have 4 bits and get 6, we keep 2
vchRet . push_back ( ( left < < 4 ) | ( dec > > 2 ) ) ;
2011-07-26 00:13:55 +02:00
left = dec & 3 ;
mode = 3 ;
break ;
2011-09-20 15:38:29 +02:00
2011-07-26 00:13:55 +02:00
case 3 : // we have 2 bits and get 6
2011-09-20 15:38:29 +02:00
vchRet . push_back ( ( left < < 6 ) | dec ) ;
mode = 0 ;
2011-07-26 00:13:55 +02:00
break ;
}
}
2011-09-20 15:38:29 +02: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 12:22:30 +02:00
if ( left | | p [ 0 ] ! = ' = ' | | p [ 1 ] ! = ' = ' | | decode64_table [ ( unsigned char ) p [ 2 ] ] ! = - 1 )
2011-09-20 15:38:29 +02:00
* pfInvalid = true ;
break ;
case 3 : // 4n+3 base64 characters processed: require '='
2012-04-15 12:22:30 +02:00
if ( left | | p [ 0 ] ! = ' = ' | | decode64_table [ ( unsigned char ) p [ 1 ] ] ! = - 1 )
2011-09-20 15:38:29 +02:00
* pfInvalid = true ;
break ;
}
return vchRet ;
2011-07-26 00:13:55 +02:00
}
2011-09-20 15:38:29 +02: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 17:25:05 +02:00
2012-01-22 20:32:58 +01:00
string EncodeBase32 ( const unsigned char * pch , size_t len )
{
2012-04-29 02:11:56 +02:00
static const char * pbase32 = " abcdefghijklmnopqrstuvwxyz234567 " ;
2012-01-22 20:32:58 +01: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 ( ) ) ;
}
2012-05-14 19:53:02 +02:00
static std : : string FormatException ( std : : exception * pex , const char * pszThread )
2011-05-14 17:25:05 +02:00
{
2011-10-07 17:02:21 +02:00
# ifdef WIN32
2012-04-22 16:22:45 +02:00
char pszModule [ MAX_PATH ] = " " ;
2011-05-14 17:25:05 +02:00
GetModuleFileNameA ( NULL , pszModule , sizeof ( pszModule ) ) ;
# else
const char * pszModule = " bitcoin " ;
# endif
if ( pex )
2012-05-14 19:53:02 +02:00
return strprintf (
2011-05-14 17:25:05 +02:00
" EXCEPTION: %s \n %s \n %s in %s \n " , typeid ( * pex ) . name ( ) , pex - > what ( ) , pszModule , pszThread ) ;
else
2012-05-14 19:53:02 +02:00
return strprintf (
2011-05-14 17:25:05 +02:00
" UNKNOWN EXCEPTION \n %s in %s \n " , pszModule , pszThread ) ;
}
void PrintExceptionContinue ( std : : exception * pex , const char * pszThread )
{
2012-05-14 19:53:02 +02:00
std : : string message = FormatException ( pex , pszThread ) ;
2014-01-16 16:15:27 +01:00
LogPrintf ( " \n \n ************************ \n %s \n " , message ) ;
2012-05-14 19:53:02 +02:00
fprintf ( stderr , " \n \n ************************ \n %s \n " , message . c_str ( ) ) ;
strMiscWarning = message ;
2011-05-14 17:25:05 +02:00
}
2012-04-09 23:50:56 +02:00
boost : : filesystem : : path GetDefaultDataDir ( )
2011-05-14 17:25:05 +02:00
{
2012-04-09 23:50:56 +02:00
namespace fs = boost : : filesystem ;
2012-04-22 16:22:45 +02:00
// Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
// Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
2011-05-14 17:25:05 +02:00
// Mac: ~/Library/Application Support/Bitcoin
// Unix: ~/.bitcoin
2011-10-07 17:02:21 +02:00
# ifdef WIN32
2011-05-14 17:25:05 +02:00
// Windows
2012-04-22 16:22:45 +02:00
return GetSpecialFolderPath ( CSIDL_APPDATA ) / " Bitcoin " ;
2011-05-14 17:25:05 +02:00
# else
2012-04-09 23:50:56 +02:00
fs : : path pathRet ;
2011-05-14 17:25:05 +02:00
char * pszHome = getenv ( " HOME " ) ;
if ( pszHome = = NULL | | strlen ( pszHome ) = = 0 )
2012-04-09 23:50:56 +02:00
pathRet = fs : : path ( " / " ) ;
else
pathRet = fs : : path ( pszHome ) ;
2011-10-07 17:02:21 +02:00
# ifdef MAC_OSX
2011-05-14 17:25:05 +02:00
// Mac
2012-04-12 17:14:46 +02:00
pathRet / = " Library/Application Support " ;
2014-03-24 02:14:43 +01:00
TryCreateDirectory ( pathRet ) ;
2012-04-09 23:50:56 +02:00
return pathRet / " Bitcoin " ;
2011-05-14 17:25:05 +02:00
# else
// Unix
2012-04-09 23:50:56 +02:00
return pathRet / " .bitcoin " ;
2011-05-14 17:25:05 +02:00
# endif
# endif
}
2014-06-19 15:10:04 +02:00
static boost : : filesystem : : path pathCached [ CBaseChainParams : : MAX_NETWORK_TYPES + 1 ] ;
2013-07-17 04:20:09 +02:00
static CCriticalSection csPathCached ;
2012-04-09 23:50:56 +02:00
const boost : : filesystem : : path & GetDataDir ( bool fNetSpecific )
2011-05-14 17:25:05 +02:00
{
2012-04-09 23:50:56 +02:00
namespace fs = boost : : filesystem ;
2013-07-17 04:20:09 +02:00
LOCK ( csPathCached ) ;
2014-06-19 15:10:04 +02:00
int nNet = CBaseChainParams : : MAX_NETWORK_TYPES ;
if ( fNetSpecific ) nNet = BaseParams ( ) . NetworkID ( ) ;
2012-04-09 23:50:56 +02:00
2013-07-17 04:20:09 +02:00
fs : : path & path = pathCached [ nNet ] ;
2012-04-09 23:50:56 +02:00
2013-09-19 14:47:21 +02:00
// This can be called during exceptions by LogPrintf(), so we cache the
2012-04-09 23:50:56 +02:00
// value so we don't have to do memory allocations after that.
2013-07-17 04:20:09 +02:00
if ( ! path . empty ( ) )
2012-04-09 23:50:56 +02:00
return path ;
if ( mapArgs . count ( " -datadir " ) ) {
2012-04-22 14:35:22 +02:00
path = fs : : system_complete ( mapArgs [ " -datadir " ] ) ;
if ( ! fs : : is_directory ( path ) ) {
path = " " ;
return path ;
}
2012-04-09 23:50:56 +02:00
} else {
path = GetDefaultDataDir ( ) ;
2011-05-14 17:25:05 +02:00
}
2013-05-07 15:16:25 +02:00
if ( fNetSpecific )
2014-06-19 15:10:04 +02:00
path / = BaseParams ( ) . DataDir ( ) ;
2011-05-14 17:25:05 +02:00
2013-06-08 10:03:23 +02:00
fs : : create_directories ( path ) ;
2012-04-09 23:50:56 +02:00
return path ;
2011-05-14 17:25:05 +02:00
}
2013-07-17 04:20:09 +02:00
void ClearDatadirCache ( )
{
2014-06-19 15:10:04 +02:00
std : : fill ( & pathCached [ 0 ] , & pathCached [ CBaseChainParams : : MAX_NETWORK_TYPES + 1 ] ,
2014-05-10 14:54:20 +02:00
boost : : filesystem : : path ( ) ) ;
2013-07-17 04:20:09 +02:00
}
2012-04-09 23:50:56 +02:00
boost : : filesystem : : path GetConfigFile ( )
2011-05-14 17:25:05 +02:00
{
2012-04-22 16:22:45 +02:00
boost : : filesystem : : path pathConfigFile ( GetArg ( " -conf " , " bitcoin.conf " ) ) ;
2014-05-10 14:54:20 +02:00
if ( ! pathConfigFile . is_complete ( ) )
pathConfigFile = GetDataDir ( false ) / pathConfigFile ;
2012-04-09 23:50:56 +02:00
return pathConfigFile ;
2011-05-14 17:25:05 +02:00
}
2012-04-22 14:35:22 +02:00
void ReadConfigFile ( map < string , string > & mapSettingsRet ,
2011-05-14 17:25:05 +02:00
map < string , vector < string > > & mapMultiSettingsRet )
{
2012-04-22 16:22:45 +02:00
boost : : filesystem : : ifstream streamConfig ( GetConfigFile ( ) ) ;
2011-05-14 17:25:05 +02:00
if ( ! streamConfig . good ( ) )
2012-04-22 14:35:22 +02:00
return ; // No bitcoin.conf file is OK
2011-05-14 17:25:05 +02:00
set < string > setOptions ;
setOptions . insert ( " * " ) ;
2012-04-09 23:50:56 +02:00
2012-04-22 16:22:45 +02:00
for ( boost : : program_options : : detail : : config_file_iterator it ( streamConfig , setOptions ) , end ; it ! = end ; + + it )
2011-05-14 17:25:05 +02: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 21:08:32 +01:00
{
2011-05-14 17:25:05 +02:00
mapSettingsRet [ strKey ] = it - > value [ 0 ] ;
2012-04-22 16:22:45 +02:00
// interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
2012-02-16 21:08:32 +01:00
InterpretNegativeSetting ( strKey , mapSettingsRet ) ;
}
2011-05-14 17:25:05 +02:00
mapMultiSettingsRet [ strKey ] . push_back ( it - > value [ 0 ] ) ;
}
2013-07-17 04:20:09 +02:00
// If datadir is changed in .conf file:
ClearDatadirCache ( ) ;
2011-05-14 17:25:05 +02:00
}
2012-04-09 23:50:56 +02:00
boost : : filesystem : : path GetPidFile ( )
2011-05-14 17:25:05 +02:00
{
2012-04-22 16:22:45 +02:00
boost : : filesystem : : path pathPidFile ( GetArg ( " -pid " , " bitcoind.pid " ) ) ;
2012-04-09 23:50:56 +02:00
if ( ! pathPidFile . is_complete ( ) ) pathPidFile = GetDataDir ( ) / pathPidFile ;
return pathPidFile ;
2011-05-14 17:25:05 +02:00
}
2013-07-24 09:30:09 +02:00
# ifndef WIN32
2012-04-09 23:50:56 +02:00
void CreatePidFile ( const boost : : filesystem : : path & path , pid_t pid )
2011-05-14 17:25:05 +02:00
{
2012-04-09 23:50:56 +02:00
FILE * file = fopen ( path . string ( ) . c_str ( ) , " w " ) ;
2011-06-24 20:03:16 +02:00
if ( file )
2011-05-14 17:25:05 +02:00
{
fprintf ( file , " %d \n " , pid ) ;
fclose ( file ) ;
}
}
2013-07-24 09:30:09 +02:00
# endif
2011-05-14 17:25:05 +02:00
2012-05-12 07:24:27 +02:00
bool RenameOver ( boost : : filesystem : : path src , boost : : filesystem : : path dest )
{
# ifdef WIN32
2012-05-17 18:30:09 +02:00
return MoveFileExA ( src . string ( ) . c_str ( ) , dest . string ( ) . c_str ( ) ,
2012-05-12 07:24:27 +02:00
MOVEFILE_REPLACE_EXISTING ) ;
# else
int rc = std : : rename ( src . string ( ) . c_str ( ) , dest . string ( ) . c_str ( ) ) ;
return ( rc = = 0 ) ;
# endif /* WIN32 */
}
2014-05-10 14:54:20 +02:00
// Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
// Specifically handles case where path p exists, but it wasn't possible for the user to
// write to the parent directory.
2014-03-24 02:14:43 +01:00
bool TryCreateDirectory ( const boost : : filesystem : : path & p )
{
try
{
return boost : : filesystem : : create_directory ( p ) ;
} catch ( boost : : filesystem : : filesystem_error ) {
if ( ! boost : : filesystem : : exists ( p ) | | ! boost : : filesystem : : is_directory ( p ) )
throw ;
}
// create_directory didn't create the directory, it had to have existed already
return false ;
}
2012-05-12 07:24:27 +02:00
void FileCommit ( FILE * fileout )
{
2013-12-20 15:55:01 +01:00
fflush ( fileout ) ; // harmless if redundantly called
2012-05-12 07:24:27 +02:00
# ifdef WIN32
2013-12-20 15:55:01 +01:00
HANDLE hFile = ( HANDLE ) _get_osfhandle ( _fileno ( fileout ) ) ;
FlushFileBuffers ( hFile ) ;
2012-05-12 07:24:27 +02:00
# else
2012-09-28 14:27:20 +02:00
# if defined(__linux__) || defined(__NetBSD__)
fdatasync ( fileno ( fileout ) ) ;
2013-09-16 05:14:06 +02:00
# elif defined(__APPLE__) && defined(F_FULLFSYNC)
fcntl ( fileno ( fileout ) , F_FULLFSYNC , 0 ) ;
2012-09-28 14:27:20 +02:00
# else
2012-05-12 07:24:27 +02:00
fsync ( fileno ( fileout ) ) ;
2012-09-28 14:27:20 +02:00
# endif
2012-05-12 07:24:27 +02:00
# endif
}
2013-01-30 04:17:33 +01: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-26 00:46:47 +02: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 02:21:28 +02: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-28 00:07:51 +01:00
# if defined(WIN32)
// Windows-specific version
HANDLE hFile = ( HANDLE ) _get_osfhandle ( _fileno ( file ) ) ;
LARGE_INTEGER nFileSize ;
2013-04-13 07:13:08 +02:00
int64_t nEndPos = ( int64_t ) offset + length ;
2013-01-28 00:07:51 +01:00
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 02:21:28 +02: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-28 00:07:51 +01:00
# endif
2012-08-16 02:21:28 +02:00
}
2011-05-14 17:25:05 +02:00
void ShrinkDebugFile ( )
{
// Scroll debug.log if it's getting too big
2012-04-09 23:50:56 +02:00
boost : : filesystem : : path pathLog = GetDataDir ( ) / " debug.log " ;
FILE * file = fopen ( pathLog . string ( ) . c_str ( ) , " r " ) ;
2014-01-30 10:55:55 +01:00
if ( file & & boost : : filesystem : : file_size ( pathLog ) > 10 * 1000000 )
2011-05-14 17:25:05 +02:00
{
// Restart the file with some of the end
2014-05-27 05:44:55 +02:00
std : : vector < char > vch ( 200000 , 0 ) ;
fseek ( file , - vch . size ( ) , SEEK_END ) ;
int nBytes = fread ( begin_ptr ( vch ) , 1 , vch . size ( ) , file ) ;
2011-05-14 17:25:05 +02:00
fclose ( file ) ;
2011-06-24 20:03:16 +02:00
2012-04-09 23:50:56 +02:00
file = fopen ( pathLog . string ( ) . c_str ( ) , " w " ) ;
2011-06-24 20:03:16 +02:00
if ( file )
2011-05-14 17:25:05 +02:00
{
2014-05-27 05:44:55 +02:00
fwrite ( begin_ptr ( vch ) , 1 , nBytes , file ) ;
2011-05-14 17:25:05 +02:00
fclose ( file ) ;
}
}
2013-04-28 17:37:50 +02:00
else if ( file ! = NULL )
fclose ( file ) ;
2011-05-14 17:25:05 +02:00
}
2013-04-13 07:13:08 +02:00
static int64_t nMockTime = 0 ; // For unit testing
2011-09-15 14:55:15 +02:00
2013-04-13 07:13:08 +02:00
int64_t GetTime ( )
2011-05-14 17:25:05 +02:00
{
2011-09-15 14:55:15 +02:00
if ( nMockTime ) return nMockTime ;
2011-05-14 17:25:05 +02:00
return time ( NULL ) ;
}
2013-04-13 07:13:08 +02:00
void SetMockTime ( int64_t nMockTimeIn )
2011-09-15 14:55:15 +02:00
{
nMockTime = nMockTimeIn ;
}
2011-05-14 17:25:05 +02: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 02:06:53 +02:00
return CLIENT_BUILD ;
2011-05-14 17:25:05 +02:00
}
2011-12-16 22:26:14 +01: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 17:25:05 +02:00
2012-04-15 22:10:54 +02:00
# ifdef WIN32
2012-04-22 16:22:45 +02: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 ) ;
}
2013-09-18 12:38:08 +02:00
LogPrintf ( " SHGetSpecialFolderPathA() failed, could not obtain requested path. \n " ) ;
2012-04-22 16:22:45 +02:00
return fs : : path ( " " ) ;
}
2012-04-15 22:10:54 +02:00
# endif
2012-05-24 05:10:59 +02:00
2012-11-29 00:33:12 +01: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 ) ) {
2013-09-18 12:38:08 +02:00
LogPrintf ( " GetTempPath(): failed to find temp path \n " ) ;
2012-11-29 00:33:12 +01:00
return boost : : filesystem : : path ( " " ) ;
}
return path ;
# endif
}
2012-05-24 05:10:59 +02:00
void runCommand ( std : : string strCommand )
{
int nErr = : : system ( strCommand . c_str ( ) ) ;
if ( nErr )
2014-01-16 16:15:27 +01:00
LogPrintf ( " runCommand error: system(%s) returned %d \n " , strCommand , nErr ) ;
2012-05-24 05:10:59 +02:00
}
2012-06-24 17:03:57 +02:00
void RenameThread ( const char * name )
{
2012-06-30 20:11:27 +02:00
# if defined(PR_SET_NAME)
2012-06-24 17:03:57 +02:00
// Only the first 15 characters are used (16 - NUL terminator)
: : prctl ( PR_SET_NAME , name , 0 , 0 , 0 ) ;
2012-06-30 17:23:04 +02: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 17:59:24 +02:00
2013-03-07 04:16:05 +01: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 17:59:24 +02:00
2012-06-24 17:03:57 +02:00
# else
// Prevent warnings for unused parameters...
( void ) name ;
# endif
}
2013-11-27 15:41:12 +01:00
2014-05-03 10:20:58 +02:00
bool ParseInt32 ( const std : : string & str , int32_t * out )
{
char * endp = NULL ;
errno = 0 ; // strtol will not set errno if valid
long int n = strtol ( str . c_str ( ) , & endp , 10 ) ;
if ( out ) * out = ( int ) n ;
// Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
// platforms the size of these types may be different.
return endp & & * endp = = 0 & & ! errno & &
n > = std : : numeric_limits < int32_t > : : min ( ) & &
n < = std : : numeric_limits < int32_t > : : max ( ) ;
}
2014-05-13 12:15:00 +02:00
void SetupEnvironment ( )
{
2014-05-10 14:54:20 +02:00
# ifndef WIN32
2014-05-13 12:15:00 +02:00
try
{
2014-05-10 14:54:20 +02:00
# if BOOST_FILESYSTEM_VERSION == 3
2014-05-13 12:15:00 +02:00
boost : : filesystem : : path : : codecvt ( ) ; // Raises runtime error if current locale is invalid
2014-05-10 14:54:20 +02:00
# else // boost filesystem v2
2014-05-13 12:15:00 +02:00
std : : locale ( ) ; // Raises runtime error if current locale is invalid
2014-05-10 14:54:20 +02:00
# endif
2014-05-13 12:15:00 +02:00
} catch ( std : : runtime_error & e )
{
setenv ( " LC_ALL " , " C " , 1 ) ; // Force C locale
}
2014-05-10 14:54:20 +02:00
# endif
2014-05-13 12:15:00 +02:00
}
2014-05-08 18:01:10 +02:00
std : : string DateTimeStrFormat ( const char * pszFormat , int64_t nTime )
{
// std::locale takes ownership of the pointer
std : : locale loc ( std : : locale : : classic ( ) , new boost : : posix_time : : time_facet ( pszFormat ) ) ;
std : : stringstream ss ;
ss . imbue ( loc ) ;
ss < < boost : : posix_time : : from_time_t ( nTime ) ;
return ss . str ( ) ;
}
2014-06-10 16:02:29 +02:00
std : : string FormatParagraph ( const std : : string in , size_t width , size_t indent )
{
std : : stringstream out ;
size_t col = 0 ;
size_t ptr = 0 ;
while ( ptr < in . size ( ) )
{
// Find beginning of next word
ptr = in . find_first_not_of ( ' ' , ptr ) ;
if ( ptr = = std : : string : : npos )
break ;
// Find end of next word
size_t endword = in . find_first_of ( ' ' , ptr ) ;
if ( endword = = std : : string : : npos )
endword = in . size ( ) ;
// Add newline and indentation if this wraps over the allowed width
if ( col > 0 )
{
if ( ( col + endword - ptr ) > width )
{
out < < ' \n ' ;
for ( size_t i = 0 ; i < indent ; + + i )
out < < ' ' ;
col = 0 ;
} else
out < < ' ' ;
}
// Append word
out < < in . substr ( ptr , endword - ptr ) ;
col + = endword - ptr ;
ptr = endword ;
}
return out . str ( ) ;
}