]> Git Repo - VerusCoin.git/blob - src/util.cpp
Fix stakeguard validation
[VerusCoin.git] / src / util.cpp
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 https://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 #include "komodo_defs.h"
19
20 #include <stdarg.h>
21 #include <sstream>
22 #include <vector>
23 #include <stdio.h>
24
25 #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
26 #include <pthread.h>
27 #include <pthread_np.h>
28 #endif
29
30 #ifndef _WIN32
31 // for posix_fallocate
32 #ifdef __linux__
33
34 #ifdef _POSIX_C_SOURCE
35 #undef _POSIX_C_SOURCE
36 #endif
37
38 #define _POSIX_C_SOURCE 200112L
39
40 #endif // __linux__
41
42 #include <algorithm>
43 #include <fcntl.h>
44 #include <sys/resource.h>
45 #include <sys/stat.h>
46
47 #else
48
49 #ifdef _MSC_VER
50 #pragma warning(disable:4786)
51 #pragma warning(disable:4804)
52 #pragma warning(disable:4805)
53 #pragma warning(disable:4717)
54 #endif
55
56 #ifdef _WIN32_WINNT
57 #undef _WIN32_WINNT
58 #endif
59 #define _WIN32_WINNT 0x0501
60
61 #ifdef _WIN32_IE
62 #undef _WIN32_IE
63 #endif
64 #define _WIN32_IE 0x0501
65
66 #define WIN32_LEAN_AND_MEAN 1
67 #ifndef NOMINMAX
68 #define NOMINMAX
69 #endif
70
71 #include <io.h> /* for _commit */
72 #include <shlobj.h>
73 #endif
74
75 #ifdef HAVE_SYS_PRCTL_H
76 #include <sys/prctl.h>
77 #endif
78
79 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
80 #include <boost/algorithm/string/join.hpp>
81 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
82 #include <boost/filesystem.hpp>
83 #include <boost/filesystem/fstream.hpp>
84 #include <boost/foreach.hpp>
85 #include <boost/program_options/detail/config_file.hpp>
86 #include <boost/program_options/parsers.hpp>
87 #include <boost/thread.hpp>
88 #include <openssl/crypto.h>
89 #include <openssl/conf.h>
90
91 // Work around clang compilation problem in Boost 1.46:
92 // /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
93 // See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
94 //           http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
95 namespace boost {
96
97     namespace program_options {
98         std::string to_internal(const std::string&);
99     }
100
101 } // namespace boost
102
103 using namespace std;
104
105 map<string, string> mapArgs;
106 map<string, vector<string> > mapMultiArgs;
107 bool fDebug = false;
108 bool fPrintToConsole = false;
109 bool fPrintToDebugLog = true;
110 bool fDaemon = false;
111 bool fServer = false;
112 string strMiscWarning;
113 bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
114 bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
115 bool fLogIPs = DEFAULT_LOGIPS;
116 std::atomic<bool> fReopenDebugLog(false);
117 CTranslationInterface translationInterface;
118
119 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
120
121 bool _IsVerusActive()
122 {
123     return (strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0 || strcmp(ASSETCHAINS_SYMBOL, "VRSCTEST") == 0);
124 }
125
126 bool _IsVerusMainnetActive()
127 {
128     return (strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0);
129 }
130
131 /** Init OpenSSL library multithreading support */
132 static CCriticalSection** ppmutexOpenSSL;
133 void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
134 {
135     if (mode & CRYPTO_LOCK) {
136         ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
137     } else {
138         LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
139     }
140 }
141
142 // Init
143 static class CInit
144 {
145 public:
146     CInit()
147     {
148         // Init OpenSSL library multithreading support
149         ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*));
150         for (int i = 0; i < CRYPTO_num_locks(); i++)
151             ppmutexOpenSSL[i] = new CCriticalSection();
152         CRYPTO_set_locking_callback(locking_callback);
153
154         // OpenSSL can optionally load a config file which lists optional loadable modules and engines.
155         // We don't use them so we don't require the config. However some of our libs may call functions
156         // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing
157         // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
158         // that the config appears to have been loaded and there are no modules/engines available.
159         OPENSSL_no_config();
160     }
161     ~CInit()
162     {
163         // Shutdown OpenSSL library multithreading support
164         CRYPTO_set_locking_callback(NULL);
165         for (int i = 0; i < CRYPTO_num_locks(); i++)
166             delete ppmutexOpenSSL[i];
167         OPENSSL_free(ppmutexOpenSSL);
168     }
169 }
170 instance_of_cinit;
171
172 /**
173  * LogPrintf() has been broken a couple of times now
174  * by well-meaning people adding mutexes in the most straightforward way.
175  * It breaks because it may be called by global destructors during shutdown.
176  * Since the order of destruction of static/global objects is undefined,
177  * defining a mutex as a global object doesn't work (the mutex gets
178  * destroyed, and then some later destructor calls OutputDebugStringF,
179  * maybe indirectly, and you get a core dump at shutdown trying to lock
180  * the mutex).
181  */
182
183 static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
184
185 /**
186  * We use boost::call_once() to make sure mutexDebugLog and
187  * vMsgsBeforeOpenLog are initialized in a thread-safe manner.
188  *
189  * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
190  * are leaked on exit. This is ugly, but will be cleaned up by
191  * the OS/libc. When the shutdown sequence is fully audited and
192  * tested, explicit destruction of these objects can be implemented.
193  */
194 static FILE* fileout = NULL;
195 static boost::mutex* mutexDebugLog = NULL;
196 static list<string> *vMsgsBeforeOpenLog;
197
198 [[noreturn]] void new_handler_terminate()
199 {
200     // Rather than throwing std::bad-alloc if allocation fails, terminate
201     // immediately to (try to) avoid chain corruption.
202     // Since LogPrintf may itself allocate memory, set the handler directly
203     // to terminate first.
204     std::set_new_handler(std::terminate);
205     fputs("Error: Out of memory. Terminating.\n", stderr);
206     LogPrintf("Error: Out of memory. Terminating.\n");
207
208     // The log was successful, terminate now.
209     std::terminate();
210 };
211
212 static int FileWriteStr(const std::string &str, FILE *fp)
213 {
214     return fwrite(str.data(), 1, str.size(), fp);
215 }
216
217 static void DebugPrintInit()
218 {
219     assert(mutexDebugLog == NULL);
220     mutexDebugLog = new boost::mutex();
221     vMsgsBeforeOpenLog = new list<string>;
222 }
223
224 void OpenDebugLog()
225 {
226     boost::call_once(&DebugPrintInit, debugPrintInitFlag);
227     boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
228
229     assert(fileout == NULL);
230     assert(vMsgsBeforeOpenLog);
231     boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
232     fileout = fopen(pathDebug.string().c_str(), "a");
233     if (fileout) setbuf(fileout, NULL); // unbuffered
234
235     // dump buffered messages from before we opened the log
236     while (!vMsgsBeforeOpenLog->empty()) {
237         FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
238         vMsgsBeforeOpenLog->pop_front();
239     }
240
241     delete vMsgsBeforeOpenLog;
242     vMsgsBeforeOpenLog = NULL;
243 }
244
245 bool LogAcceptCategory(const char* category)
246 {
247     if (category != NULL)
248     {
249         if (!fDebug)
250             return false;
251
252         // Give each thread quick access to -debug settings.
253         // This helps prevent issues debugging global destructors,
254         // where mapMultiArgs might be deleted before another
255         // global destructor calls LogPrint()
256         static boost::thread_specific_ptr<set<string>> ptrCategory;
257         if (ptrCategory.get() == NULL)
258         {
259             const vector<string>& categories = mapMultiArgs["-debug"];
260             ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
261             // thread_specific_ptr automatically deletes the set when the thread ends.
262         }
263         const set<string>& setCategories = *ptrCategory.get();
264
265         // if not debugging everything and not debugging specific category, LogPrint does nothing.
266         if (setCategories.count(string("")) == 0 &&
267             setCategories.count(string("1")) == 0 &&
268             setCategories.count(string(category)) == 0)
269             return false;
270     }
271     return true;
272 }
273
274 /**
275  * fStartedNewLine is a state variable held by the calling context that will
276  * suppress printing of the timestamp when multiple calls are made that don't
277  * end in a newline. Initialize it to true, and hold it, in the calling context.
278  */
279 static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
280 {
281     string strStamped;
282
283     if (!fLogTimestamps)
284         return str;
285
286     if (*fStartedNewLine)
287         strStamped =  DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
288     else
289         strStamped = str;
290
291     if (!str.empty() && str[str.size()-1] == '\n')
292         *fStartedNewLine = true;
293     else
294         *fStartedNewLine = false;
295
296     return strStamped;
297 }
298
299 int LogPrintStr(const std::string &str)
300 {
301     int ret = 0; // Returns total number of characters written
302     static bool fStartedNewLine = true;
303     if (fPrintToConsole)
304     {
305         // print to console
306         ret = fwrite(str.data(), 1, str.size(), stdout);
307         fflush(stdout);
308     }
309     else if (fPrintToDebugLog)
310     {
311         boost::call_once(&DebugPrintInit, debugPrintInitFlag);
312         boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
313
314         string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
315
316         // buffer if we haven't opened the log yet
317         if (fileout == NULL) {
318             assert(vMsgsBeforeOpenLog);
319             ret = strTimestamped.length();
320             vMsgsBeforeOpenLog->push_back(strTimestamped);
321         }
322         else
323         {
324             // reopen the log file, if requested
325             if (fReopenDebugLog) {
326                 fReopenDebugLog = false;
327                 boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
328                 if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
329                     setbuf(fileout, NULL); // unbuffered
330             }
331
332             ret = FileWriteStr(strTimestamped, fileout);
333         }
334     }
335     return ret;
336 }
337
338 static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
339 {
340     // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
341     if (name.find("-no") == 0)
342     {
343         std::string positive("-");
344         positive.append(name.begin()+3, name.end());
345         if (mapSettingsRet.count(positive) == 0)
346         {
347             bool value = !GetBoolArg(name, false);
348             mapSettingsRet[positive] = (value ? "1" : "0");
349         }
350     }
351 }
352
353 void ParseParameters(int argc, const char* const argv[])
354 {
355     mapArgs.clear();
356     mapMultiArgs.clear();
357
358     for (int i = 1; i < argc; i++)
359     {
360         std::string str(argv[i]);
361         std::string strValue;
362         size_t is_index = str.find('=');
363         if (is_index != std::string::npos)
364         {
365             strValue = str.substr(is_index+1);
366             str = str.substr(0, is_index);
367         }
368 #ifdef _WIN32
369         boost::to_lower(str);
370         if (boost::algorithm::starts_with(str, "/"))
371             str = "-" + str.substr(1);
372 #endif
373
374         if (str[0] != '-')
375             break;
376
377         // Interpret --foo as -foo.
378         // If both --foo and -foo are set, the last takes effect.
379         if (str.length() > 1 && str[1] == '-')
380             str = str.substr(1);
381
382         mapArgs[str] = strValue;
383         mapMultiArgs[str].push_back(strValue);
384     }
385
386     // New 0.6 features:
387     BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs)
388     {
389         // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
390         InterpretNegativeSetting(entry.first, mapArgs);
391     }
392 }
393
394 void Split(const std::string& strVal, uint64_t *outVals, const uint64_t nDefault,int maxElements)
395 {
396     stringstream ss(strVal);
397     vector<uint64_t> vec;
398
399     uint64_t i, nLast, numVals = 0;
400
401     while ( ss.peek() == ' ' )
402         ss.ignore();
403
404     while ( numVals < maxElements && ss >> i )
405     {
406         outVals[numVals] = i;
407         numVals += 1;
408
409         while ( ss.peek() == ' ' )
410             ss.ignore();
411         if ( ss.peek() == ',' )
412             ss.ignore();
413         while ( ss.peek() == ' ' )
414             ss.ignore();
415     }
416
417     if ( numVals > 0 )
418         nLast = outVals[numVals - 1];
419     else
420         nLast = nDefault;
421
422     for ( i = numVals; i < maxElements; i++ )
423     {
424         outVals[i] = nLast;
425     }
426 }
427
428 std::string GetArg(const std::string& strArg, const std::string& strDefault)
429 {
430     if (mapArgs.count(strArg))
431         return mapArgs[strArg];
432     return strDefault;
433 }
434
435 int64_t GetArg(const std::string& strArg, int64_t nDefault)
436 {
437     if (mapArgs.count(strArg))
438         return atoi64(mapArgs[strArg]);
439     return nDefault;
440 }
441
442 bool GetBoolArg(const std::string& strArg, bool fDefault)
443 {
444     if (mapArgs.count(strArg))
445     {
446         if (mapArgs[strArg].empty())
447             return true;
448         return (atoi(mapArgs[strArg]) != 0);
449     }
450     return fDefault;
451 }
452
453 bool SoftSetArg(const std::string& strArg, const std::string& strValue)
454 {
455     if (mapArgs.count(strArg))
456         return false;
457     mapArgs[strArg] = strValue;
458     return true;
459 }
460
461 bool SoftSetBoolArg(const std::string& strArg, bool fValue)
462 {
463     if (fValue)
464         return SoftSetArg(strArg, std::string("1"));
465     else
466         return SoftSetArg(strArg, std::string("0"));
467 }
468
469 static const int screenWidth = 79;
470 static const int optIndent = 2;
471 static const int msgIndent = 7;
472
473 std::string HelpMessageGroup(const std::string &message) {
474     return std::string(message) + std::string("\n\n");
475 }
476
477 std::string HelpMessageOpt(const std::string &option, const std::string &message) {
478     return std::string(optIndent,' ') + std::string(option) +
479            std::string("\n") + std::string(msgIndent,' ') +
480            FormatParagraph(message, screenWidth - msgIndent, msgIndent) +
481            std::string("\n\n");
482 }
483
484 static std::string FormatException(const std::exception* pex, const char* pszThread)
485 {
486 #ifdef _WIN32
487     char pszModule[MAX_PATH] = "";
488     GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
489 #else
490     const char* pszModule = "Komodo";
491 #endif
492     if (pex)
493         return strprintf(
494             "EXCEPTION: %s       \n%s       \n%s in %s       \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
495     else
496         return strprintf(
497             "UNKNOWN EXCEPTION       \n%s in %s       \n", pszModule, pszThread);
498 }
499
500 void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
501 {
502     std::string message = FormatException(pex, pszThread);
503     LogPrintf("\n\n************************\n%s\n", message);
504     fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
505     strMiscWarning = message;
506 }
507
508 //int64_t MAX_MONEY = 200000000 * 100000000LL;
509
510 boost::filesystem::path GetDefaultDataDir()
511 {
512     namespace fs = boost::filesystem;
513     char symbol[KOMODO_ASSETCHAIN_MAXLEN];
514     if ( ASSETCHAINS_SYMBOL[0] != 0 )
515         strcpy(symbol,ASSETCHAINS_SYMBOL);
516     else symbol[0] = 0;
517     // Windows < Vista: C:\Documents and Settings\Username\Application Data\Zcash
518     // Windows >= Vista: C:\Users\Username\AppData\Roaming\Zcash
519     // Mac: ~/Library/Application Support/Zcash
520     // Unix: ~/.zcash
521 #ifdef _WIN32
522     // Windows
523     if ( symbol[0] == 0 )
524         return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo";
525     else
526     {
527         if (_IsVerusActive())
528         {
529             return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo" / symbol;
530         }
531         else
532         {
533             return GetSpecialFolderPath(CSIDL_APPDATA) / (PBAAS_TESTMODE ? "VerusTest" : "Verus") / "PBAAS" / symbol;
534         }
535     }
536 #else
537     fs::path pathRet;
538     char* pszHome = getenv("HOME");
539     if (pszHome == NULL || strlen(pszHome) == 0)
540         pathRet = fs::path("/");
541     else
542         pathRet = fs::path(pszHome);
543 #ifdef MAC_OSX
544     // Mac
545     pathRet /= "Library/Application Support";
546     TryCreateDirectory(pathRet);
547     if ( symbol[0] == 0 )
548         return pathRet / "Komodo";
549     else
550     {
551         if (_IsVerusActive())
552         {
553             pathRet /= "Komodo";
554             TryCreateDirectory(pathRet);
555         }
556         else
557         {
558             pathRet /= PBAAS_TESTMODE ? "VerusTest" : "Verus";
559             TryCreateDirectory(pathRet);
560             pathRet /= "PBAAS";
561             TryCreateDirectory(pathRet);
562         }
563         return pathRet / symbol;
564     }
565 #else
566     // Unix
567     if ( symbol[0] == 0 )
568         return pathRet / ".komodo";
569     else
570     {
571         if (_IsVerusActive())
572         {
573             return pathRet / ".komodo" / symbol;
574         }
575         else
576         {
577             return pathRet / (PBAAS_TESTMODE ? ".verustest" : ".verus") / "PBAAS" / symbol;
578         }
579     }
580 #endif
581 #endif
582 }
583
584 boost::filesystem::path GetDefaultDataDir(std::string chainName)
585 {
586     char symbol[KOMODO_ASSETCHAIN_MAXLEN];
587     if (chainName.size() >= KOMODO_ASSETCHAIN_MAXLEN)
588         chainName.resize(KOMODO_ASSETCHAIN_MAXLEN - 1);
589     strcpy(symbol, chainName.c_str());
590
591     namespace fs = boost::filesystem;
592
593     // Windows < Vista: C:\Documents and Settings\Username\Application Data\Zcash
594     // Windows >= Vista: C:\Users\Username\AppData\Roaming\Zcash
595     // Mac: ~/Library/Application Support/Zcash
596     // Unix: ~/.zcash
597 #ifdef _WIN32
598     // Windows
599     if (chainName == "VRSC" || chainName == "VRSCTEST")
600     {
601         return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo" / symbol;
602     }
603     else
604     {
605         return GetSpecialFolderPath(CSIDL_APPDATA) / (PBAAS_TESTMODE ? "VerusTest" : "Verus") / "PBAAS" / symbol;
606     }
607 #else
608     fs::path pathRet;
609     char* pszHome = getenv("HOME");
610     if (pszHome == NULL || strlen(pszHome) == 0)
611         pathRet = fs::path("/");
612     else
613         pathRet = fs::path(pszHome);
614 #ifdef MAC_OSX
615     // Mac
616     pathRet /= "Library/Application Support";
617     TryCreateDirectory(pathRet);
618     if (chainName == "VRSC" || chainName == "VRSCTEST")
619     {
620         pathRet /= "Komodo";
621         TryCreateDirectory(pathRet);
622     }
623     else
624     {
625         pathRet /= PBAAS_TESTMODE ? "VerusTest" : "Verus";
626         TryCreateDirectory(pathRet);
627         pathRet /= "PBAAS";
628         TryCreateDirectory(pathRet);
629     }
630     return pathRet / symbol;
631 #else
632     // Unix
633     if (chainName == "VRSC" || chainName == "VRSCTEST")
634     {
635         return pathRet / ".komodo" / symbol;
636     }
637     else
638     {
639         return pathRet / (PBAAS_TESTMODE ? ".verustest" : ".verus") / "PBAAS" / symbol;
640     }
641 #endif
642 #endif
643 }
644
645 static boost::filesystem::path pathCached;
646 static boost::filesystem::path pathCachedNetSpecific;
647 static boost::filesystem::path zc_paramsPathCached;
648 static CCriticalSection csPathCached;
649
650 static boost::filesystem::path ZC_GetBaseParamsDir()
651 {
652     // Copied from GetDefaultDataDir and adapter for zcash params.
653
654     namespace fs = boost::filesystem;
655     // Windows < Vista: C:\Documents and Settings\Username\Application Data\ZcashParams
656     // Windows >= Vista: C:\Users\Username\AppData\Roaming\ZcashParams
657     // Mac: ~/Library/Application Support/ZcashParams
658     // Unix: ~/.zcash-params
659     fs::path pathRet;
660 #ifdef _WIN32
661     return GetSpecialFolderPath(CSIDL_APPDATA) / "ZcashParams";
662 #else
663     char* pszHome = getenv("HOME");
664     if (pszHome == NULL || strlen(pszHome) == 0)
665         pathRet = fs::path("/");
666     else
667         pathRet = fs::path(pszHome);
668 #ifdef MAC_OSX
669     // Mac
670     pathRet /= "Library/Application Support";
671     TryCreateDirectory(pathRet);
672     return pathRet / "ZcashParams";
673 #else
674     // Unix
675     return pathRet / ".zcash-params";
676 #endif
677 #endif
678 }
679
680 const boost::filesystem::path &ZC_GetParamsDir()
681 {
682     namespace fs = boost::filesystem;
683
684     LOCK(csPathCached); // Reuse the same lock as upstream.
685
686     fs::path &path = zc_paramsPathCached;
687
688     // This can be called during exceptions by LogPrintf(), so we cache the
689     // value so we don't have to do memory allocations after that.
690     if (!path.empty())
691         return path;
692
693     path = ZC_GetBaseParamsDir();
694
695     return path;
696 }
697
698 // Return the user specified export directory.  Create directory if it doesn't exist.
699 // If user did not set option, return an empty path.
700 // If there is a filesystem problem, throw an exception.
701 const boost::filesystem::path GetExportDir()
702 {
703     namespace fs = boost::filesystem;
704     fs::path path;
705     if (!mapArgs.count("-exportdir"))
706     {
707         path = GetDataDir();
708     }
709     else
710     {
711         path = fs::system_complete(mapArgs["-exportdir"]);
712         if (fs::exists(path) && !fs::is_directory(path)) {
713             throw std::runtime_error(strprintf("The -exportdir '%s' already exists and is not a directory", path.string()));
714         }
715         if (!fs::exists(path) && !fs::create_directories(path)) {
716             throw std::runtime_error(strprintf("Failed to create directory at -exportdir '%s'", path.string()));
717         }
718     }
719     return path;
720 }
721
722
723 const boost::filesystem::path &GetDataDir(bool fNetSpecific)
724 {
725     namespace fs = boost::filesystem;
726
727     LOCK(csPathCached);
728
729     fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
730
731     // This can be called during exceptions by LogPrintf(), so we cache the
732     // value so we don't have to do memory allocations after that.
733     if (!path.empty())
734         return path;
735
736     if (mapArgs.count("-datadir")) {
737         path = fs::system_complete(mapArgs["-datadir"]);
738         if (!fs::is_directory(path)) {
739             path = "";
740             return path;
741         }
742     } else {
743         path = GetDefaultDataDir();
744     }
745     if (fNetSpecific)
746         path /= BaseParams().DataDir();
747
748     fs::create_directories(path);
749     //std::string assetpath = path + "/assets";
750     //boost::filesystem::create_directory(assetpath);
751     return path;
752 }
753
754 const boost::filesystem::path GetDataDir(std::string chainName)
755 {
756     namespace fs = boost::filesystem;
757     fs::path path;
758
759     if ((chainName == "VRSC" || chainName == "VRSCTEST") && mapArgs.count("-datadir")) {
760         path = fs::system_complete(mapArgs["-datadir"]);
761         if (!fs::is_directory(path)) {
762             path = GetDefaultDataDir(chainName);
763         }
764     } else
765     {
766         path = GetDefaultDataDir(chainName);
767     }
768     return path;
769 }
770 void ClearDatadirCache()
771 {
772     pathCached = boost::filesystem::path();
773     pathCachedNetSpecific = boost::filesystem::path();
774 }
775
776 boost::filesystem::path GetConfigFile()
777 {
778     char confname[512];
779     if ( ASSETCHAINS_SYMBOL[0] != 0 )
780         sprintf(confname,"%s.conf",ASSETCHAINS_SYMBOL);
781     else
782     {
783 #ifdef __APPLE__
784         strcpy(confname,"Komodo.conf");
785 #else
786         strcpy(confname,"komodo.conf");
787 #endif
788     }
789     boost::filesystem::path pathConfigFile(GetArg("-conf",confname));
790     if (!pathConfigFile.is_complete())
791         pathConfigFile = GetDataDir(false) / pathConfigFile;
792
793     return pathConfigFile;
794 }
795
796 boost::filesystem::path GetConfigFile(std::string chainName)
797 {
798     char confname[512];
799     if (chainName.size() >= KOMODO_ASSETCHAIN_MAXLEN)
800         chainName.resize(KOMODO_ASSETCHAIN_MAXLEN - 1);
801     sprintf(confname, "%s.conf", chainName.c_str());
802     boost::filesystem::path pathConfigFile(GetArg("-conf",confname));
803     if (!pathConfigFile.is_complete())
804         pathConfigFile = GetDataDir(chainName) / pathConfigFile;
805
806     return pathConfigFile;
807 }
808
809 void ReadConfigFile(map<string, string>& mapSettingsRet,
810                     map<string, vector<string> >& mapMultiSettingsRet)
811 {
812     boost::filesystem::ifstream streamConfig(GetConfigFile());
813     if (!streamConfig.good())
814         throw missing_zcash_conf();
815
816     set<string> setOptions;
817     setOptions.insert("*");
818
819     for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
820     {
821         // Don't overwrite existing settings so command line settings override komodo.conf
822         string strKey = string("-") + it->string_key;
823         if (mapSettingsRet.count(strKey) == 0)
824         {
825             mapSettingsRet[strKey] = it->value[0];
826             // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
827             InterpretNegativeSetting(strKey, mapSettingsRet);
828         }
829         mapMultiSettingsRet[strKey].push_back(it->value[0]);
830     }
831     // If datadir is changed in .conf file:
832     ClearDatadirCache();
833     extern uint16_t BITCOIND_RPCPORT;
834     BITCOIND_RPCPORT = GetArg("-rpcport",BaseParams().RPCPort());
835 }
836
837 // for reading an external config file. does not clear the data dir cache
838 bool ReadConfigFile(std::string chainName,
839                     map<string, string>& mapSettingsRet,
840                     map<string, vector<string> >& mapMultiSettingsRet)
841 {
842     boost::filesystem::ifstream streamConfig(GetConfigFile(chainName));
843     if (!streamConfig.good())
844         return false;
845
846     set<string> setOptions;
847     setOptions.insert("*");
848
849     for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
850     {
851         // Don't overwrite existing settings so command line settings override komodo.conf
852         string strKey = string("-") + it->string_key;
853         if (mapSettingsRet.count(strKey) == 0)
854         {
855             mapSettingsRet[strKey] = it->value[0];
856             // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
857             InterpretNegativeSetting(strKey, mapSettingsRet);
858         }
859         mapMultiSettingsRet[strKey].push_back(it->value[0]);
860     }
861     return true;
862 }
863
864 #ifndef _WIN32
865 boost::filesystem::path GetPidFile()
866 {
867     boost::filesystem::path pathPidFile(GetArg("-pid", "verusd.pid"));
868     if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
869     return pathPidFile;
870 }
871
872 void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
873 {
874     FILE* file = fopen(path.string().c_str(), "w");
875     if (file)
876     {
877         fprintf(file, "%d\n", pid);
878         fclose(file);
879     }
880 }
881 #endif
882
883 bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
884 {
885 #ifdef _WIN32
886     return MoveFileExA(src.string().c_str(), dest.string().c_str(),
887                        MOVEFILE_REPLACE_EXISTING) != 0;
888 #else
889     int rc = std::rename(src.string().c_str(), dest.string().c_str());
890     return (rc == 0);
891 #endif /* _WIN32 */
892 }
893
894 /**
895  * Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
896  * Specifically handles case where path p exists, but it wasn't possible for the user to
897  * write to the parent directory.
898  */
899 bool TryCreateDirectory(const boost::filesystem::path& p)
900 {
901     try
902     {
903         return boost::filesystem::create_directory(p);
904     } catch (const boost::filesystem::filesystem_error&) {
905         if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p))
906             throw;
907     }
908
909     // create_directory didn't create the directory, it had to have existed already
910     return false;
911 }
912
913 void FileCommit(FILE *fileout)
914 {
915     fflush(fileout); // harmless if redundantly called
916 #ifdef _WIN32
917     HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout));
918     FlushFileBuffers(hFile);
919 #else
920     #if defined(__linux__) || defined(__NetBSD__)
921     fdatasync(fileno(fileout));
922     #elif defined(__APPLE__) && defined(F_FULLFSYNC)
923     fcntl(fileno(fileout), F_FULLFSYNC, 0);
924     #else
925     fsync(fileno(fileout));
926     #endif
927 #endif
928 }
929
930 bool TruncateFile(FILE *file, unsigned int length) {
931 #if defined(WIN32)
932     return _chsize(_fileno(file), length) == 0;
933 #else
934     return ftruncate(fileno(file), length) == 0;
935 #endif
936 }
937
938 /**
939  * this function tries to raise the file descriptor limit to the requested number.
940  * It returns the actual file descriptor limit (which may be more or less than nMinFD)
941  */
942 int RaiseFileDescriptorLimit(int nMinFD) {
943 #if defined(WIN32)
944     return 2048;
945 #else
946     struct rlimit limitFD;
947     if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
948         if (limitFD.rlim_cur < (rlim_t)nMinFD) {
949             limitFD.rlim_cur = nMinFD;
950             if (limitFD.rlim_cur > limitFD.rlim_max)
951                 limitFD.rlim_cur = limitFD.rlim_max;
952             setrlimit(RLIMIT_NOFILE, &limitFD);
953             getrlimit(RLIMIT_NOFILE, &limitFD);
954         }
955         return limitFD.rlim_cur;
956     }
957     return nMinFD; // getrlimit failed, assume it's fine
958 #endif
959 }
960
961 /**
962  * this function tries to make a particular range of a file allocated (corresponding to disk space)
963  * it is advisory, and the range specified in the arguments will never contain live data
964  */
965 void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
966 #if defined(WIN32)
967     // Windows-specific version
968     HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
969     LARGE_INTEGER nFileSize;
970     int64_t nEndPos = (int64_t)offset + length;
971     nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
972     nFileSize.u.HighPart = nEndPos >> 32;
973     SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
974     SetEndOfFile(hFile);
975 #elif defined(MAC_OSX)
976     // OSX specific version
977     fstore_t fst;
978     fst.fst_flags = F_ALLOCATECONTIG;
979     fst.fst_posmode = F_PEOFPOSMODE;
980     fst.fst_offset = 0;
981     fst.fst_length = (off_t)offset + length;
982     fst.fst_bytesalloc = 0;
983     if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
984         fst.fst_flags = F_ALLOCATEALL;
985         fcntl(fileno(file), F_PREALLOCATE, &fst);
986     }
987     ftruncate(fileno(file), fst.fst_length);
988 #elif defined(__linux__)
989     // Version using posix_fallocate
990     off_t nEndPos = (off_t)offset + length;
991     posix_fallocate(fileno(file), 0, nEndPos);
992 #else
993     // Fallback version
994     // TODO: just write one byte per block
995     static const char buf[65536] = {};
996     fseek(file, offset, SEEK_SET);
997     while (length > 0) {
998         unsigned int now = 65536;
999         if (length < now)
1000             now = length;
1001         fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
1002         length -= now;
1003     }
1004 #endif
1005 }
1006
1007 void ShrinkDebugFile()
1008 {
1009     // Scroll debug.log if it's getting too big
1010     boost::filesystem::path pathLog = GetDataDir() / "debug.log";
1011     FILE* file = fopen(pathLog.string().c_str(), "r");
1012     if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000)
1013     {
1014         // Restart the file with some of the end
1015         std::vector <char> vch(200000,0);
1016         fseek(file, -((long)vch.size()), SEEK_END);
1017         int nBytes = fread(begin_ptr(vch), 1, vch.size(), file);
1018         fclose(file);
1019
1020         file = fopen(pathLog.string().c_str(), "w");
1021         if (file)
1022         {
1023             fwrite(begin_ptr(vch), 1, nBytes, file);
1024             fclose(file);
1025         }
1026     }
1027     else if (file != NULL)
1028         fclose(file);
1029 }
1030
1031 #ifdef _WIN32
1032 boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
1033 {
1034     namespace fs = boost::filesystem;
1035
1036     char pszPath[MAX_PATH] = "";
1037
1038     if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
1039     {
1040         return fs::path(pszPath);
1041     }
1042
1043     LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
1044     return fs::path("");
1045 }
1046 #endif
1047
1048 boost::filesystem::path GetTempPath() {
1049 #if BOOST_FILESYSTEM_VERSION == 3
1050     return boost::filesystem::temp_directory_path();
1051 #else
1052     // TODO: remove when we don't support filesystem v2 anymore
1053     boost::filesystem::path path;
1054 #ifdef _WIN32
1055     char pszPath[MAX_PATH] = "";
1056
1057     if (GetTempPathA(MAX_PATH, pszPath))
1058         path = boost::filesystem::path(pszPath);
1059 #else
1060     path = boost::filesystem::path("/tmp");
1061 #endif
1062     if (path.empty() || !boost::filesystem::is_directory(path)) {
1063         LogPrintf("GetTempPath(): failed to find temp path\n");
1064         return boost::filesystem::path("");
1065     }
1066     return path;
1067 #endif
1068 }
1069
1070 void runCommand(const std::string& strCommand)
1071 {
1072     int nErr = ::system(strCommand.c_str());
1073     if (nErr)
1074         LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
1075 }
1076
1077 void RenameThread(const char* name)
1078 {
1079 #if defined(PR_SET_NAME)
1080     // Only the first 15 characters are used (16 - NUL terminator)
1081     ::prctl(PR_SET_NAME, name, 0, 0, 0);
1082 #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
1083     pthread_set_name_np(pthread_self(), name);
1084
1085 #elif defined(MAC_OSX)
1086     pthread_setname_np(name);
1087 #else
1088     // Prevent warnings for unused parameters...
1089     (void)name;
1090 #endif
1091 }
1092
1093 void SetupEnvironment()
1094 {
1095     // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
1096     // may be invalid, in which case the "C" locale is used as fallback.
1097 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
1098     try {
1099         std::locale(""); // Raises a runtime error if current locale is invalid
1100     } catch (const std::runtime_error&) {
1101         setenv("LC_ALL", "C", 1);
1102     }
1103 #endif
1104     // The path locale is lazy initialized and to avoid deinitialization errors
1105     // in multithreading environments, it is set explicitly by the main thread.
1106     // A dummy locale is used to extract the internal default locale, used by
1107     // boost::filesystem::path, which is then used to explicitly imbue the path.
1108     std::locale loc = boost::filesystem::path::imbue(std::locale::classic());
1109     boost::filesystem::path::imbue(loc);
1110 }
1111
1112 bool SetupNetworking()
1113 {
1114 #ifdef _WIN32
1115     // Initialize Windows Sockets
1116     WSADATA wsadata;
1117     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1118     if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
1119         return false;
1120 #endif
1121     return true;
1122 }
1123
1124 void SetThreadPriority(int nPriority)
1125 {
1126 #ifdef _WIN32
1127     SetThreadPriority(GetCurrentThread(), nPriority);
1128 #else // _WIN32
1129 #ifdef PRIO_THREAD
1130     setpriority(PRIO_THREAD, 0, nPriority);
1131 #else // PRIO_THREAD
1132     setpriority(PRIO_PROCESS, 0, nPriority);
1133 #endif // PRIO_THREAD
1134 #endif // _WIN32
1135 }
1136
1137 std::string PrivacyInfo()
1138 {
1139     return "\n" +
1140            FormatParagraph(strprintf(_("In order to ensure you are adequately protecting your privacy when using Zcash, please see <%s>."),
1141                                      "https://z.cash/support/security/")) + "\n";
1142 }
1143
1144 std::string LicenseInfo()
1145 {
1146     return "\n" +
1147            FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" +
1148            FormatParagraph(strprintf(_("Copyright (C) 2015-%i The Zcash Developers"), COPYRIGHT_YEAR)) + "\n" +
1149            FormatParagraph(strprintf(_("Copyright (C) 2015-%i jl777 and SuperNET developers"), COPYRIGHT_YEAR)) + "\n" +
1150            FormatParagraph(strprintf(_("Copyright (C) 2018-%i The Verus developers"), COPYRIGHT_YEAR)) + "\n" +
1151            "\n" +
1152            FormatParagraph(_("This is experimental software.")) + "\n" +
1153            "\n" +
1154            FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or <https://www.opensource.org/licenses/mit-license.php>.")) + "\n" +
1155            "\n" +
1156            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.")) +
1157            "\n";
1158 }
1159
1160 int GetNumCores()
1161 {
1162     return boost::thread::physical_concurrency();
1163 }
1164
This page took 0.087774 seconds and 4 git commands to generate.