]> Git Repo - VerusCoin.git/blame - src/util.cpp
Streamline dice queue
[VerusCoin.git] / src / util.cpp
CommitLineData
2097c09a 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
c63a73d1 3// Distributed under the MIT software license, see the accompanying
3a25a2b9 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
36949554 5
4c61ba40
WL
6#if defined(HAVE_CONFIG_H)
7#include "config/bitcoin-config.h"
8#endif
9
51ed9ec9
BD
10#include "util.h"
11
84ce18ca 12#include "chainparamsbase.h"
6354935c 13#include "random.h"
ad49c256 14#include "serialize.h"
51ed9ec9 15#include "sync.h"
ad49c256
WL
16#include "utilstrencodings.h"
17#include "utiltime.h"
7ce53ed0 18#include "komodo_defs.h"
51ed9ec9 19
51ed9ec9 20#include <stdarg.h>
51ed9ec9 21
5207f33f
PK
22#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
23#include <pthread.h>
24#include <pthread_np.h>
25#endif
26
9cb1ec9c 27#ifndef _WIN32
288fdc09 28// for posix_fallocate
76c49c41 29#ifdef __linux__
51ed9ec9
BD
30
31#ifdef _POSIX_C_SOURCE
32#undef _POSIX_C_SOURCE
33#endif
34
288fdc09 35#define _POSIX_C_SOURCE 200112L
51ed9ec9 36
76c49c41 37#endif // __linux__
51ed9ec9 38
b94595bb 39#include <algorithm>
288fdc09 40#include <fcntl.h>
ba29a559 41#include <sys/resource.h>
51ed9ec9 42#include <sys/stat.h>
1f29d399 43
51ed9ec9 44#else
ed6d0b5f 45
ed6d0b5f
PW
46#ifdef _MSC_VER
47#pragma warning(disable:4786)
48#pragma warning(disable:4804)
49#pragma warning(disable:4805)
50#pragma warning(disable:4717)
51#endif
51ed9ec9 52
ed6d0b5f
PW
53#ifdef _WIN32_WINNT
54#undef _WIN32_WINNT
55#endif
56#define _WIN32_WINNT 0x0501
51ed9ec9 57
ed6d0b5f
PW
58#ifdef _WIN32_IE
59#undef _WIN32_IE
60#endif
234db30d 61#define _WIN32_IE 0x0501
51ed9ec9 62
ed6d0b5f
PW
63#define WIN32_LEAN_AND_MEAN 1
64#ifndef NOMINMAX
65#define NOMINMAX
66#endif
51ed9ec9 67
5f986195 68#include <io.h> /* for _commit */
51ed9ec9 69#include <shlobj.h>
ed6d0b5f 70#endif
2097c09a 71
4c61ba40
WL
72#ifdef HAVE_SYS_PRCTL_H
73#include <sys/prctl.h>
74#endif
75
51ed9ec9
BD
76#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
77#include <boost/algorithm/string/join.hpp>
78#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
79#include <boost/filesystem.hpp>
80#include <boost/filesystem/fstream.hpp>
81#include <boost/foreach.hpp>
82#include <boost/program_options/detail/config_file.hpp>
83#include <boost/program_options/parsers.hpp>
ad49c256 84#include <boost/thread.hpp>
51ed9ec9 85#include <openssl/crypto.h>
25314386 86#include <openssl/conf.h>
51ed9ec9
BD
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
92namespace boost {
e10dcf27 93
51ed9ec9
BD
94 namespace program_options {
95 std::string to_internal(const std::string&);
96 }
51ed9ec9 97
e10dcf27 98} // namespace boost
51ed9ec9 99
2097c09a
WL
100using namespace std;
101
102map<string, string> mapArgs;
103map<string, vector<string> > mapMultiArgs;
104bool fDebug = false;
105bool fPrintToConsole = false;
9e9056cd 106bool fPrintToDebugLog = true;
2097c09a
WL
107bool fDaemon = false;
108bool fServer = false;
2097c09a 109string strMiscWarning;
7a4e0e09
CD
110bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
111bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
112bool fLogIPs = DEFAULT_LOGIPS;
bf673640 113std::atomic<bool> fReopenDebugLog(false);
b74dcb3b 114CTranslationInterface translationInterface;
2097c09a 115
c63a73d1 116/** Init OpenSSL library multithreading support */
7f3ccb59 117static CCriticalSection** ppmutexOpenSSL;
60457d3c 118void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
2097c09a 119{
7f3ccb59
PW
120 if (mode & CRYPTO_LOCK) {
121 ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
122 } else {
123 LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
124 }
2097c09a
WL
125}
126
127// Init
128class CInit
129{
130public:
131 CInit()
132 {
a7f82808 133 // Init OpenSSL library multithreading support
7f3ccb59 134 ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*));
2097c09a 135 for (int i = 0; i < CRYPTO_num_locks(); i++)
7f3ccb59 136 ppmutexOpenSSL[i] = new CCriticalSection();
2097c09a
WL
137 CRYPTO_set_locking_callback(locking_callback);
138
25314386
CF
139 // OpenSSL can optionally load a config file which lists optional loadable modules and engines.
140 // We don't use them so we don't require the config. However some of our libs may call functions
141 // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing
142 // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
143 // that the config appears to have been loaded and there are no modules/engines available.
144 OPENSSL_no_config();
2097c09a
WL
145 }
146 ~CInit()
147 {
a7f82808 148 // Shutdown OpenSSL library multithreading support
2097c09a
WL
149 CRYPTO_set_locking_callback(NULL);
150 for (int i = 0; i < CRYPTO_num_locks(); i++)
151 delete ppmutexOpenSSL[i];
152 OPENSSL_free(ppmutexOpenSSL);
153 }
154}
155instance_of_cinit;
156
c63a73d1
MF
157/**
158 * LogPrintf() has been broken a couple of times now
159 * by well-meaning people adding mutexes in the most straightforward way.
160 * It breaks because it may be called by global destructors during shutdown.
161 * Since the order of destruction of static/global objects is undefined,
162 * defining a mutex as a global object doesn't work (the mutex gets
163 * destroyed, and then some later destructor calls OutputDebugStringF,
164 * maybe indirectly, and you get a core dump at shutdown trying to lock
165 * the mutex).
166 */
2097c09a 167
ee337423 168static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
8550bcfe 169
c63a73d1 170/**
8550bcfe
AW
171 * We use boost::call_once() to make sure mutexDebugLog and
172 * vMsgsBeforeOpenLog are initialized in a thread-safe manner.
173 *
174 * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
175 * are leaked on exit. This is ugly, but will be cleaned up by
176 * the OS/libc. When the shutdown sequence is fully audited and
177 * tested, explicit destruction of these objects can be implemented.
c63a73d1 178 */
ee337423
GA
179static FILE* fileout = NULL;
180static boost::mutex* mutexDebugLog = NULL;
8550bcfe
AW
181static list<string> *vMsgsBeforeOpenLog;
182
183static int FileWriteStr(const std::string &str, FILE *fp)
184{
185 return fwrite(str.data(), 1, str.size(), fp);
186}
ee337423
GA
187
188static void DebugPrintInit()
2097c09a 189{
ee337423 190 assert(mutexDebugLog == NULL);
8550bcfe
AW
191 mutexDebugLog = new boost::mutex();
192 vMsgsBeforeOpenLog = new list<string>;
193}
ee337423 194
8550bcfe
AW
195void OpenDebugLog()
196{
197 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
198 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
199
200 assert(fileout == NULL);
201 assert(vMsgsBeforeOpenLog);
ee337423
GA
202 boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
203 fileout = fopen(pathDebug.string().c_str(), "a");
204 if (fileout) setbuf(fileout, NULL); // unbuffered
205
8550bcfe
AW
206 // dump buffered messages from before we opened the log
207 while (!vMsgsBeforeOpenLog->empty()) {
208 FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
209 vMsgsBeforeOpenLog->pop_front();
210 }
211
212 delete vMsgsBeforeOpenLog;
213 vMsgsBeforeOpenLog = NULL;
ee337423
GA
214}
215
b77dfdc9 216bool LogAcceptCategory(const char* category)
ee337423 217{
e51321fb
GA
218 if (category != NULL)
219 {
3b570559 220 if (!fDebug)
b77dfdc9 221 return false;
3b570559 222
0b238b27
GA
223 // Give each thread quick access to -debug settings.
224 // This helps prevent issues debugging global destructors,
225 // where mapMultiArgs might be deleted before another
226 // global destructor calls LogPrint()
227 static boost::thread_specific_ptr<set<string> > ptrCategory;
228 if (ptrCategory.get() == NULL)
3b570559 229 {
0b238b27
GA
230 const vector<string>& categories = mapMultiArgs["-debug"];
231 ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
232 // thread_specific_ptr automatically deletes the set when the thread ends.
3b570559 233 }
0b238b27
GA
234 const set<string>& setCategories = *ptrCategory.get();
235
236 // if not debugging everything and not debugging specific category, LogPrint does nothing.
237 if (setCategories.count(string("")) == 0 &&
1d2db276 238 setCategories.count(string("1")) == 0 &&
0b238b27 239 setCategories.count(string(category)) == 0)
b77dfdc9 240 return false;
e51321fb 241 }
b77dfdc9
WL
242 return true;
243}
e51321fb 244
8550bcfe
AW
245/**
246 * fStartedNewLine is a state variable held by the calling context that will
247 * suppress printing of the timestamp when multiple calls are made that don't
248 * end in a newline. Initialize it to true, and hold it, in the calling context.
249 */
250static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
251{
252 string strStamped;
253
254 if (!fLogTimestamps)
255 return str;
256
257 if (*fStartedNewLine)
258 strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
259 else
260 strStamped = str;
261
262 if (!str.empty() && str[str.size()-1] == '\n')
263 *fStartedNewLine = true;
264 else
265 *fStartedNewLine = false;
266
267 return strStamped;
268}
269
b77dfdc9
WL
270int LogPrintStr(const std::string &str)
271{
ee337423 272 int ret = 0; // Returns total number of characters written
8550bcfe 273 static bool fStartedNewLine = true;
2097c09a
WL
274 if (fPrintToConsole)
275 {
276 // print to console
b77dfdc9 277 ret = fwrite(str.data(), 1, str.size(), stdout);
e982b574 278 fflush(stdout);
2097c09a 279 }
8550bcfe 280 else if (fPrintToDebugLog)
2097c09a 281 {
ee337423 282 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
ee337423
GA
283 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
284
8550bcfe 285 string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
2097c09a 286
8550bcfe
AW
287 // buffer if we haven't opened the log yet
288 if (fileout == NULL) {
289 assert(vMsgsBeforeOpenLog);
290 ret = strTimestamped.length();
291 vMsgsBeforeOpenLog->push_back(strTimestamped);
292 }
ee337423 293 else
8550bcfe
AW
294 {
295 // reopen the log file, if requested
296 if (fReopenDebugLog) {
297 fReopenDebugLog = false;
298 boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
299 if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
300 setbuf(fileout, NULL); // unbuffered
301 }
302
303 ret = FileWriteStr(strTimestamped, fileout);
304 }
2097c09a 305 }
2097c09a
WL
306 return ret;
307}
308
d64e124c
CM
309static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
310{
311 // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
312 if (name.find("-no") == 0)
313 {
314 std::string positive("-");
315 positive.append(name.begin()+3, name.end());
316 if (mapSettingsRet.count(positive) == 0)
317 {
3260b4c0 318 bool value = !GetBoolArg(name, false);
d64e124c
CM
319 mapSettingsRet[positive] = (value ? "1" : "0");
320 }
321 }
322}
323
3e468840 324void ParseParameters(int argc, const char* const argv[])
2097c09a
WL
325{
326 mapArgs.clear();
327 mapMultiArgs.clear();
71aaff39 328
2097c09a
WL
329 for (int i = 1; i < argc; i++)
330 {
6032e4f4
WL
331 std::string str(argv[i]);
332 std::string strValue;
333 size_t is_index = str.find('=');
334 if (is_index != std::string::npos)
2097c09a 335 {
6032e4f4
WL
336 strValue = str.substr(is_index+1);
337 str = str.substr(0, is_index);
2097c09a 338 }
9cb1ec9c 339#ifdef _WIN32
6032e4f4
WL
340 boost::to_lower(str);
341 if (boost::algorithm::starts_with(str, "/"))
342 str = "-" + str.substr(1);
343#endif
71aaff39 344
6032e4f4 345 if (str[0] != '-')
2097c09a 346 break;
3ad9f8a7 347
71aaff39
KZ
348 // Interpret --foo as -foo.
349 // If both --foo and -foo are set, the last takes effect.
350 if (str.length() > 1 && str[1] == '-')
351 str = str.substr(1);
352
6032e4f4
WL
353 mapArgs[str] = strValue;
354 mapMultiArgs[str].push_back(strValue);
2097c09a 355 }
3ad9f8a7
GA
356
357 // New 0.6 features:
358 BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs)
359 {
d64e124c 360 // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
71aaff39 361 InterpretNegativeSetting(entry.first, mapArgs);
3ad9f8a7 362 }
2097c09a
WL
363}
364
3ae07355
GA
365std::string GetArg(const std::string& strArg, const std::string& strDefault)
366{
367 if (mapArgs.count(strArg))
368 return mapArgs[strArg];
369 return strDefault;
370}
371
51ed9ec9 372int64_t GetArg(const std::string& strArg, int64_t nDefault)
3ae07355
GA
373{
374 if (mapArgs.count(strArg))
375 return atoi64(mapArgs[strArg]);
376 return nDefault;
377}
378
379bool GetBoolArg(const std::string& strArg, bool fDefault)
380{
381 if (mapArgs.count(strArg))
382 {
383 if (mapArgs[strArg].empty())
384 return true;
385 return (atoi(mapArgs[strArg]) != 0);
386 }
387 return fDefault;
388}
389
0fcf91ea
GA
390bool SoftSetArg(const std::string& strArg, const std::string& strValue)
391{
392 if (mapArgs.count(strArg))
393 return false;
394 mapArgs[strArg] = strValue;
395 return true;
396}
397
7bf8b7c2 398bool SoftSetBoolArg(const std::string& strArg, bool fValue)
0fcf91ea
GA
399{
400 if (fValue)
401 return SoftSetArg(strArg, std::string("1"));
402 else
403 return SoftSetArg(strArg, std::string("0"));
404}
405
1fdb9fa3
LV
406static const int screenWidth = 79;
407static const int optIndent = 2;
408static const int msgIndent = 7;
409
410std::string HelpMessageGroup(const std::string &message) {
411 return std::string(message) + std::string("\n\n");
412}
413
414std::string HelpMessageOpt(const std::string &option, const std::string &message) {
415 return std::string(optIndent,' ') + std::string(option) +
416 std::string("\n") + std::string(msgIndent,' ') +
417 FormatParagraph(message, screenWidth - msgIndent, msgIndent) +
418 std::string("\n\n");
419}
420
27df4123 421static std::string FormatException(const std::exception* pex, const char* pszThread)
2097c09a 422{
9cb1ec9c 423#ifdef _WIN32
3e468840 424 char pszModule[MAX_PATH] = "";
2097c09a
WL
425 GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
426#else
5166804f 427 const char* pszModule = "Komodo";
2097c09a
WL
428#endif
429 if (pex)
29b79e4c 430 return strprintf(
2097c09a
WL
431 "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
432 else
29b79e4c 433 return strprintf(
2097c09a
WL
434 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
435}
436
27df4123 437void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
2097c09a 438{
29b79e4c 439 std::string message = FormatException(pex, pszThread);
7d9d134b 440 LogPrintf("\n\n************************\n%s\n", message);
29b79e4c
WL
441 fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
442 strMiscWarning = message;
2097c09a
WL
443}
444
7c130297 445extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
ec3bf0d8 446//int64_t MAX_MONEY = 200000000 * 100000000LL;
f71f89bb 447
ee12c3d6 448boost::filesystem::path GetDefaultDataDir()
2097c09a 449{
ee12c3d6 450 namespace fs = boost::filesystem;
7c130297 451 char symbol[KOMODO_ASSETCHAIN_MAXLEN];
dadaab0a 452 if ( ASSETCHAINS_SYMBOL[0] != 0 )
ab918767 453 strcpy(symbol,ASSETCHAINS_SYMBOL);
454 else symbol[0] = 0;
8a183335
TH
455 // Windows < Vista: C:\Documents and Settings\Username\Application Data\Zcash
456 // Windows >= Vista: C:\Users\Username\AppData\Roaming\Zcash
457 // Mac: ~/Library/Application Support/Zcash
458 // Unix: ~/.zcash
9cb1ec9c 459#ifdef _WIN32
2097c09a 460 // Windows
dadaab0a 461 if ( symbol[0] == 0 )
892dc7ac 462 return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo";
dadaab0a 463 else return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo" / symbol;
2097c09a 464#else
ee12c3d6 465 fs::path pathRet;
2097c09a
WL
466 char* pszHome = getenv("HOME");
467 if (pszHome == NULL || strlen(pszHome) == 0)
ee12c3d6
PW
468 pathRet = fs::path("/");
469 else
470 pathRet = fs::path(pszHome);
6853e627 471#ifdef MAC_OSX
2097c09a 472 // Mac
940e22fd 473 pathRet /= "Library/Application Support";
2b7709dc 474 TryCreateDirectory(pathRet);
dadaab0a 475 if ( symbol[0] == 0 )
892dc7ac 476 return pathRet / "Komodo";
477 else
478 {
479 pathRet /= "Komodo";
480 TryCreateDirectory(pathRet);
dadaab0a 481 return pathRet / symbol;
892dc7ac 482 }
2097c09a
WL
483#else
484 // Unix
dadaab0a 485 if ( symbol[0] == 0 )
892dc7ac 486 return pathRet / ".komodo";
dadaab0a 487 else return pathRet / ".komodo" / symbol;
2097c09a
WL
488#endif
489#endif
490}
491
ebdb9ff6 492static boost::filesystem::path pathCached;
493static boost::filesystem::path pathCachedNetSpecific;
4f1c3798 494static boost::filesystem::path zc_paramsPathCached;
b94595bb
GA
495static CCriticalSection csPathCached;
496
4f1c3798
SB
497static boost::filesystem::path ZC_GetBaseParamsDir()
498{
499 // Copied from GetDefaultDataDir and adapter for zcash params.
500
501 namespace fs = boost::filesystem;
502 // Windows < Vista: C:\Documents and Settings\Username\Application Data\ZcashParams
503 // Windows >= Vista: C:\Users\Username\AppData\Roaming\ZcashParams
504 // Mac: ~/Library/Application Support/ZcashParams
505 // Unix: ~/.zcash-params
9cb1ec9c 506#ifdef _WIN32
4f1c3798
SB
507 // Windows
508 return GetSpecialFolderPath(CSIDL_APPDATA) / "ZcashParams";
509#else
510 fs::path pathRet;
511 char* pszHome = getenv("HOME");
512 if (pszHome == NULL || strlen(pszHome) == 0)
513 pathRet = fs::path("/");
514 else
515 pathRet = fs::path(pszHome);
516#ifdef MAC_OSX
517 // Mac
518 pathRet /= "Library/Application Support";
519 TryCreateDirectory(pathRet);
520 return pathRet / "ZcashParams";
521#else
522 // Unix
523 return pathRet / ".zcash-params";
524#endif
525#endif
526}
527
528const boost::filesystem::path &ZC_GetParamsDir()
529{
530 namespace fs = boost::filesystem;
531
532 LOCK(csPathCached); // Reuse the same lock as upstream.
533
534 fs::path &path = zc_paramsPathCached;
535
536 // This can be called during exceptions by LogPrintf(), so we cache the
537 // value so we don't have to do memory allocations after that.
538 if (!path.empty())
539 return path;
540
541 path = ZC_GetBaseParamsDir();
4f1c3798
SB
542
543 return path;
544}
545
9064d73b
S
546// Return the user specified export directory. Create directory if it doesn't exist.
547// If user did not set option, return an empty path.
548// If there is a filesystem problem, throw an exception.
549const boost::filesystem::path GetExportDir()
550{
551 namespace fs = boost::filesystem;
552 fs::path path;
553 if (mapArgs.count("-exportdir")) {
554 path = fs::system_complete(mapArgs["-exportdir"]);
555 if (fs::exists(path) && !fs::is_directory(path)) {
556 throw std::runtime_error(strprintf("The -exportdir '%s' already exists and is not a directory", path.string()));
557 }
558 if (!fs::exists(path) && !fs::create_directories(path)) {
559 throw std::runtime_error(strprintf("Failed to create directory at -exportdir '%s'", path.string()));
560 }
561 }
562 return path;
563}
564
565
ee12c3d6 566const boost::filesystem::path &GetDataDir(bool fNetSpecific)
2097c09a 567{
ee12c3d6
PW
568 namespace fs = boost::filesystem;
569
b94595bb
GA
570 LOCK(csPathCached);
571
ebdb9ff6 572 fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
ee12c3d6 573
faaeae1e 574 // This can be called during exceptions by LogPrintf(), so we cache the
ee12c3d6 575 // value so we don't have to do memory allocations after that.
b94595bb 576 if (!path.empty())
ee12c3d6
PW
577 return path;
578
ee12c3d6 579 if (mapArgs.count("-datadir")) {
f4203de3
PW
580 path = fs::system_complete(mapArgs["-datadir"]);
581 if (!fs::is_directory(path)) {
582 path = "";
583 return path;
584 }
ee12c3d6
PW
585 } else {
586 path = GetDefaultDataDir();
2097c09a 587 }
0e4b3175 588 if (fNetSpecific)
84ce18ca 589 path /= BaseParams().DataDir();
2097c09a 590
3e9c8bab 591 fs::create_directories(path);
c1428363 592 //std::string assetpath = path + "/assets";
593 //boost::filesystem::create_directory(assetpath);
ee12c3d6 594 return path;
2097c09a
WL
595}
596
b94595bb
GA
597void ClearDatadirCache()
598{
ebdb9ff6 599 pathCached = boost::filesystem::path();
600 pathCachedNetSpecific = boost::filesystem::path();
b94595bb
GA
601}
602
ee12c3d6 603boost::filesystem::path GetConfigFile()
2097c09a 604{
323832c3 605 char confname[512];
606 if ( ASSETCHAINS_SYMBOL[0] != 0 )
607 sprintf(confname,"%s.conf",ASSETCHAINS_SYMBOL);
923f5177 608 else
609 {
610#ifdef __APPLE__
611 strcpy(confname,"Komodo.conf");
612#else
613 strcpy(confname,"komodo.conf");
614#endif
615 }
323832c3 616 boost::filesystem::path pathConfigFile(GetArg("-conf",confname));
ac14bcc1
PK
617 if (!pathConfigFile.is_complete())
618 pathConfigFile = GetDataDir(false) / pathConfigFile;
619
ee12c3d6 620 return pathConfigFile;
2097c09a
WL
621}
622
f4203de3 623void ReadConfigFile(map<string, string>& mapSettingsRet,
2097c09a
WL
624 map<string, vector<string> >& mapMultiSettingsRet)
625{
3e468840 626 boost::filesystem::ifstream streamConfig(GetConfigFile());
2097c09a 627 if (!streamConfig.good())
d87f00c4 628 throw missing_zcash_conf();
2097c09a
WL
629
630 set<string> setOptions;
631 setOptions.insert("*");
ee12c3d6 632
3e468840 633 for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
2097c09a 634 {
5166804f 635 // Don't overwrite existing settings so command line settings override komodo.conf
2097c09a
WL
636 string strKey = string("-") + it->string_key;
637 if (mapSettingsRet.count(strKey) == 0)
d64e124c 638 {
2097c09a 639 mapSettingsRet[strKey] = it->value[0];
3e468840 640 // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
d64e124c
CM
641 InterpretNegativeSetting(strKey, mapSettingsRet);
642 }
2097c09a
WL
643 mapMultiSettingsRet[strKey].push_back(it->value[0]);
644 }
b94595bb
GA
645 // If datadir is changed in .conf file:
646 ClearDatadirCache();
05c2ba63 647 extern uint16_t BITCOIND_RPCPORT;
648 BITCOIND_RPCPORT = GetArg("-rpcport",BaseParams().RPCPort());
2097c09a
WL
649}
650
9cb1ec9c 651#ifndef _WIN32
ee12c3d6 652boost::filesystem::path GetPidFile()
2097c09a 653{
5166804f 654 boost::filesystem::path pathPidFile(GetArg("-pid", "komodod.pid"));
ee12c3d6
PW
655 if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
656 return pathPidFile;
2097c09a
WL
657}
658
ee12c3d6 659void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
2097c09a 660{
ee12c3d6 661 FILE* file = fopen(path.string().c_str(), "w");
f85c0974 662 if (file)
2097c09a
WL
663 {
664 fprintf(file, "%d\n", pid);
665 fclose(file);
666 }
667}
a034c7eb 668#endif
2097c09a 669
768e5d52
JG
670bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
671{
9cb1ec9c 672#ifdef _WIN32
5f986195 673 return MoveFileExA(src.string().c_str(), dest.string().c_str(),
8d657a65 674 MOVEFILE_REPLACE_EXISTING) != 0;
768e5d52
JG
675#else
676 int rc = std::rename(src.string().c_str(), dest.string().c_str());
677 return (rc == 0);
9cb1ec9c 678#endif /* _WIN32 */
768e5d52
JG
679}
680
c63a73d1
MF
681/**
682 * Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
683 * Specifically handles case where path p exists, but it wasn't possible for the user to
684 * write to the parent directory.
685 */
2b7709dc
BD
686bool TryCreateDirectory(const boost::filesystem::path& p)
687{
688 try
689 {
690 return boost::filesystem::create_directory(p);
27df4123 691 } catch (const boost::filesystem::filesystem_error&) {
2b7709dc
BD
692 if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p))
693 throw;
694 }
695
696 // create_directory didn't create the directory, it had to have existed already
697 return false;
698}
699
768e5d52
JG
700void FileCommit(FILE *fileout)
701{
4c0b2cde 702 fflush(fileout); // harmless if redundantly called
9cb1ec9c 703#ifdef _WIN32
4c0b2cde
PK
704 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout));
705 FlushFileBuffers(hFile);
768e5d52 706#else
e9965213
PW
707 #if defined(__linux__) || defined(__NetBSD__)
708 fdatasync(fileno(fileout));
e7bad10c
GM
709 #elif defined(__APPLE__) && defined(F_FULLFSYNC)
710 fcntl(fileno(fileout), F_FULLFSYNC, 0);
e9965213 711 #else
768e5d52 712 fsync(fileno(fileout));
e9965213 713 #endif
768e5d52
JG
714#endif
715}
716
1eb57879
PW
717bool TruncateFile(FILE *file, unsigned int length) {
718#if defined(WIN32)
719 return _chsize(_fileno(file), length) == 0;
720#else
721 return ftruncate(fileno(file), length) == 0;
722#endif
723}
724
c63a73d1
MF
725/**
726 * this function tries to raise the file descriptor limit to the requested number.
727 * It returns the actual file descriptor limit (which may be more or less than nMinFD)
728 */
ba29a559
PW
729int RaiseFileDescriptorLimit(int nMinFD) {
730#if defined(WIN32)
731 return 2048;
732#else
733 struct rlimit limitFD;
734 if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
735 if (limitFD.rlim_cur < (rlim_t)nMinFD) {
736 limitFD.rlim_cur = nMinFD;
737 if (limitFD.rlim_cur > limitFD.rlim_max)
738 limitFD.rlim_cur = limitFD.rlim_max;
739 setrlimit(RLIMIT_NOFILE, &limitFD);
740 getrlimit(RLIMIT_NOFILE, &limitFD);
741 }
742 return limitFD.rlim_cur;
743 }
744 return nMinFD; // getrlimit failed, assume it's fine
745#endif
746}
747
c63a73d1
MF
748/**
749 * this function tries to make a particular range of a file allocated (corresponding to disk space)
750 * it is advisory, and the range specified in the arguments will never contain live data
751 */
bba89aa8 752void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
288fdc09
PW
753#if defined(WIN32)
754 // Windows-specific version
755 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
756 LARGE_INTEGER nFileSize;
51ed9ec9 757 int64_t nEndPos = (int64_t)offset + length;
288fdc09
PW
758 nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
759 nFileSize.u.HighPart = nEndPos >> 32;
760 SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
761 SetEndOfFile(hFile);
762#elif defined(MAC_OSX)
763 // OSX specific version
764 fstore_t fst;
765 fst.fst_flags = F_ALLOCATECONTIG;
766 fst.fst_posmode = F_PEOFPOSMODE;
767 fst.fst_offset = 0;
768 fst.fst_length = (off_t)offset + length;
769 fst.fst_bytesalloc = 0;
770 if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
771 fst.fst_flags = F_ALLOCATEALL;
772 fcntl(fileno(file), F_PREALLOCATE, &fst);
773 }
774 ftruncate(fileno(file), fst.fst_length);
775#elif defined(__linux__)
776 // Version using posix_fallocate
777 off_t nEndPos = (off_t)offset + length;
778 posix_fallocate(fileno(file), 0, nEndPos);
779#else
780 // Fallback version
781 // TODO: just write one byte per block
bba89aa8
PW
782 static const char buf[65536] = {};
783 fseek(file, offset, SEEK_SET);
784 while (length > 0) {
785 unsigned int now = 65536;
786 if (length < now)
787 now = length;
788 fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
789 length -= now;
790 }
288fdc09 791#endif
bba89aa8
PW
792}
793
2097c09a
WL
794void ShrinkDebugFile()
795{
796 // Scroll debug.log if it's getting too big
ee12c3d6
PW
797 boost::filesystem::path pathLog = GetDataDir() / "debug.log";
798 FILE* file = fopen(pathLog.string().c_str(), "r");
a486abd4 799 if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000)
2097c09a
WL
800 {
801 // Restart the file with some of the end
fcb0a1bb 802 std::vector <char> vch(200000,0);
1e735048 803 fseek(file, -((long)vch.size()), SEEK_END);
fcb0a1bb 804 int nBytes = fread(begin_ptr(vch), 1, vch.size(), file);
2097c09a 805 fclose(file);
f85c0974 806
ee12c3d6 807 file = fopen(pathLog.string().c_str(), "w");
f85c0974 808 if (file)
2097c09a 809 {
fcb0a1bb 810 fwrite(begin_ptr(vch), 1, nBytes, file);
2097c09a
WL
811 fclose(file);
812 }
813 }
3260b4c0
PK
814 else if (file != NULL)
815 fclose(file);
2097c09a
WL
816}
817
9cb1ec9c 818#ifdef _WIN32
3e468840
PK
819boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
820{
821 namespace fs = boost::filesystem;
822
823 char pszPath[MAX_PATH] = "";
824
825 if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
826 {
827 return fs::path(pszPath);
828 }
829
881a85a2 830 LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
3e468840
PK
831 return fs::path("");
832}
ed6d0b5f 833#endif
429039d4 834
597fa4cd
PW
835boost::filesystem::path GetTempPath() {
836#if BOOST_FILESYSTEM_VERSION == 3
837 return boost::filesystem::temp_directory_path();
838#else
839 // TODO: remove when we don't support filesystem v2 anymore
840 boost::filesystem::path path;
9cb1ec9c 841#ifdef _WIN32
597fa4cd
PW
842 char pszPath[MAX_PATH] = "";
843
844 if (GetTempPathA(MAX_PATH, pszPath))
845 path = boost::filesystem::path(pszPath);
846#else
847 path = boost::filesystem::path("/tmp");
848#endif
849 if (path.empty() || !boost::filesystem::is_directory(path)) {
881a85a2 850 LogPrintf("GetTempPath(): failed to find temp path\n");
597fa4cd
PW
851 return boost::filesystem::path("");
852 }
853 return path;
854#endif
855}
856
db954a65 857void runCommand(const std::string& strCommand)
429039d4
JG
858{
859 int nErr = ::system(strCommand.c_str());
860 if (nErr)
7d9d134b 861 LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
429039d4
JG
862}
863
96931d6f
GS
864void RenameThread(const char* name)
865{
b277b0f1 866#if defined(PR_SET_NAME)
96931d6f
GS
867 // Only the first 15 characters are used (16 - NUL terminator)
868 ::prctl(PR_SET_NAME, name, 0, 0, 0);
7f386d2f 869#elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
304ca955 870 pthread_set_name_np(pthread_self(), name);
cd58f058 871
850c570d 872#elif defined(MAC_OSX)
c8c2fbe0 873 pthread_setname_np(name);
96931d6f
GS
874#else
875 // Prevent warnings for unused parameters...
876 (void)name;
877#endif
878}
0b47fe6b 879
5248ff40
SC
880void SetupEnvironment()
881{
317e66c7 882 // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
883 // may be invalid, in which case the "C" locale is used as fallback.
884#if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
885 try {
3da78490 886 std::locale(""); // Raises a runtime error if current locale is invalid
27df4123 887 } catch (const std::runtime_error&) {
ba0fa0d9 888 setenv("LC_ALL", "C", 1);
5248ff40 889 }
ac14bcc1 890#endif
3da78490 891 // The path locale is lazy initialized and to avoid deinitialization errors
317e66c7 892 // in multithreading environments, it is set explicitly by the main thread.
3da78490
JS
893 // A dummy locale is used to extract the internal default locale, used by
894 // boost::filesystem::path, which is then used to explicitly imbue the path.
895 std::locale loc = boost::filesystem::path::imbue(std::locale::classic());
ba0fa0d9 896 boost::filesystem::path::imbue(loc);
5248ff40 897}
3e8ac6af 898
167b6231
WL
899bool SetupNetworking()
900{
9cb1ec9c 901#ifdef _WIN32
167b6231
WL
902 // Initialize Windows Sockets
903 WSADATA wsadata;
904 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
905 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
906 return false;
907#endif
908 return true;
909}
910
610a8c07
WL
911void SetThreadPriority(int nPriority)
912{
9cb1ec9c 913#ifdef _WIN32
610a8c07 914 SetThreadPriority(GetCurrentThread(), nPriority);
9cb1ec9c 915#else // _WIN32
610a8c07
WL
916#ifdef PRIO_THREAD
917 setpriority(PRIO_THREAD, 0, nPriority);
918#else // PRIO_THREAD
919 setpriority(PRIO_PROCESS, 0, nPriority);
920#endif // PRIO_THREAD
9cb1ec9c 921#endif // _WIN32
610a8c07 922}
af021144 923
f0d1accb
DH
924std::string PrivacyInfo()
925{
926 return "\n" +
927 FormatParagraph(strprintf(_("In order to ensure you are adequately protecting your privacy when using Zcash, please see <%s>."),
10512429 928 "https://z.cash/support/security/")) + "\n";
f0d1accb
DH
929}
930
af021144
S
931std::string LicenseInfo()
932{
f0d1accb 933 return "\n" +
ab1d2d57 934 FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" +
af021144 935 FormatParagraph(strprintf(_("Copyright (C) 2015-%i The Zcash Developers"), COPYRIGHT_YEAR)) + "\n" +
62526d82 936 FormatParagraph(strprintf(_("Copyright (C) 2015-%i jl777 and SuperNET developers"), COPYRIGHT_YEAR)) + "\n" +
937 "\n" +
af021144
S
938 FormatParagraph(_("This is experimental software.")) + "\n" +
939 "\n" +
940 FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.")) + "\n" +
941 "\n" +
506a2185 942 FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young.")) +
af021144
S
943 "\n";
944}
da1357e6
WL
945
946int GetNumCores()
947{
da1357e6 948 return boost::thread::physical_concurrency();
da1357e6
WL
949}
950
This page took 0.648765 seconds and 4 git commands to generate.