LCOV - code coverage report
Current view: top level - src - util.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 211 256 82.4 %
Date: 2015-10-12 22:39:14 Functions: 37 42 88.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #if defined(HAVE_CONFIG_H)
       7             : #include "config/bitcoin-config.h"
       8             : #endif
       9             : 
      10             : #include "util.h"
      11             : 
      12             : #include "chainparamsbase.h"
      13             : #include "random.h"
      14             : #include "serialize.h"
      15             : #include "sync.h"
      16             : #include "utilstrencodings.h"
      17             : #include "utiltime.h"
      18             : 
      19             : #include <stdarg.h>
      20             : 
      21             : #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
      22             : #include <pthread.h>
      23             : #include <pthread_np.h>
      24             : #endif
      25             : 
      26             : #ifndef WIN32
      27             : // for posix_fallocate
      28             : #ifdef __linux__
      29             : 
      30             : #ifdef _POSIX_C_SOURCE
      31             : #undef _POSIX_C_SOURCE
      32             : #endif
      33             : 
      34             : #define _POSIX_C_SOURCE 200112L
      35             : 
      36             : #endif // __linux__
      37             : 
      38             : #include <algorithm>
      39             : #include <fcntl.h>
      40             : #include <sys/resource.h>
      41             : #include <sys/stat.h>
      42             : 
      43             : #else
      44             : 
      45             : #ifdef _MSC_VER
      46             : #pragma warning(disable:4786)
      47             : #pragma warning(disable:4804)
      48             : #pragma warning(disable:4805)
      49             : #pragma warning(disable:4717)
      50             : #endif
      51             : 
      52             : #ifdef _WIN32_WINNT
      53             : #undef _WIN32_WINNT
      54             : #endif
      55             : #define _WIN32_WINNT 0x0501
      56             : 
      57             : #ifdef _WIN32_IE
      58             : #undef _WIN32_IE
      59             : #endif
      60             : #define _WIN32_IE 0x0501
      61             : 
      62             : #define WIN32_LEAN_AND_MEAN 1
      63             : #ifndef NOMINMAX
      64             : #define NOMINMAX
      65             : #endif
      66             : 
      67             : #include <io.h> /* for _commit */
      68             : #include <shlobj.h>
      69             : #endif
      70             : 
      71             : #ifdef HAVE_SYS_PRCTL_H
      72             : #include <sys/prctl.h>
      73             : #endif
      74             : 
      75             : #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
      76             : #include <boost/algorithm/string/join.hpp>
      77             : #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
      78             : #include <boost/filesystem.hpp>
      79             : #include <boost/filesystem/fstream.hpp>
      80             : #include <boost/foreach.hpp>
      81             : #include <boost/program_options/detail/config_file.hpp>
      82             : #include <boost/program_options/parsers.hpp>
      83             : #include <boost/thread.hpp>
      84             : #include <openssl/crypto.h>
      85             : #include <openssl/rand.h>
      86             : #include <openssl/conf.h>
      87             : 
      88             : // Work around clang compilation problem in Boost 1.46:
      89             : // /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
      90             : // See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
      91             : //           http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
      92             : namespace boost {
      93             : 
      94             :     namespace program_options {
      95             :         std::string to_internal(const std::string&);
      96             :     }
      97             : 
      98             : } // namespace boost
      99             : 
     100             : using namespace std;
     101             : 
     102         203 : map<string, string> mapArgs;
     103         203 : map<string, vector<string> > mapMultiArgs;
     104             : bool fDebug = false;
     105             : bool fPrintToConsole = false;
     106             : bool fPrintToDebugLog = true;
     107             : bool fDaemon = false;
     108             : bool fServer = false;
     109         203 : string strMiscWarning;
     110             : bool fLogTimestamps = false;
     111             : bool fLogIPs = false;
     112             : volatile bool fReopenDebugLog = false;
     113         203 : CTranslationInterface translationInterface;
     114             : 
     115             : /** Init OpenSSL library multithreading support */
     116             : static CCriticalSection** ppmutexOpenSSL;
     117     3407602 : void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
     118             : {
     119     3407602 :     if (mode & CRYPTO_LOCK) {
     120     1703801 :         ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
     121             :     } else {
     122     1703801 :         LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
     123             :     }
     124     3407603 : }
     125             : 
     126             : // Init
     127             : class CInit
     128             : {
     129             : public:
     130         203 :     CInit()
     131             :     {
     132             :         // Init OpenSSL library multithreading support
     133         203 :         ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*));
     134        8526 :         for (int i = 0; i < CRYPTO_num_locks(); i++)
     135       16646 :             ppmutexOpenSSL[i] = new CCriticalSection();
     136         203 :         CRYPTO_set_locking_callback(locking_callback);
     137             : 
     138             :         // OpenSSL can optionally load a config file which lists optional loadable modules and engines.
     139             :         // We don't use them so we don't require the config. However some of our libs may call functions
     140             :         // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing
     141             :         // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
     142             :         // that the config appears to have been loaded and there are no modules/engines available.
     143         203 :         OPENSSL_no_config();
     144             : 
     145             : #ifdef WIN32
     146             :         // Seed OpenSSL PRNG with current contents of the screen
     147             :         RAND_screen();
     148             : #endif
     149             : 
     150             :         // Seed OpenSSL PRNG with performance counter
     151         203 :         RandAddSeed();
     152         203 :     }
     153         203 :     ~CInit()
     154             :     {
     155             :         // Securely erase the memory used by the PRNG
     156         203 :         RAND_cleanup();
     157             :         // Shutdown OpenSSL library multithreading support
     158         203 :         CRYPTO_set_locking_callback(NULL);
     159        8323 :         for (int i = 0; i < CRYPTO_num_locks(); i++)
     160       16646 :             delete ppmutexOpenSSL[i];
     161         203 :         OPENSSL_free(ppmutexOpenSSL);
     162         203 :     }
     163             : }
     164         203 : instance_of_cinit;
     165             : 
     166             : /**
     167             :  * LogPrintf() has been broken a couple of times now
     168             :  * by well-meaning people adding mutexes in the most straightforward way.
     169             :  * It breaks because it may be called by global destructors during shutdown.
     170             :  * Since the order of destruction of static/global objects is undefined,
     171             :  * defining a mutex as a global object doesn't work (the mutex gets
     172             :  * destroyed, and then some later destructor calls OutputDebugStringF,
     173             :  * maybe indirectly, and you get a core dump at shutdown trying to lock
     174             :  * the mutex).
     175             :  */
     176             : 
     177             : static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
     178             : 
     179             : /**
     180             :  * We use boost::call_once() to make sure mutexDebugLog and
     181             :  * vMsgsBeforeOpenLog are initialized in a thread-safe manner.
     182             :  *
     183             :  * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
     184             :  * are leaked on exit. This is ugly, but will be cleaned up by
     185             :  * the OS/libc. When the shutdown sequence is fully audited and
     186             :  * tested, explicit destruction of these objects can be implemented.
     187             :  */
     188             : static FILE* fileout = NULL;
     189             : static boost::mutex* mutexDebugLog = NULL;
     190             : static list<string> *vMsgsBeforeOpenLog;
     191             : 
     192             : static int FileWriteStr(const std::string &str, FILE *fp)
     193             : {
     194       46018 :     return fwrite(str.data(), 1, str.size(), fp);
     195             : }
     196             : 
     197          94 : static void DebugPrintInit()
     198             : {
     199          94 :     assert(mutexDebugLog == NULL);
     200          94 :     mutexDebugLog = new boost::mutex();
     201         188 :     vMsgsBeforeOpenLog = new list<string>;
     202          94 : }
     203             : 
     204          94 : void OpenDebugLog()
     205             : {
     206             :     boost::call_once(&DebugPrintInit, debugPrintInitFlag);
     207          94 :     boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
     208             : 
     209          94 :     assert(fileout == NULL);
     210          94 :     assert(vMsgsBeforeOpenLog);
     211         188 :     boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
     212         188 :     fileout = fopen(pathDebug.string().c_str(), "a");
     213          94 :     if (fileout) setbuf(fileout, NULL); // unbuffered
     214             : 
     215             :     // dump buffered messages from before we opened the log
     216         594 :     while (!vMsgsBeforeOpenLog->empty()) {
     217         406 :         FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
     218         203 :         vMsgsBeforeOpenLog->pop_front();
     219             :     }
     220             : 
     221         188 :     delete vMsgsBeforeOpenLog;
     222          94 :     vMsgsBeforeOpenLog = NULL;
     223          94 : }
     224             : 
     225      292817 : bool LogAcceptCategory(const char* category)
     226             : {
     227      292817 :     if (category != NULL)
     228             :     {
     229      271412 :         if (!fDebug)
     230             :             return false;
     231             : 
     232             :         // Give each thread quick access to -debug settings.
     233             :         // This helps prevent issues debugging global destructors,
     234             :         // where mapMultiArgs might be deleted before another
     235             :         // global destructor calls LogPrint()
     236       25126 :         static boost::thread_specific_ptr<set<string> > ptrCategory;
     237       25126 :         if (ptrCategory.get() == NULL)
     238             :         {
     239         327 :             const vector<string>& categories = mapMultiArgs["-debug"];
     240         327 :             ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
     241             :             // thread_specific_ptr automatically deletes the set when the thread ends.
     242             :         }
     243       25126 :         const set<string>& setCategories = *ptrCategory.get();
     244             : 
     245             :         // if not debugging everything and not debugging specific category, LogPrint does nothing.
     246       78656 :         if (setCategories.count(string("")) == 0 &&
     247       81934 :             setCategories.count(string("1")) == 0 &&
     248       30043 :             setCategories.count(string(category)) == 0)
     249             :             return false;
     250             :     }
     251             :     return true;
     252             : }
     253             : 
     254             : /**
     255             :  * fStartedNewLine is a state variable held by the calling context that will
     256             :  * suppress printing of the timestamp when multiple calls are made that don't
     257             :  * end in a newline. Initialize it to true, and hold it, in the calling context.
     258             :  */
     259       46888 : static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
     260             : {
     261             :     string strStamped;
     262             : 
     263       46888 :     if (!fLogTimestamps)
     264         870 :         return str;
     265             : 
     266       46018 :     if (*fStartedNewLine)
     267      174331 :         strStamped =  DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
     268             :     else
     269             :         strStamped = str;
     270             : 
     271       91942 :     if (!str.empty() && str[str.size()-1] == '\n')
     272       43583 :         *fStartedNewLine = true;
     273             :     else
     274        2435 :         *fStartedNewLine = false;
     275             : 
     276       46018 :     return strStamped;
     277             : }
     278             : 
     279       46888 : int LogPrintStr(const std::string &str)
     280             : {
     281       46888 :     int ret = 0; // Returns total number of characters written
     282             :     static bool fStartedNewLine = true;
     283             : 
     284       46888 :     string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
     285             : 
     286       46888 :     if (fPrintToConsole)
     287             :     {
     288             :         // print to console
     289           0 :         ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
     290           0 :         fflush(stdout);
     291             :     }
     292       46888 :     else if (fPrintToDebugLog)
     293             :     {
     294             :         boost::call_once(&DebugPrintInit, debugPrintInitFlag);
     295       46017 :         boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
     296             : 
     297             :         // buffer if we haven't opened the log yet
     298       46018 :         if (fileout == NULL) {
     299         203 :             assert(vMsgsBeforeOpenLog);
     300         203 :             ret = strTimestamped.length();
     301         203 :             vMsgsBeforeOpenLog->push_back(strTimestamped);
     302             :         }
     303             :         else
     304             :         {
     305             :             // reopen the log file, if requested
     306       45815 :             if (fReopenDebugLog) {
     307           0 :                 fReopenDebugLog = false;
     308           0 :                 boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
     309           0 :                 if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
     310           0 :                     setbuf(fileout, NULL); // unbuffered
     311             :             }
     312             : 
     313       91630 :             ret = FileWriteStr(strTimestamped, fileout);
     314             :         }
     315             :     }
     316       93776 :     return ret;
     317             : }
     318             : 
     319             : /** Interpret string as boolean, for argument parsing */
     320             : static bool InterpretBool(const std::string& strValue)
     321             : {
     322         668 :     if (strValue.empty())
     323             :         return true;
     324         446 :     return (atoi(strValue) != 0);
     325             : }
     326             : 
     327             : /** Turn -noX into -X=0 */
     328        1601 : static void InterpretNegativeSetting(std::string& strKey, std::string& strValue)
     329             : {
     330        4799 :     if (strKey.length()>3 && strKey[0]=='-' && strKey[1]=='n' && strKey[2]=='o')
     331             :     {
     332          36 :         strKey = "-" + strKey.substr(3);
     333          12 :         strValue = InterpretBool(strValue) ? "0" : "1";
     334             :     }
     335        1601 : }
     336             : 
     337         230 : void ParseParameters(int argc, const char* const argv[])
     338             : {
     339             :     mapArgs.clear();
     340             :     mapMultiArgs.clear();
     341             : 
     342         901 :     for (int i = 1; i < argc; i++)
     343             :     {
     344        1552 :         std::string str(argv[i]);
     345             :         std::string strValue;
     346         776 :         size_t is_index = str.find('=');
     347         776 :         if (is_index != std::string::npos)
     348             :         {
     349         900 :             strValue = str.substr(is_index+1);
     350         900 :             str = str.substr(0, is_index);
     351             :         }
     352             : #ifdef WIN32
     353             :         boost::to_lower(str);
     354             :         if (boost::algorithm::starts_with(str, "/"))
     355             :             str = "-" + str.substr(1);
     356             : #endif
     357             : 
     358         776 :         if (str[0] != '-')
     359             :             break;
     360             : 
     361             :         // Interpret --foo as -foo.
     362             :         // If both --foo and -foo are set, the last takes effect.
     363        1336 :         if (str.length() > 1 && str[1] == '-')
     364          12 :             str = str.substr(1);
     365         671 :         InterpretNegativeSetting(str, strValue);
     366             : 
     367         671 :         mapArgs[str] = strValue;
     368         671 :         mapMultiArgs[str].push_back(strValue);
     369             :     }
     370         230 : }
     371             : 
     372        5077 : std::string GetArg(const std::string& strArg, const std::string& strDefault)
     373             : {
     374        5077 :     if (mapArgs.count(strArg))
     375          23 :         return mapArgs[strArg];
     376        5054 :     return strDefault;
     377             : }
     378             : 
     379      116615 : int64_t GetArg(const std::string& strArg, int64_t nDefault)
     380             : {
     381      116608 :     if (mapArgs.count(strArg))
     382        1731 :         return atoi64(mapArgs[strArg]);
     383             :     return nDefault;
     384             : }
     385             : 
     386       10327 : bool GetBoolArg(const std::string& strArg, bool fDefault)
     387             : {
     388       10327 :     if (mapArgs.count(strArg))
     389        1312 :         return InterpretBool(mapArgs[strArg]);
     390             :     return fDefault;
     391             : }
     392             : 
     393         127 : bool SoftSetArg(const std::string& strArg, const std::string& strValue)
     394             : {
     395         127 :     if (mapArgs.count(strArg))
     396             :         return false;
     397         115 :     mapArgs[strArg] = strValue;
     398         115 :     return true;
     399             : }
     400             : 
     401         124 : bool SoftSetBoolArg(const std::string& strArg, bool fValue)
     402             : {
     403         124 :     if (fValue)
     404         294 :         return SoftSetArg(strArg, std::string("1"));
     405             :     else
     406          78 :         return SoftSetArg(strArg, std::string("0"));
     407             : }
     408             : 
     409             : static const int screenWidth = 79;
     410             : static const int optIndent = 2;
     411             : static const int msgIndent = 7;
     412             : 
     413           0 : std::string HelpMessageGroup(const std::string &message) {
     414           0 :     return std::string(message) + std::string("\n\n");
     415             : }
     416             : 
     417           0 : std::string HelpMessageOpt(const std::string &option, const std::string &message) {
     418           0 :     return std::string(optIndent,' ') + std::string(option) +
     419           0 :            std::string("\n") + std::string(msgIndent,' ') +
     420             :            FormatParagraph(message, screenWidth - msgIndent, msgIndent) +
     421           0 :            std::string("\n\n");
     422             : }
     423             : 
     424           0 : static std::string FormatException(const std::exception* pex, const char* pszThread)
     425             : {
     426             : #ifdef WIN32
     427             :     char pszModule[MAX_PATH] = "";
     428             :     GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
     429             : #else
     430           0 :     const char* pszModule = "bitcoin";
     431             : #endif
     432           0 :     if (pex)
     433             :         return strprintf(
     434           0 :             "EXCEPTION: %s       \n%s       \n%s in %s       \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
     435             :     else
     436             :         return strprintf(
     437           0 :             "UNKNOWN EXCEPTION       \n%s in %s       \n", pszModule, pszThread);
     438             : }
     439             : 
     440           0 : void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
     441             : {
     442           0 :     std::string message = FormatException(pex, pszThread);
     443           0 :     LogPrintf("\n\n************************\n%s\n", message);
     444           0 :     fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
     445             :     strMiscWarning = message;
     446           0 : }
     447             : 
     448          95 : boost::filesystem::path GetDefaultDataDir()
     449             : {
     450             :     namespace fs = boost::filesystem;
     451             :     // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
     452             :     // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
     453             :     // Mac: ~/Library/Application Support/Bitcoin
     454             :     // Unix: ~/.bitcoin
     455             : #ifdef WIN32
     456             :     // Windows
     457             :     return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
     458             : #else
     459             :     fs::path pathRet;
     460          95 :     char* pszHome = getenv("HOME");
     461          95 :     if (pszHome == NULL || strlen(pszHome) == 0)
     462           0 :         pathRet = fs::path("/");
     463             :     else
     464          95 :         pathRet = fs::path(pszHome);
     465             : #ifdef MAC_OSX
     466             :     // Mac
     467             :     pathRet /= "Library/Application Support";
     468             :     TryCreateDirectory(pathRet);
     469             :     return pathRet / "Bitcoin";
     470             : #else
     471             :     // Unix
     472         285 :     return pathRet / ".bitcoin";
     473             : #endif
     474             : #endif
     475             : }
     476             : 
     477         203 : static boost::filesystem::path pathCached;
     478         203 : static boost::filesystem::path pathCachedNetSpecific;
     479         203 : static CCriticalSection csPathCached;
     480             : 
     481       70679 : const boost::filesystem::path &GetDataDir(bool fNetSpecific)
     482             : {
     483             :     namespace fs = boost::filesystem;
     484             : 
     485       70679 :     LOCK(csPathCached);
     486             : 
     487       70679 :     fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
     488             : 
     489             :     // This can be called during exceptions by LogPrintf(), so we cache the
     490             :     // value so we don't have to do memory allocations after that.
     491       70679 :     if (!path.empty())
     492             :         return path;
     493             : 
     494        1600 :     if (mapArgs.count("-datadir")) {
     495        1995 :         path = fs::system_complete(mapArgs["-datadir"]);
     496         399 :         if (!fs::is_directory(path)) {
     497             :             path = "";
     498             :             return path;
     499             :         }
     500             :     } else {
     501           2 :         path = GetDefaultDataDir();
     502             :     }
     503         400 :     if (fNetSpecific)
     504         240 :         path /= BaseParams().DataDir();
     505             : 
     506             :     fs::create_directories(path);
     507             : 
     508             :     return path;
     509             : }
     510             : 
     511         211 : void ClearDatadirCache()
     512             : {
     513         211 :     pathCached = boost::filesystem::path();
     514         211 :     pathCachedNetSpecific = boost::filesystem::path();
     515         211 : }
     516             : 
     517         281 : boost::filesystem::path GetConfigFile()
     518             : {
     519        1686 :     boost::filesystem::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
     520         281 :     if (!pathConfigFile.is_complete())
     521         562 :         pathConfigFile = GetDataDir(false) / pathConfigFile;
     522             : 
     523         281 :     return pathConfigFile;
     524             : }
     525             : 
     526         187 : void ReadConfigFile(map<string, string>& mapSettingsRet,
     527             :                     map<string, vector<string> >& mapMultiSettingsRet)
     528             : {
     529         374 :     boost::filesystem::ifstream streamConfig(GetConfigFile());
     530         187 :     if (!streamConfig.good())
     531           1 :         return; // No bitcoin.conf file is OK
     532             : 
     533             :     set<string> setOptions;
     534         558 :     setOptions.insert("*");
     535             : 
     536        1302 :     for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
     537             :     {
     538             :         // Don't overwrite existing settings so command line settings override bitcoin.conf
     539        2790 :         string strKey = string("-") + it->string_key;
     540         930 :         string strValue = it->value[0];
     541         930 :         InterpretNegativeSetting(strKey, strValue);
     542         930 :         if (mapSettingsRet.count(strKey) == 0)
     543         930 :             mapSettingsRet[strKey] = strValue;
     544         930 :         mapMultiSettingsRet[strKey].push_back(strValue);
     545         186 :     }
     546             :     // If datadir is changed in .conf file:
     547         372 :     ClearDatadirCache();
     548             : }
     549             : 
     550             : #ifndef WIN32
     551         188 : boost::filesystem::path GetPidFile()
     552             : {
     553        1128 :     boost::filesystem::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
     554         376 :     if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
     555         188 :     return pathPidFile;
     556             : }
     557             : 
     558          94 : void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
     559             : {
     560         188 :     FILE* file = fopen(path.string().c_str(), "w");
     561          94 :     if (file)
     562             :     {
     563             :         fprintf(file, "%d\n", pid);
     564          94 :         fclose(file);
     565             :     }
     566          94 : }
     567             : #endif
     568             : 
     569         118 : bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
     570             : {
     571             : #ifdef WIN32
     572             :     return MoveFileExA(src.string().c_str(), dest.string().c_str(),
     573             :                        MOVEFILE_REPLACE_EXISTING) != 0;
     574             : #else
     575         472 :     int rc = std::rename(src.string().c_str(), dest.string().c_str());
     576         118 :     return (rc == 0);
     577             : #endif /* WIN32 */
     578             : }
     579             : 
     580             : /**
     581             :  * Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
     582             :  * Specifically handles case where path p exists, but it wasn't possible for the user to
     583             :  * write to the parent directory.
     584             :  */
     585         286 : bool TryCreateDirectory(const boost::filesystem::path& p)
     586             : {
     587             :     try
     588             :     {
     589             :         return boost::filesystem::create_directory(p);
     590           0 :     } catch (const boost::filesystem::filesystem_error&) {
     591           0 :         if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p))
     592           0 :             throw;
     593             :     }
     594             : 
     595             :     // create_directory didn't create the directory, it had to have existed already
     596           0 :     return false;
     597             : }
     598             : 
     599         428 : void FileCommit(FILE *fileout)
     600             : {
     601         428 :     fflush(fileout); // harmless if redundantly called
     602             : #ifdef WIN32
     603             :     HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout));
     604             :     FlushFileBuffers(hFile);
     605             : #else
     606             :     #if defined(__linux__) || defined(__NetBSD__)
     607         428 :     fdatasync(fileno(fileout));
     608             :     #elif defined(__APPLE__) && defined(F_FULLFSYNC)
     609             :     fcntl(fileno(fileout), F_FULLFSYNC, 0);
     610             :     #else
     611             :     fsync(fileno(fileout));
     612             :     #endif
     613             : #endif
     614         428 : }
     615             : 
     616           0 : bool TruncateFile(FILE *file, unsigned int length) {
     617             : #if defined(WIN32)
     618             :     return _chsize(_fileno(file), length) == 0;
     619             : #else
     620           0 :     return ftruncate(fileno(file), length) == 0;
     621             : #endif
     622             : }
     623             : 
     624             : /**
     625             :  * this function tries to raise the file descriptor limit to the requested number.
     626             :  * It returns the actual file descriptor limit (which may be more or less than nMinFD)
     627             :  */
     628          94 : int RaiseFileDescriptorLimit(int nMinFD) {
     629             : #if defined(WIN32)
     630             :     return 2048;
     631             : #else
     632             :     struct rlimit limitFD;
     633          94 :     if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
     634          94 :         if (limitFD.rlim_cur < (rlim_t)nMinFD) {
     635           0 :             limitFD.rlim_cur = nMinFD;
     636           0 :             if (limitFD.rlim_cur > limitFD.rlim_max)
     637           0 :                 limitFD.rlim_cur = limitFD.rlim_max;
     638           0 :             setrlimit(RLIMIT_NOFILE, &limitFD);
     639           0 :             getrlimit(RLIMIT_NOFILE, &limitFD);
     640             :         }
     641          94 :         return limitFD.rlim_cur;
     642             :     }
     643             :     return nMinFD; // getrlimit failed, assume it's fine
     644             : #endif
     645             : }
     646             : 
     647             : /**
     648             :  * this function tries to make a particular range of a file allocated (corresponding to disk space)
     649             :  * it is advisory, and the range specified in the arguments will never contain live data
     650             :  */
     651          98 : void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
     652             : #if defined(WIN32)
     653             :     // Windows-specific version
     654             :     HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
     655             :     LARGE_INTEGER nFileSize;
     656             :     int64_t nEndPos = (int64_t)offset + length;
     657             :     nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
     658             :     nFileSize.u.HighPart = nEndPos >> 32;
     659             :     SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
     660             :     SetEndOfFile(hFile);
     661             : #elif defined(MAC_OSX)
     662             :     // OSX specific version
     663             :     fstore_t fst;
     664             :     fst.fst_flags = F_ALLOCATECONTIG;
     665             :     fst.fst_posmode = F_PEOFPOSMODE;
     666             :     fst.fst_offset = 0;
     667             :     fst.fst_length = (off_t)offset + length;
     668             :     fst.fst_bytesalloc = 0;
     669             :     if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
     670             :         fst.fst_flags = F_ALLOCATEALL;
     671             :         fcntl(fileno(file), F_PREALLOCATE, &fst);
     672             :     }
     673             :     ftruncate(fileno(file), fst.fst_length);
     674             : #elif defined(__linux__)
     675             :     // Version using posix_fallocate
     676          98 :     off_t nEndPos = (off_t)offset + length;
     677          98 :     posix_fallocate(fileno(file), 0, nEndPos);
     678             : #else
     679             :     // Fallback version
     680             :     // TODO: just write one byte per block
     681             :     static const char buf[65536] = {};
     682             :     fseek(file, offset, SEEK_SET);
     683             :     while (length > 0) {
     684             :         unsigned int now = 65536;
     685             :         if (length < now)
     686             :             now = length;
     687             :         fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
     688             :         length -= now;
     689             :     }
     690             : #endif
     691          98 : }
     692             : 
     693          79 : void ShrinkDebugFile()
     694             : {
     695             :     // Scroll debug.log if it's getting too big
     696         158 :     boost::filesystem::path pathLog = GetDataDir() / "debug.log";
     697         158 :     FILE* file = fopen(pathLog.string().c_str(), "r");
     698         106 :     if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000)
     699             :     {
     700             :         // Restart the file with some of the end
     701           0 :         std::vector <char> vch(200000,0);
     702           0 :         fseek(file, -((long)vch.size()), SEEK_END);
     703           0 :         int nBytes = fread(begin_ptr(vch), 1, vch.size(), file);
     704           0 :         fclose(file);
     705             : 
     706           0 :         file = fopen(pathLog.string().c_str(), "w");
     707           0 :         if (file)
     708             :         {
     709           0 :             fwrite(begin_ptr(vch), 1, nBytes, file);
     710           0 :             fclose(file);
     711             :         }
     712             :     }
     713          79 :     else if (file != NULL)
     714          27 :         fclose(file);
     715          79 : }
     716             : 
     717             : #ifdef WIN32
     718             : boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
     719             : {
     720             :     namespace fs = boost::filesystem;
     721             : 
     722             :     char pszPath[MAX_PATH] = "";
     723             : 
     724             :     if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
     725             :     {
     726             :         return fs::path(pszPath);
     727             :     }
     728             : 
     729             :     LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
     730             :     return fs::path("");
     731             : }
     732             : #endif
     733             : 
     734          26 : boost::filesystem::path GetTempPath() {
     735             : #if BOOST_FILESYSTEM_VERSION == 3
     736          26 :     return boost::filesystem::temp_directory_path();
     737             : #else
     738             :     // TODO: remove when we don't support filesystem v2 anymore
     739             :     boost::filesystem::path path;
     740             : #ifdef WIN32
     741             :     char pszPath[MAX_PATH] = "";
     742             : 
     743             :     if (GetTempPathA(MAX_PATH, pszPath))
     744             :         path = boost::filesystem::path(pszPath);
     745             : #else
     746             :     path = boost::filesystem::path("/tmp");
     747             : #endif
     748             :     if (path.empty() || !boost::filesystem::is_directory(path)) {
     749             :         LogPrintf("GetTempPath(): failed to find temp path\n");
     750             :         return boost::filesystem::path("");
     751             :     }
     752             :     return path;
     753             : #endif
     754             : }
     755             : 
     756           6 : void runCommand(const std::string& strCommand)
     757             : {
     758           6 :     int nErr = ::system(strCommand.c_str());
     759           6 :     if (nErr)
     760           0 :         LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
     761           6 : }
     762             : 
     763        1643 : void RenameThread(const char* name)
     764             : {
     765             : #if defined(PR_SET_NAME)
     766             :     // Only the first 15 characters are used (16 - NUL terminator)
     767        1643 :     ::prctl(PR_SET_NAME, name, 0, 0, 0);
     768             : #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
     769             :     pthread_set_name_np(pthread_self(), name);
     770             : 
     771             : #elif defined(MAC_OSX)
     772             :     pthread_setname_np(name);
     773             : #else
     774             :     // Prevent warnings for unused parameters...
     775             :     (void)name;
     776             : #endif
     777        1643 : }
     778             : 
     779         377 : void SetupEnvironment()
     780             : {
     781             :     // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
     782             :     // may be invalid, in which case the "C" locale is used as fallback.
     783             : #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
     784             :     try {
     785         377 :         std::locale(""); // Raises a runtime error if current locale is invalid
     786           0 :     } catch (const std::runtime_error&) {
     787           0 :         setenv("LC_ALL", "C", 1);
     788             :     }
     789             : #endif
     790             :     // The path locale is lazy initialized and to avoid deinitialization errors
     791             :     // in multithreading environments, it is set explicitly by the main thread.
     792             :     // A dummy locale is used to extract the internal default locale, used by
     793             :     // boost::filesystem::path, which is then used to explicitly imbue the path.
     794         377 :     std::locale loc = boost::filesystem::path::imbue(std::locale::classic());
     795         377 :     boost::filesystem::path::imbue(loc);
     796         377 : }
     797             : 
     798         187 : bool SetupNetworking()
     799             : {
     800             : #ifdef WIN32
     801             :     // Initialize Windows Sockets
     802             :     WSADATA wsadata;
     803             :     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
     804             :     if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
     805             :         return false;
     806             : #endif
     807         187 :     return true;
     808             : }
     809             : 
     810          94 : void SetThreadPriority(int nPriority)
     811             : {
     812             : #ifdef WIN32
     813             :     SetThreadPriority(GetCurrentThread(), nPriority);
     814             : #else // WIN32
     815             : #ifdef PRIO_THREAD
     816             :     setpriority(PRIO_THREAD, 0, nPriority);
     817             : #else // PRIO_THREAD
     818          94 :     setpriority(PRIO_PROCESS, 0, nPriority);
     819             : #endif // PRIO_THREAD
     820             : #endif // WIN32
     821          94 : }
     822             : 
     823          94 : int GetNumCores()
     824             : {
     825             : #if BOOST_VERSION >= 105600
     826          94 :     return boost::thread::physical_concurrency();
     827             : #else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores
     828             :     return boost::thread::hardware_concurrency();
     829             : #endif
     830         609 : }
     831             : 

Generated by: LCOV version 1.11