2011-05-14 17:25:05 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2013-10-20 21:25:06 +02:00
// Copyright (c) 2009-2013 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"
# include "chainparams.h"
# include "netbase.h"
# include "sync.h"
# include "ui_interface.h"
# include "uint256.h"
# include "version.h"
# include <stdarg.h>
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 {
namespace program_options {
std : : string to_internal ( const std : : string & ) ;
}
}
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 ;
bool fPrintToDebugger = false ;
bool fDaemon = false ;
bool fServer = false ;
string strMiscWarning ;
bool fNoListen = false ;
bool fLogTimestamps = false ;
2013-01-01 23:12:30 +01:00
volatile bool fReopenDebugLog = false ;
2013-11-27 15:41:12 +01:00
CClientUIInterface uiInterface ;
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
2011-05-14 17:25:05 +02:00
// Seed random number generator with screen scrape and other hardware sources
RAND_screen ( ) ;
# endif
// Seed random number generator with performance counter
RandAddSeed ( ) ;
}
~ CInit ( )
{
2012-07-21 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 ;
void RandAddSeed ( )
{
// Seed with CPU performance counter
2013-04-13 07:13:08 +02:00
int64_t nCounter = GetPerformanceCounter ( ) ;
2011-05-14 17:25:05 +02:00
RAND_add ( & nCounter , sizeof ( nCounter ) , 1.5 ) ;
memset ( & nCounter , 0 , sizeof ( nCounter ) ) ;
}
void RandAddSeedPerfmon ( )
{
RandAddSeed ( ) ;
// This can take up to 2 seconds, so only do it every 10 minutes
2013-04-13 07:13:08 +02:00
static int64_t nLastPerfmon ;
2011-05-14 17:25:05 +02:00
if ( GetTime ( ) < nLastPerfmon + 10 * 60 )
return ;
nLastPerfmon = GetTime ( ) ;
2011-10-07 17:02:21 +02:00
# ifdef WIN32
2011-05-14 17:25:05 +02:00
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
unsigned char pdata [ 250000 ] ;
memset ( pdata , 0 , sizeof ( pdata ) ) ;
unsigned long nSize = sizeof ( pdata ) ;
long ret = RegQueryValueExA ( HKEY_PERFORMANCE_DATA , " Global " , NULL , NULL , pdata , & nSize ) ;
RegCloseKey ( HKEY_PERFORMANCE_DATA ) ;
if ( ret = = ERROR_SUCCESS )
{
RAND_add ( pdata , nSize , nSize / 100.0 ) ;
2012-11-08 19:38:49 +01:00
OPENSSL_cleanse ( pdata , nSize ) ;
2013-09-18 12:38:08 +02:00
LogPrint ( " rand " , " RandAddSeed() %lu bytes \n " , nSize ) ;
2011-05-14 17:25:05 +02:00
}
# endif
}
2013-04-13 07:13:08 +02:00
uint64_t GetRand ( uint64_t nMax )
2011-05-14 17:25:05 +02:00
{
if ( nMax = = 0 )
return 0 ;
// The range of the random source must be a multiple of the modulus
// to give every possible output value an equal possibility
2013-04-13 07:13:08 +02:00
uint64_t nRange = ( std : : numeric_limits < uint64_t > : : max ( ) / nMax ) * nMax ;
uint64_t nRand = 0 ;
2011-05-14 17:25:05 +02:00
do
RAND_bytes ( ( unsigned char * ) & nRand , sizeof ( nRand ) ) ;
while ( nRand > = nRange ) ;
return ( nRand % nMax ) ;
}
int GetRandInt ( int nMax )
{
return GetRand ( nMax ) ;
}
2012-05-17 18:13:14 +02:00
uint256 GetRandHash ( )
{
uint256 hash ;
RAND_bytes ( ( unsigned char * ) & hash , sizeof ( hash ) ) ;
return hash ;
}
2011-05-14 17:25:05 +02:00
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 ( ) ;
}
2013-09-18 10:03:21 +02:00
int LogPrint ( const char * category , const char * pszFormat , . . . )
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 )
2013-09-18 10:03:21 +02:00
return 0 ;
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 )
return 0 ;
2013-09-18 10:03:21 +02:00
}
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
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
2013-01-01 23:12:30 +01:00
ret + = vprintf ( pszFormat , arg_ptr ) ;
2011-05-14 17:25:05 +02:00
va_end ( arg_ptr ) ;
}
2012-08-20 17:33:20 +02:00
else if ( ! fPrintToDebugger )
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 ( ) ) ;
if ( pszFormat [ strlen ( pszFormat ) - 1 ] = = ' \n ' )
fStartedNewLine = true ;
else
fStartedNewLine = false ;
2011-05-14 17:25:05 +02:00
2013-01-01 23:12:30 +01:00
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
ret + = vfprintf ( fileout , pszFormat , arg_ptr ) ;
va_end ( arg_ptr ) ;
2011-05-14 17:25:05 +02:00
}
2011-10-07 17:02:21 +02:00
# ifdef WIN32
2011-05-14 17:25:05 +02:00
if ( fPrintToDebugger )
{
2012-05-14 19:53:02 +02:00
// accumulate and output a line at a time
2013-12-10 02:34:28 +01:00
static std : : string buffer ;
boost : : mutex : : scoped_lock scoped_lock ( * mutexDebugLog ) ;
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 )
2011-05-14 17:25:05 +02:00
{
2013-12-10 02:34:28 +01:00
OutputDebugStringA ( buffer . substr ( line_start , line_end - line_start ) . c_str ( ) ) ;
line_start = line_end + 1 ;
ret + = line_end - line_start ;
2011-05-14 17:25:05 +02:00
}
2013-12-10 02:34:28 +01:00
buffer . erase ( 0 , line_start ) ;
2011-05-14 17:25:05 +02:00
}
# endif
return ret ;
}
2012-09-09 14:43:06 +02:00
string vstrprintf ( const char * format , va_list ap )
2011-05-14 17:25:05 +02:00
{
char buffer [ 50000 ] ;
char * p = buffer ;
int limit = sizeof ( buffer ) ;
int ret ;
2013-07-31 06:06:44 +02:00
while ( true )
2011-05-14 17:25:05 +02:00
{
va_list arg_ptr ;
2012-05-14 19:53:02 +02:00
va_copy ( arg_ptr , ap ) ;
2012-09-09 14:50:31 +02:00
ret = vsnprintf ( p , limit , format , arg_ptr ) ;
2011-05-14 17:25:05 +02:00
va_end ( arg_ptr ) ;
if ( ret > = 0 & & ret < limit )
break ;
if ( p ! = buffer )
2011-06-05 19:15:15 +02:00
delete [ ] p ;
2011-05-14 17:25:05 +02:00
limit * = 2 ;
p = new char [ limit ] ;
if ( p = = NULL )
throw std : : bad_alloc ( ) ;
}
string str ( p , p + ret ) ;
if ( p ! = buffer )
2011-06-05 19:15:15 +02:00
delete [ ] p ;
2011-05-14 17:25:05 +02:00
return str ;
}
2012-09-09 14:43:06 +02:00
string real_strprintf ( const char * format , int dummy , . . . )
2012-05-14 19:53:02 +02:00
{
va_list arg_ptr ;
va_start ( arg_ptr , dummy ) ;
string str = vstrprintf ( format , arg_ptr ) ;
va_end ( arg_ptr ) ;
return str ;
}
2012-09-09 14:43:06 +02:00
string real_strprintf ( const std : : string & format , int dummy , . . . )
{
va_list arg_ptr ;
va_start ( arg_ptr , dummy ) ;
string str = vstrprintf ( format . c_str ( ) , arg_ptr ) ;
va_end ( arg_ptr ) ;
return str ;
}
2012-03-18 23:14:03 +01:00
bool error ( const char * format , . . . )
2011-05-14 17:25:05 +02:00
{
va_list arg_ptr ;
va_start ( arg_ptr , format ) ;
2012-05-14 19:53:02 +02:00
std : : string str = vstrprintf ( format , arg_ptr ) ;
2011-05-14 17:25:05 +02:00
va_end ( arg_ptr ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " ERROR: %s \n " , str . c_str ( ) ) ;
2011-05-14 17:25:05 +02:00
return false ;
}
void ParseString ( const string & str , char c , vector < string > & v )
{
if ( str . empty ( ) )
return ;
string : : size_type i1 = 0 ;
string : : size_type i2 ;
2013-07-31 06:06:44 +02:00
while ( true )
2011-05-14 17:25:05 +02:00
{
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 ;
}
}
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 ;
string str = strprintf ( " % " PRId64 " .%08 " PRId64 , 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 , } ;
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 ( ) ;
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
if ( str [ 0 ] ! = ' - ' )
2011-05-14 17:25:05 +02:00
break ;
2012-02-06 19:55:11 +01:00
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 )
{
string name = entry . first ;
// interpret --foo as -foo (as long as both are not set)
if ( name . find ( " -- " ) = = 0 )
{
std : : string singleDash ( name . begin ( ) + 1 , name . end ( ) ) ;
if ( mapArgs . count ( singleDash ) = = 0 )
mapArgs [ singleDash ] = entry . second ;
name = singleDash ;
}
2012-02-16 21:08:32 +01:00
// interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
InterpretNegativeSetting ( name , 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 ( ) ) ;
}
2011-05-14 17:25:05 +02:00
bool WildcardMatch ( const char * psz , const char * mask )
{
2013-07-31 06:06:44 +02:00
while ( true )
2011-05-14 17:25:05 +02:00
{
switch ( * mask )
{
case ' \0 ' :
return ( * psz = = ' \0 ' ) ;
case ' * ' :
return WildcardMatch ( psz , mask + 1 ) | | ( * psz & & WildcardMatch ( psz + 1 , mask ) ) ;
case ' ? ' :
if ( * psz = = ' \0 ' )
return false ;
break ;
default :
if ( * psz ! = * mask )
return false ;
break ;
}
psz + + ;
mask + + ;
}
}
bool WildcardMatch ( const string & str , const string & mask )
{
return WildcardMatch ( str . c_str ( ) , mask . c_str ( ) ) ;
}
2012-05-14 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 LogException ( std : : exception * pex , const char * pszThread )
{
2012-05-14 19:53:02 +02:00
std : : string message = FormatException ( pex , pszThread ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " \n %s " , message . c_str ( ) ) ;
2011-05-14 17:25:05 +02:00
}
void PrintException ( std : : exception * pex , const char * pszThread )
{
2012-05-14 19:53:02 +02:00
std : : string message = FormatException ( pex , pszThread ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " \n \n ************************ \n %s \n " , message . c_str ( ) ) ;
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
throw ;
}
void PrintExceptionContinue ( std : : exception * pex , const char * pszThread )
{
2012-05-14 19:53:02 +02:00
std : : string message = FormatException ( pex , pszThread ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " \n \n ************************ \n %s \n " , message . c_str ( ) ) ;
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 " ;
2012-05-09 19:56:53 +02:00
fs : : create_directory ( 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
}
2013-07-17 04:20:09 +02:00
static boost : : filesystem : : path pathCached [ CChainParams : : MAX_NETWORK_TYPES + 1 ] ;
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 ) ;
int nNet = CChainParams : : MAX_NETWORK_TYPES ;
if ( fNetSpecific ) nNet = Params ( ) . 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 )
path / = Params ( ) . 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 ( )
{
std : : fill ( & pathCached [ 0 ] , & pathCached [ CChainParams : : MAX_NETWORK_TYPES + 1 ] ,
boost : : filesystem : : path ( ) ) ;
}
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 " ) ) ;
2012-04-09 23:50:56 +02:00
if ( ! pathConfigFile . is_complete ( ) ) pathConfigFile = GetDataDir ( false ) / pathConfigFile ;
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 */
}
void FileCommit ( FILE * fileout )
{
fflush ( fileout ) ; // harmless if redundantly called
# ifdef WIN32
_commit ( _fileno ( fileout ) ) ;
# 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
}
2011-05-14 17:25:05 +02:00
int GetFilesize ( FILE * file )
{
int nSavePos = ftell ( file ) ;
int nFilesize = - 1 ;
if ( fseek ( file , 0 , SEEK_END ) = = 0 )
nFilesize = ftell ( file ) ;
fseek ( file , nSavePos , SEEK_SET ) ;
return nFilesize ;
}
2013-01-30 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 " ) ;
2011-05-14 17:25:05 +02:00
if ( file & & GetFilesize ( file ) > 10 * 1000000 )
{
// Restart the file with some of the end
char pch [ 200000 ] ;
fseek ( file , - sizeof ( pch ) , SEEK_END ) ;
int nBytes = fread ( pch , 1 , sizeof ( pch ) , file ) ;
fclose ( file ) ;
2011-06-24 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
{
fwrite ( pch , 1 , nBytes , file ) ;
fclose ( file ) ;
}
}
2013-04-28 17:37:50 +02:00
else if ( file ! = NULL )
fclose ( file ) ;
2011-05-14 17:25:05 +02:00
}
//
// "Never go to sea with two chronometers; take one or three."
// Our three time sources are:
// - System clock
2012-06-29 11:26:45 +02:00
// - Median of other nodes clocks
2011-05-14 17:25:05 +02:00
// - The user (asking the user to fix the system clock if the first two disagree)
//
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 ;
}
2013-10-19 15:55:08 +02:00
static CCriticalSection cs_nTimeOffset ;
2013-04-13 07:13:08 +02:00
static int64_t nTimeOffset = 0 ;
2011-05-14 17:25:05 +02:00
2013-04-13 07:13:08 +02:00
int64_t GetTimeOffset ( )
2013-01-11 12:11:34 +01:00
{
2013-10-19 15:55:08 +02:00
LOCK ( cs_nTimeOffset ) ;
2013-01-11 12:11:34 +01:00
return nTimeOffset ;
}
2013-04-13 07:13:08 +02:00
int64_t GetAdjustedTime ( )
2011-05-14 17:25:05 +02:00
{
2013-01-11 12:11:34 +01:00
return GetTime ( ) + GetTimeOffset ( ) ;
2011-05-14 17:25:05 +02:00
}
2013-04-13 07:13:08 +02:00
void AddTimeData ( const CNetAddr & ip , int64_t nTime )
2011-05-14 17:25:05 +02:00
{
2013-04-13 07:13:08 +02:00
int64_t nOffsetSample = nTime - GetTime ( ) ;
2011-05-14 17:25:05 +02:00
2013-10-19 15:55:08 +02:00
LOCK ( cs_nTimeOffset ) ;
2011-05-14 17:25:05 +02:00
// Ignore duplicates
2012-01-03 23:33:31 +01:00
static set < CNetAddr > setKnown ;
2011-05-14 17:25:05 +02:00
if ( ! setKnown . insert ( ip ) . second )
return ;
// Add data
2013-04-13 07:13:08 +02:00
static CMedianFilter < int64_t > vTimeOffsets ( 200 , 0 ) ;
Retain only the most recent time samples
Remembering all time samples makes nTimeOffset slow to respond to
system clock corrections. For instance, I start my node with a system
clock that's 30 minutes slow and run it for a few days. During that
time, I accumulate 10,000 offset samples with a median of 1800
seconds. Now I correct my system clock. Without this change, my node
must collect another 10,000 samples before nTimeOffset is correct
again. With this change, I must only accumulate 100 samples to
correct the offset.
Storing unlimited time samples also allows an attacker with many IP
addresses (ex, a large botnet) to perform a memory exhaustion attack
against Bitcoin nodes. The attacker sends a version message from each
IP to his target, consuming more of the target's memory each time.
Time samples are small, so this attack might be impractical under the
old code, but it's impossible with the new code.
2011-11-30 04:15:59 +01:00
vTimeOffsets . input ( nOffsetSample ) ;
2013-04-13 07:13:08 +02:00
LogPrintf ( " Added time data, samples %d, offset %+ " PRId64 " (%+ " PRId64 " minutes) \n " , vTimeOffsets . size ( ) , nOffsetSample , nOffsetSample / 60 ) ;
2011-05-14 17:25:05 +02:00
if ( vTimeOffsets . size ( ) > = 5 & & vTimeOffsets . size ( ) % 2 = = 1 )
{
2013-04-13 07:13:08 +02:00
int64_t nMedian = vTimeOffsets . median ( ) ;
std : : vector < int64_t > vSorted = vTimeOffsets . sorted ( ) ;
2011-05-14 17:25:05 +02:00
// Only let other nodes change our time by so much
if ( abs64 ( nMedian ) < 70 * 60 )
{
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 ;
2013-04-13 07:13:08 +02:00
BOOST_FOREACH ( int64_t nOffset , vSorted )
2011-05-14 17:25:05 +02:00
if ( nOffset ! = 0 & & abs64 ( nOffset ) < 5 * 60 )
fMatch = true ;
if ( ! fMatch )
{
fDone = true ;
2012-07-27 08:36:43 +02:00
string strMessage = _ ( " Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly. " ) ;
2011-05-14 17:25:05 +02:00
strMiscWarning = strMessage ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " *** %s \n " , strMessage . c_str ( ) ) ;
2012-11-05 08:04:21 +01:00
uiInterface . ThreadSafeMessageBox ( strMessage , " " , CClientUIInterface : : MSG_WARNING ) ;
2011-05-14 17:25:05 +02:00
}
}
}
2011-11-30 03:06:10 +01:00
if ( fDebug ) {
2013-04-13 07:13:08 +02:00
BOOST_FOREACH ( int64_t n , vSorted )
LogPrintf ( " %+ " PRId64 " " , n ) ;
2013-09-18 12:38:08 +02:00
LogPrintf ( " | " ) ;
2011-11-30 03:06:10 +01:00
}
2013-04-13 07:13:08 +02:00
LogPrintf ( " nTimeOffset = %+ " PRId64 " (%+ " PRId64 " minutes) \n " , nTimeOffset , nTimeOffset / 60 ) ;
2011-05-14 17:25:05 +02:00
}
}
2013-02-16 00:27:57 +01:00
uint32_t insecure_rand_Rz = 11 ;
uint32_t insecure_rand_Rw = 11 ;
void seed_insecure_rand ( bool fDeterministic )
{
//The seed values have some unlikely fixed points which we avoid.
if ( fDeterministic )
{
insecure_rand_Rz = insecure_rand_Rw = 11 ;
} else {
uint32_t tmp ;
2013-04-04 11:30:55 +02:00
do {
RAND_bytes ( ( unsigned char * ) & tmp , 4 ) ;
} while ( tmp = = 0 | | tmp = = 0x9068ffffU ) ;
insecure_rand_Rz = tmp ;
do {
RAND_bytes ( ( unsigned char * ) & tmp , 4 ) ;
} while ( tmp = = 0 | | tmp = = 0x464fffffU ) ;
insecure_rand_Rw = tmp ;
2013-02-16 00:27:57 +01:00
}
}
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 )
2013-09-18 12:38:08 +02:00
LogPrintf ( " runCommand error: system(%s) returned %d \n " , strCommand . c_str ( ) , 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