2011-05-14 17:25:05 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2014-12-17 02:47:57 +01:00
// Copyright (c) 2009-2014 The Bitcoin Core developers
2014-11-17 04:04:01 +01:00
// Distributed under the MIT 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
2014-08-12 13:03:56 +02:00
# if defined(HAVE_CONFIG_H)
# include "config/bitcoin-config.h"
# endif
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"
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
# include "serialize.h"
2013-04-13 07:13:08 +02:00
# include "sync.h"
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
# include "utilstrencodings.h"
# include "utiltime.h"
2013-04-13 07:13:08 +02:00
# include <stdarg.h>
2015-03-27 13:19:49 +01:00
# if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
# include <pthread.h>
# include <pthread_np.h>
# endif
2013-01-28 00:07:51 +01:00
# ifndef WIN32
// for posix_fallocate
2014-08-12 12:05:03 +02:00
# ifdef __linux__
2013-04-13 07:13:08 +02:00
# 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
2014-08-12 12:05:03 +02:00
# endif // __linux__
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
2014-08-12 13:03:56 +02:00
# ifdef HAVE_SYS_PRCTL_H
# include <sys/prctl.h>
# endif
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>
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
# include <boost/thread.hpp>
2013-04-13 07:13:08 +02:00
# 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 ;
2015-04-16 16:20:01 +02:00
CTranslationInterface translationInterface ;
2011-05-14 17:25:05 +02:00
2014-11-17 04:04:01 +01: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 ;
2014-11-17 04:04:01 +01:00
/**
* LogPrintf ( ) has been broken a couple of times now
* by well - meaning people adding mutexes in the most straightforward way .
* It breaks because it may be called by global destructors during shutdown .
* Since the order of destruction of static / global objects is undefined ,
* 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 ;
2014-11-17 04:04:01 +01:00
/**
* We use boost : : call_once ( ) to make sure these are initialized
* in a thread - safe manner the first time called :
*/
2013-01-01 23:12:30 +01:00
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 & &
2015-05-20 06:14:35 +02:00
setCategories . count ( string ( " 1 " ) ) = = 0 & &
2013-12-10 04:19:18 +01:00
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 ) ;
2014-09-10 18:26:59 +02:00
fflush ( 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 ;
}
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 " ) ) ;
}
2015-02-04 09:11:49 +01:00
static const int screenWidth = 79 ;
static const int optIndent = 2 ;
static const int msgIndent = 7 ;
std : : string HelpMessageGroup ( const std : : string & message ) {
return std : : string ( message ) + std : : string ( " \n \n " ) ;
}
std : : string HelpMessageOpt ( const std : : string & option , const std : : string & message ) {
return std : : string ( optIndent , ' ' ) + std : : string ( option ) +
std : : string ( " \n " ) + std : : string ( msgIndent , ' ' ) +
FormatParagraph ( message , screenWidth - msgIndent , msgIndent ) +
std : : string ( " \n \n " ) ;
}
2014-12-07 13:29:06 +01:00
static std : : string FormatException ( const 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 ) ;
}
2014-12-07 13:29:06 +01:00
void PrintExceptionContinue ( const std : : exception * pex , const char * pszThread )
2011-05-14 17:25:05 +02:00
{
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
2015-06-12 04:55:12 +02:00
return pathRet / " .lbrycrd " ;
2011-05-14 17:25:05 +02:00
# endif
# endif
}
2014-10-11 20:56:27 +02:00
static boost : : filesystem : : path pathCached ;
static boost : : filesystem : : path pathCachedNetSpecific ;
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-10-11 20:56:27 +02:00
fs : : path & path = fNetSpecific ? pathCachedNetSpecific : pathCached ;
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-10-11 20:56:27 +02:00
pathCached = boost : : filesystem : : path ( ) ;
pathCachedNetSpecific = 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
{
2015-06-12 17:16:09 +02:00
boost : : filesystem : : path pathConfigFile ( GetArg ( " -conf " , " lbrycrd.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
}
2014-09-20 10:56:25 +02:00
# ifndef WIN32
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
}
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 ( ) ,
2014-09-06 21:59:59 +02:00
MOVEFILE_REPLACE_EXISTING ) ! = 0 ;
2012-05-12 07:24:27 +02:00
# else
int rc = std : : rename ( src . string ( ) . c_str ( ) , dest . string ( ) . c_str ( ) ) ;
return ( rc = = 0 ) ;
# endif /* WIN32 */
}
2014-11-17 04:04:01 +01: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 ) ;
2014-12-07 13:29:06 +01:00
} catch ( const boost : : filesystem : : filesystem_error & ) {
2014-03-24 02:14:43 +01:00
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
}
2014-11-17 04:04:01 +01: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 )
*/
2013-04-26 00:46:47 +02:00
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
}
2014-11-17 04:04:01 +01: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
*/
2012-08-16 02:21:28 +02:00
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 ) ;
2014-09-02 23:36:45 +02:00
fseek ( file , - ( ( long ) vch . size ( ) ) , SEEK_END ) ;
2014-05-27 05:44:55 +02:00
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
}
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
}
2015-05-31 15:36:44 +02:00
void runCommand ( const std : : string & strCommand )
2012-05-24 05:10:59 +02:00
{
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 ) ;
2015-04-29 15:04:34 +02:00
# elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
2012-06-30 17:23:04 +02:00
pthread_set_name_np ( pthread_self ( ) , name ) ;
2012-08-21 17:59:24 +02:00
2014-11-25 09:12:55 +01:00
# elif defined(MAC_OSX)
2013-03-07 04:16:05 +01:00
pthread_setname_np ( name ) ;
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-13 12:15:00 +02:00
void SetupEnvironment ( )
{
2015-03-11 13:34:20 +01:00
// On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
// may be invalid, in which case the "C" locale is used as fallback.
# if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
try {
2015-05-02 10:10:31 +02:00
std : : locale ( " " ) ; // Raises a runtime error if current locale is invalid
2014-12-07 13:29:06 +01:00
} catch ( const std : : runtime_error & ) {
2015-03-27 01:07:49 +01:00
setenv ( " LC_ALL " , " C " , 1 ) ;
2014-05-13 12:15:00 +02:00
}
2014-05-10 14:54:20 +02:00
# endif
2015-05-02 10:10:31 +02:00
// The path locale is lazy initialized and to avoid deinitialization errors
2015-03-11 13:34:20 +01:00
// in multithreading environments, it is set explicitly by the main thread.
2015-05-02 10:10:31 +02:00
// A dummy locale is used to extract the internal default locale, used by
// boost::filesystem::path, which is then used to explicitly imbue the path.
std : : locale loc = boost : : filesystem : : path : : imbue ( std : : locale : : classic ( ) ) ;
2015-03-27 01:07:49 +01:00
boost : : filesystem : : path : : imbue ( loc ) ;
2014-05-13 12:15:00 +02:00
}
2014-05-08 18:01:10 +02:00
2014-08-20 17:43:56 +02:00
void SetThreadPriority ( int nPriority )
{
# ifdef WIN32
SetThreadPriority ( GetCurrentThread ( ) , nPriority ) ;
# else // WIN32
# ifdef PRIO_THREAD
setpriority ( PRIO_THREAD , 0 , nPriority ) ;
# else // PRIO_THREAD
setpriority ( PRIO_PROCESS , 0 , nPriority ) ;
# endif // PRIO_THREAD
# endif // WIN32
}