Fabcoin Core  0.16.2
P2P Digital Currency
util.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 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)
8 #endif
9 
10 #include <util.h>
11 
12 #include <chainparamsbase.h>
13 #include <fs.h>
14 #include <random.h>
15 #include <serialize.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 #ifdef HAVE_MALLOPT_ARENA_MAX
76 #include <malloc.h>
77 #endif
78 
79 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
80 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
81 #include <boost/program_options/detail/config_file.hpp>
82 #include <boost/thread.hpp>
83 #include <openssl/crypto.h>
84 #include <openssl/rand.h>
85 #include <openssl/conf.h>
86 
87 using namespace std;
88 // Application startup time (used for uptime calculation)
89 const int64_t nStartupTime = GetTime();
90 
91 const char * const FABCOIN_CONF_FILENAME = "fabcoin.conf";
92 const char * const FABCOIN_PID_FILENAME = "fabcoind.pid";
93 
95 bool fPrintToConsole = false;
96 bool fPrintToDebugLog = true;
97 
98 bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
99 bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
100 bool fLogIPs = DEFAULT_LOGIPS;
101 std::atomic<bool> fReopenDebugLog(false);
103 
105 std::atomic<uint32_t> logCategories(0);
106 
108 static std::unique_ptr<CCriticalSection[]> ppmutexOpenSSL;
109 void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
110 {
111  if (mode & CRYPTO_LOCK) {
112  ENTER_CRITICAL_SECTION(ppmutexOpenSSL[i]);
113  } else {
114  LEAVE_CRITICAL_SECTION(ppmutexOpenSSL[i]);
115  }
116 }
117 
118 // Singleton for wrapping OpenSSL setup/teardown.
119 class CInit
120 {
121 public:
123  {
124  // Init OpenSSL library multithreading support
125  ppmutexOpenSSL.reset(new CCriticalSection[CRYPTO_num_locks()]);
126  CRYPTO_set_locking_callback(locking_callback);
127 
128  // OpenSSL can optionally load a config file which lists optional loadable modules and engines.
129  // We don't use them so we don't require the config. However some of our libs may call functions
130  // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing
131  // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
132  // that the config appears to have been loaded and there are no modules/engines available.
133  OPENSSL_no_config();
134 
135 #ifdef WIN32
136  // Seed OpenSSL PRNG with current contents of the screen
137  RAND_screen();
138 #endif
139 
140  // Seed OpenSSL PRNG with performance counter
141  RandAddSeed();
142  }
144  {
145  // Securely erase the memory used by the PRNG
146  RAND_cleanup();
147  // Shutdown OpenSSL library multithreading support
148  CRYPTO_set_locking_callback(nullptr);
149  // Clear the set of locks now to maintain symmetry with the constructor.
150  ppmutexOpenSSL.reset();
151  }
152 }
154 
166 static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
167 
177 static FILE* fileout = nullptr;
178 static boost::mutex* mutexDebugLog = nullptr;
179 static std::list<std::string>* vMsgsBeforeOpenLog;
180 
182 static FILE* fileoutVM = nullptr;
184 
185 
186 static int FileWriteStr(const std::string &str, FILE *fp)
187 {
188  return fwrite(str.data(), 1, str.size(), fp);
189 }
190 
191 static void DebugPrintInit()
192 {
193  assert(mutexDebugLog == nullptr);
194  mutexDebugLog = new boost::mutex();
195  vMsgsBeforeOpenLog = new std::list<std::string>;
196 }
197 
199 {
200  boost::call_once(&DebugPrintInit, debugPrintInitFlag);
201  boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
202 
203  assert(fileout == nullptr);
204  assert(fileoutVM == nullptr); // fasc
205 
206  assert(vMsgsBeforeOpenLog);
207  fs::path pathDebug = GetDataDir() / "debug.log";
208  fs::path pathDebugVM = GetDataDir() / "vm.log"; // fasc
209 
210  fileout = fsbridge::fopen(pathDebug, "a");
211  fileoutVM = fsbridge::fopen(pathDebugVM, "a"); // fasc
212 
213  if (fileout) {
214  setbuf(fileout, nullptr); // unbuffered
215  // dump buffered messages from before we opened the log
216  while (!vMsgsBeforeOpenLog->empty()) {
217  FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
218  vMsgsBeforeOpenLog->pop_front();
219  }
220  }
221 
223  if (fileoutVM) {
224  setbuf(fileoutVM, NULL); // unbuffered
225  // dump buffered messages from before we opened the log
226  while (!vMsgsBeforeOpenLog->empty()) {
227  FileWriteStr(vMsgsBeforeOpenLog->front(), fileoutVM);
228  vMsgsBeforeOpenLog->pop_front();
229  }
230  }
232 
233 
234  delete vMsgsBeforeOpenLog;
235  vMsgsBeforeOpenLog = nullptr;
236 }
237 
239 {
240  uint32_t flag;
241  std::string category;
242 };
243 
245 {
246  {BCLog::NONE, "0"},
247  {BCLog::NET, "net"},
248  {BCLog::TOR, "tor"},
249  {BCLog::MEMPOOL, "mempool"},
250  {BCLog::HTTP, "http"},
251  {BCLog::BENCH, "bench"},
252  {BCLog::ZMQ, "zmq"},
253  {BCLog::DB, "db"},
254  {BCLog::RPC, "rpc"},
255  {BCLog::ESTIMATEFEE, "estimatefee"},
256  {BCLog::ADDRMAN, "addrman"},
257  {BCLog::SELECTCOINS, "selectcoins"},
258  {BCLog::REINDEX, "reindex"},
259  {BCLog::CMPCTBLOCK, "cmpctblock"},
260  {BCLog::RAND, "rand"},
261  {BCLog::PRUNE, "prune"},
262  {BCLog::PROXY, "proxy"},
263  {BCLog::MEMPOOLREJ, "mempoolrej"},
264  {BCLog::LIBEVENT, "libevent"},
265  {BCLog::COINDB, "coindb"},
266  {BCLog::QT, "qt"},
267  {BCLog::LEVELDB, "leveldb"},
268  {BCLog::POW, "pow"},
269  {BCLog::HTTPPOLL, "http-poll"},
270  {BCLog::ALL, "1"},
271  {BCLog::ALL, "all"},
272 };
273 
274 bool GetLogCategory(uint32_t *f, const std::string *str)
275 {
276  if (f && str) {
277  if (*str == "") {
278  *f = BCLog::ALL;
279  return true;
280  }
281  for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) {
282  if (LogCategories[i].category == *str) {
283  *f = LogCategories[i].flag;
284  return true;
285  }
286  }
287  }
288  return false;
289 }
290 
291 std::string ListLogCategories()
292 {
293  std::string ret;
294  int outcount = 0;
295  for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) {
296  // Omit the special cases.
297  if (LogCategories[i].flag != BCLog::NONE && LogCategories[i].flag != BCLog::ALL) {
298  if (outcount != 0) ret += ", ";
299  ret += LogCategories[i].category;
300  outcount++;
301  }
302  }
303  return ret;
304 }
305 
306 std::vector<CLogCategoryActive> ListActiveLogCategories()
307 {
308  std::vector<CLogCategoryActive> ret;
309  for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) {
310  // Omit the special cases.
311  if (LogCategories[i].flag != BCLog::NONE && LogCategories[i].flag != BCLog::ALL) {
312  CLogCategoryActive catActive;
313  catActive.category = LogCategories[i].category;
314  catActive.active = LogAcceptCategory(LogCategories[i].flag);
315  ret.push_back(catActive);
316  }
317  }
318  return ret;
319 }
320 
321 bool LogAcceptCategoryChar(const char* category)
322 {
323  /*
324  if (category != NULL)
325  {
326  if (!fDebug)
327  return false;
328 
329  // Give each thread quick access to -debug settings.
330  // This helps prevent issues debugging global destructors,
331  // where mapMultiArgs might be deleted before another
332  // global destructor calls LogPrint()
333  static boost::thread_specific_ptr<set<string> > ptrCategory;
334  if (ptrCategory.get() == NULL)
335  {
336  if (mapMultiArgs.count("-debug")) {
337  const vector<string>& categories = mapMultiArgs.at("-debug");
338  ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
339  // thread_specific_ptr automatically deletes the set when the thread ends.
340  } else
341  ptrCategory.reset(new set<string>());
342  }
343  const set<string>& setCategories = *ptrCategory.get();
344 
345  // if not debugging everything and not debugging specific category, LogPrint does nothing.
346  if (setCategories.count(string("")) == 0 &&
347  setCategories.count(string("1")) == 0 &&
348  setCategories.count(string(category)) == 0)
349  return false;
350  }
351  */
352  return true;
353 }
354 
360 static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fStartedNewLine)
361 {
362  std::string strStamped;
363 
364  if (!fLogTimestamps)
365  return str;
366 
367  if (*fStartedNewLine) {
368  int64_t nTimeMicros = GetTimeMicros();
369  strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nTimeMicros/1000000);
370  if (fLogTimeMicros)
371  strStamped += strprintf(".%06d", nTimeMicros%1000000);
372  int64_t mocktime = GetMockTime();
373  if (mocktime) {
374  strStamped += " (mocktime: " + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", mocktime) + ")";
375  }
376  strStamped += ' ' + str;
377  } else
378  strStamped = str;
379 
380  if (!str.empty() && str[str.size()-1] == '\n')
381  *fStartedNewLine = true;
382  else
383  *fStartedNewLine = false;
384 
385  return strStamped;
386 }
387 
388 int LogPrintStr(const std::string &str, bool useVMLog)
389 {
390 
392  FILE* file = fileout;
393  if(useVMLog){
394  file = fileoutVM;
395  }
397 
398  int ret = 0; // Returns total number of characters written
399  static std::atomic_bool fStartedNewLine(true);
400 
401  std::string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
402 
403  if (fPrintToConsole)
404  {
405  // print to console
406  ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
407  fflush(stdout);
408  }
409  else if (fPrintToDebugLog)
410  {
411  boost::call_once(&DebugPrintInit, debugPrintInitFlag);
412  boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
413 
414  // buffer if we haven't opened the log yet
415  if (file == nullptr) {
416  assert(vMsgsBeforeOpenLog);
417  ret = strTimestamped.length();
418  vMsgsBeforeOpenLog->push_back(strTimestamped);
419  }
420  else
421  {
422  // reopen the log file, if requested
423  if (fReopenDebugLog) {
424  fReopenDebugLog = false;
425  fs::path pathDebug = GetDataDir() / "debug.log";
426  if (fsbridge::freopen(pathDebug,"a",file) != nullptr)
427  setbuf(file, nullptr); // unbuffered
428  }
429 
430  ret = FileWriteStr(strTimestamped, file);
431  }
432  }
433  return ret;
434 }
435 
437 static bool InterpretBool(const std::string& strValue)
438 {
439  if (strValue.empty())
440  return true;
441  return (atoi(strValue) != 0);
442 }
443 
445 static void InterpretNegativeSetting(std::string& strKey, std::string& strValue)
446 {
447  if (strKey.length()>3 && strKey[0]=='-' && strKey[1]=='n' && strKey[2]=='o')
448  {
449  strKey = "-" + strKey.substr(3);
450  strValue = InterpretBool(strValue) ? "0" : "1";
451  }
452 }
453 
454 void ArgsManager::ParseParameters(int argc, const char* const argv[])
455 {
456  LOCK(cs_args);
457  mapArgs.clear();
458  mapMultiArgs.clear();
459 
460  for (int i = 1; i < argc; i++)
461  {
462  std::string str(argv[i]);
463  std::string strValue;
464  size_t is_index = str.find('=');
465  if (is_index != std::string::npos)
466  {
467  strValue = str.substr(is_index+1);
468  str = str.substr(0, is_index);
469  }
470 #ifdef WIN32
471  boost::to_lower(str);
472  if (boost::algorithm::starts_with(str, "/"))
473  str = "-" + str.substr(1);
474 #endif
475 
476  if (str[0] != '-')
477  break;
478 
479  // Interpret --foo as -foo.
480  // If both --foo and -foo are set, the last takes effect.
481  if (str.length() > 1 && str[1] == '-')
482  str = str.substr(1);
483  InterpretNegativeSetting(str, strValue);
484 
485  mapArgs[str] = strValue;
486  mapMultiArgs[str].push_back(strValue);
487  }
488 }
489 
490 std::vector<std::string> ArgsManager::GetArgs(const std::string& strArg)
491 {
492  LOCK(cs_args);
493  if (IsArgSet(strArg))
494  return mapMultiArgs.at(strArg);
495  return {};
496 }
497 
498 bool ArgsManager::IsArgSet(const std::string& strArg)
499 {
500  LOCK(cs_args);
501  return mapArgs.count(strArg);
502 }
503 
504 std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault)
505 {
506  LOCK(cs_args);
507  if (mapArgs.count(strArg))
508  return mapArgs[strArg];
509  return strDefault;
510 }
511 
512 int64_t ArgsManager::GetArg(const std::string& strArg, int64_t nDefault)
513 {
514  LOCK(cs_args);
515  if (mapArgs.count(strArg))
516  return atoi64(mapArgs[strArg]);
517  return nDefault;
518 }
519 
520 bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault)
521 {
522  LOCK(cs_args);
523  if (mapArgs.count(strArg))
524  return InterpretBool(mapArgs[strArg]);
525  return fDefault;
526 }
527 
528 bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strValue)
529 {
530  LOCK(cs_args);
531  if (mapArgs.count(strArg))
532  return false;
533  ForceSetArg(strArg, strValue);
534  return true;
535 }
536 
537 bool ArgsManager::SoftSetBoolArg(const std::string& strArg, bool fValue)
538 {
539  if (fValue)
540  return SoftSetArg(strArg, std::string("1"));
541  else
542  return SoftSetArg(strArg, std::string("0"));
543 }
544 
545 void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strValue)
546 {
547  LOCK(cs_args);
548  mapArgs[strArg] = strValue;
549  mapMultiArgs[strArg].clear();
550  mapMultiArgs[strArg].push_back(strValue);
551 }
552 
553 
554 
555 static const int screenWidth = 79;
556 static const int optIndent = 2;
557 static const int msgIndent = 7;
558 
559 std::string HelpMessageGroup(const std::string &message) {
560  return std::string(message) + std::string("\n\n");
561 }
562 
563 std::string HelpMessageOpt(const std::string &option, const std::string &message) {
564  return std::string(optIndent,' ') + std::string(option) +
565  std::string("\n") + std::string(msgIndent,' ') +
566  FormatParagraph(message, screenWidth - msgIndent, msgIndent) +
567  std::string("\n\n");
568 }
569 
570 static std::string FormatException(const std::exception* pex, const char* pszThread)
571 {
572 #ifdef WIN32
573  char pszModule[MAX_PATH] = "";
574  GetModuleFileNameA(nullptr, pszModule, sizeof(pszModule));
575 #else
576  const char* pszModule = "fabcoin";
577 #endif
578  if (pex)
579  return strprintf(
580  "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
581  else
582  return strprintf(
583  "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
584 }
585 
586 void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
587 {
588  std::string message = FormatException(pex, pszThread);
589  LogPrintf("\n\n************************\n%s\n", message);
590  fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
591 }
592 
594 {
595  // Windows < Vista: C:\Documents and Settings\Username\Application Data\Fabcoin
596  // Windows >= Vista: C:\Users\Username\AppData\Roaming\Fabcoin
597  // Mac: ~/Library/Application Support/Fabcoin
598  // Unix: ~/.fabcoin
599 #ifdef WIN32
600  // Windows
601  return GetSpecialFolderPath(CSIDL_APPDATA) / "Fabcoinsc";
602 #else
603  fs::path pathRet;
604  char* pszHome = getenv("HOME");
605  if (pszHome == nullptr || strlen(pszHome) == 0)
606  pathRet = fs::path("/");
607  else
608  pathRet = fs::path(pszHome);
609 #ifdef MAC_OSX
610  // Mac
611  return pathRet / "Library/Application Support/Fabcoinsc";
612 #else
613  // Unix
614  return pathRet / ".fabcoinsc";
615 #endif
616 #endif
617 }
618 
619 static fs::path pathCached;
620 static fs::path pathCachedNetSpecific;
621 static CCriticalSection csPathCached;
622 
623 const fs::path &GetDataDir(bool fNetSpecific)
624 {
625 
626  LOCK(csPathCached);
627 
628  fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
629 
630  // This can be called during exceptions by LogPrintf(), so we cache the
631  // value so we don't have to do memory allocations after that.
632  if (!path.empty())
633  return path;
634 
635  if (gArgs.IsArgSet("-datadir")) {
636  path = fs::system_complete(gArgs.GetArg("-datadir", ""));
637  if (!fs::is_directory(path)) {
638  path = "";
639  return path;
640  }
641  } else {
642  path = GetDefaultDataDir();
643  }
644  if (fNetSpecific)
645  path /= BaseParams().DataDir();
646 
647  fs::create_directories(path);
648 
649  return path;
650 }
651 
653 {
654  LOCK(csPathCached);
655 
656  pathCached = fs::path();
657  pathCachedNetSpecific = fs::path();
658 }
659 
660 fs::path GetConfigFile(const std::string& confPath)
661 {
662  fs::path pathConfigFile(confPath);
663  if (!pathConfigFile.is_complete())
664  pathConfigFile = GetDataDir(false) / pathConfigFile;
665 
666  return pathConfigFile;
667 }
668 
669 void ArgsManager::ReadConfigFile(const std::string& confPath)
670 {
671  fs::ifstream streamConfig(GetConfigFile(confPath));
672  if (!streamConfig.good())
673  return; // No fabcoin.conf file is OK
674 
675  {
676  LOCK(cs_args);
677  std::set<std::string> setOptions;
678  setOptions.insert("*");
679 
680  for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
681  {
682  // Don't overwrite existing settings so command line settings override fabcoin.conf
683  std::string strKey = std::string("-") + it->string_key;
684  std::string strValue = it->value[0];
685  InterpretNegativeSetting(strKey, strValue);
686  if (mapArgs.count(strKey) == 0)
687  mapArgs[strKey] = strValue;
688  mapMultiArgs[strKey].push_back(strValue);
689  }
690  }
691  // If datadir is changed in .conf file:
693 }
694 
695 #ifndef WIN32
696 fs::path GetPidFile()
697 {
698  fs::path pathPidFile(gArgs.GetArg("-pid", FABCOIN_PID_FILENAME));
699  if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
700  return pathPidFile;
701 }
702 
703 void CreatePidFile(const fs::path &path, pid_t pid)
704 {
705  FILE* file = fsbridge::fopen(path, "w");
706  if (file)
707  {
708  fprintf(file, "%d\n", pid);
709  fclose(file);
710  }
711 }
712 #endif
713 
714 bool RenameOver(fs::path src, fs::path dest)
715 {
716 #ifdef WIN32
717  return MoveFileExA(src.string().c_str(), dest.string().c_str(),
718  MOVEFILE_REPLACE_EXISTING) != 0;
719 #else
720  int rc = std::rename(src.string().c_str(), dest.string().c_str());
721  return (rc == 0);
722 #endif /* WIN32 */
723 }
724 
730 bool TryCreateDirectories(const fs::path& p)
731 {
732  try
733  {
734  return fs::create_directories(p);
735  } catch (const fs::filesystem_error&) {
736  if (!fs::exists(p) || !fs::is_directory(p))
737  throw;
738  }
739 
740  // create_directories didn't create the directory, it had to have existed already
741  return false;
742 }
743 
744 void FileCommit(FILE *file)
745 {
746  fflush(file); // harmless if redundantly called
747 #ifdef WIN32
748  HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
749  FlushFileBuffers(hFile);
750 #else
751  #if defined(__linux__) || defined(__NetBSD__)
752  fdatasync(fileno(file));
753  #elif defined(__APPLE__) && defined(F_FULLFSYNC)
754  fcntl(fileno(file), F_FULLFSYNC, 0);
755  #else
756  fsync(fileno(file));
757  #endif
758 #endif
759 }
760 
761 bool TruncateFile(FILE *file, unsigned int length) {
762 #if defined(WIN32)
763  return _chsize(_fileno(file), length) == 0;
764 #else
765  return ftruncate(fileno(file), length) == 0;
766 #endif
767 }
768 
773 int RaiseFileDescriptorLimit(int nMinFD) {
774 #if defined(WIN32)
775  return 2048;
776 #else
777  struct rlimit limitFD;
778  if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
779  if (limitFD.rlim_cur < (rlim_t)nMinFD) {
780  limitFD.rlim_cur = nMinFD;
781  if (limitFD.rlim_cur > limitFD.rlim_max)
782  limitFD.rlim_cur = limitFD.rlim_max;
783  setrlimit(RLIMIT_NOFILE, &limitFD);
784  getrlimit(RLIMIT_NOFILE, &limitFD);
785  }
786  return limitFD.rlim_cur;
787  }
788  return nMinFD; // getrlimit failed, assume it's fine
789 #endif
790 }
791 
796 void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
797 #if defined(WIN32)
798  // Windows-specific version
799  HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
800  LARGE_INTEGER nFileSize;
801  int64_t nEndPos = (int64_t)offset + length;
802  nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
803  nFileSize.u.HighPart = nEndPos >> 32;
804  SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
805  SetEndOfFile(hFile);
806 #elif defined(MAC_OSX)
807  // OSX specific version
808  fstore_t fst;
809  fst.fst_flags = F_ALLOCATECONTIG;
810  fst.fst_posmode = F_PEOFPOSMODE;
811  fst.fst_offset = 0;
812  fst.fst_length = (off_t)offset + length;
813  fst.fst_bytesalloc = 0;
814  if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
815  fst.fst_flags = F_ALLOCATEALL;
816  fcntl(fileno(file), F_PREALLOCATE, &fst);
817  }
818  ftruncate(fileno(file), fst.fst_length);
819 #elif defined(__linux__)
820  // Version using posix_fallocate
821  off_t nEndPos = (off_t)offset + length;
822  posix_fallocate(fileno(file), 0, nEndPos);
823 #else
824  // Fallback version
825  // TODO: just write one byte per block
826  static const char buf[65536] = {};
827  fseek(file, offset, SEEK_SET);
828  while (length > 0) {
829  unsigned int now = 65536;
830  if (length < now)
831  now = length;
832  fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
833  length -= now;
834  }
835 #endif
836 }
837 
839 {
840  // Amount of debug.log to save at end when shrinking (must fit in memory)
841  constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
842  // Scroll debug.log if it's getting too big
843  fs::path pathLog = GetDataDir() / "debug.log";
844  FILE* file = fsbridge::fopen(pathLog, "r");
845  // If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE
846  // trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes
847  if (file && fs::file_size(pathLog) > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10))
848  {
849  // Restart the file with some of the end
850  std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
851  fseek(file, -((long)vch.size()), SEEK_END);
852  int nBytes = fread(vch.data(), 1, vch.size(), file);
853  fclose(file);
854 
855  file = fsbridge::fopen(pathLog, "w");
856  if (file)
857  {
858  fwrite(vch.data(), 1, nBytes, file);
859  fclose(file);
860  }
861  }
862  else if (file != nullptr)
863  fclose(file);
864 }
865 
866 #ifdef WIN32
867 fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
868 {
869  char pszPath[MAX_PATH] = "";
870 
871  if(SHGetSpecialFolderPathA(nullptr, pszPath, nFolder, fCreate))
872  {
873  return fs::path(pszPath);
874  }
875 
876  LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
877  return fs::path("");
878 }
879 #endif
880 
881 void runCommand(const std::string& strCommand)
882 {
883  int nErr = ::system(strCommand.c_str());
884  if (nErr)
885  LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
886 }
887 
888 void RenameThread(const char* name)
889 {
890 #if defined(PR_SET_NAME)
891  // Only the first 15 characters are used (16 - NUL terminator)
892  ::prctl(PR_SET_NAME, name, 0, 0, 0);
893 #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
894  pthread_set_name_np(pthread_self(), name);
895 
896 #elif defined(MAC_OSX)
897  pthread_setname_np(name);
898 #else
899  // Prevent warnings for unused parameters...
900  (void)name;
901 #endif
902 }
903 
905 {
906 #ifdef HAVE_MALLOPT_ARENA_MAX
907  // glibc-specific: On 32-bit systems set the number of arenas to 1.
908  // By default, since glibc 2.10, the C library will create up to two heap
909  // arenas per core. This is known to cause excessive virtual address space
910  // usage in our usage. Work around it by setting the maximum number of
911  // arenas to 1.
912  if (sizeof(void*) == 4) {
913  mallopt(M_ARENA_MAX, 1);
914  }
915 #endif
916  // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
917  // may be invalid, in which case the "C" locale is used as fallback.
918 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
919  try {
920  std::locale(""); // Raises a runtime error if current locale is invalid
921  } catch (const std::runtime_error&) {
922  setenv("LC_ALL", "C", 1);
923  }
924 #endif
925  // The path locale is lazy initialized and to avoid deinitialization errors
926  // in multithreading environments, it is set explicitly by the main thread.
927  // A dummy locale is used to extract the internal default locale, used by
928  // fs::path, which is then used to explicitly imbue the path.
929  std::locale loc = fs::path::imbue(std::locale::classic());
930  fs::path::imbue(loc);
931 }
932 
934 {
935 #ifdef WIN32
936  // Initialize Windows Sockets
937  WSADATA wsadata;
938  int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
939  if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
940  return false;
941 #endif
942  return true;
943 }
944 
945 void SetThreadPriority(int nPriority)
946 {
947 #ifdef WIN32
948  SetThreadPriority(GetCurrentThread(), nPriority);
949 #else // WIN32
950 #ifdef PRIO_THREAD
951  setpriority(PRIO_THREAD, 0, nPriority);
952 #else // PRIO_THREAD
953  setpriority(PRIO_PROCESS, 0, nPriority);
954 #endif // PRIO_THREAD
955 #endif // WIN32
956 }
957 
958 
960 {
961 #if BOOST_VERSION >= 105600
962  return boost::thread::physical_concurrency();
963 #else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores
964  return boost::thread::hardware_concurrency();
965 #endif
966 }
967 
968 std::string CopyrightHolders(const std::string& strPrefix)
969 {
970  std::string strCopyrightHolders = strPrefix + strprintf(_(COPYRIGHT_HOLDERS), _(COPYRIGHT_HOLDERS_SUBSTITUTION));
971 
972  // Check for untranslated substitution to make sure Fabcoin Core copyright is not removed by accident
973  if (strprintf(COPYRIGHT_HOLDERS, COPYRIGHT_HOLDERS_SUBSTITUTION).find("Fabcoin Core") == std::string::npos) {
974  strCopyrightHolders += "\n" + strPrefix + "The Bitcoin Core developers";
975  }
976  return strCopyrightHolders;
977 }
978 
979 // Obtain the application startup time (used for uptime calculation)
980 int64_t GetStartupTime()
981 {
982  return nStartupTime;
983 }
984 
985 bool CheckHex(const std::string& str) {
986  size_t data=0;
987  if(str.size() > 2 && (str.compare(0, 2, "0x") == 0 || str.compare(0, 2, "0X") == 0)){
988  data=2;
989  }
990  return str.size() > data && str.find_first_not_of("0123456789abcdefABCDEF", data) == std::string::npos;
991 }
992 
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
Definition: util.cpp:563
#define NO_THREAD_SAFETY_ANALYSIS
Definition: threadsafety.h:52
std::string ListLogCategories()
Returns a string with the log categories.
Definition: util.cpp:291
const int64_t nStartupTime
Definition: util.cpp:89
bool SetupNetworking()
Definition: util.cpp:933
FILE * freopen(const fs::path &p, const char *mode, FILE *stream)
Definition: fs.cpp:10
void ParseParameters(int argc, const char *const argv[])
Definition: util.cpp:454
void SetThreadPriority(int nPriority)
Definition: util.cpp:945
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:5
bool IsArgSet(const std::string &strArg)
Return true if the given argument has been manually set.
Definition: util.cpp:498
void FileCommit(FILE *file)
Definition: util.cpp:744
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn&#39;t already have a value.
Definition: util.cpp:537
Definition: util.h:95
#define strprintf
Definition: tinyformat.h:1054
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)
Definition: utiltime.cpp:78
int64_t GetStartupTime()
Server/client environment: argument handling, config file parsing, logging, thread wrappers...
Definition: util.cpp:980
#define COPYRIGHT_HOLDERS
#define MAX_PATH
Definition: compat.h:72
evm_mode mode
Definition: SmartVM.cpp:47
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
Definition: util.cpp:119
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
Definition: util.cpp:520
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
Definition: util.cpp:586
std::hash for asio::adress
Definition: Common.h:323
std::vector< std::string > GetArgs(const std::string &strArg)
Definition: util.cpp:490
assert(len-trim+(2 *lenIndices)<=WIDTH)
int64_t GetTimeMicros()
Definition: utiltime.cpp:47
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: util.cpp:545
void locking_callback(int mode, int i, const char *file, int line) NO_THREAD_SAFETY_ANALYSIS
Definition: util.cpp:109
void ReadConfigFile(const std::string &confPath)
Definition: util.cpp:669
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn&#39;t already have a value.
Definition: util.cpp:528
void RenameThread(const char *name)
Definition: util.cpp:888
int RaiseFileDescriptorLimit(int nMinFD)
this function tries to raise the file descriptor limit to the requested number.
Definition: util.cpp:773
class CInit instance_of_cinit
CTranslationInterface translationInterface
Definition: util.cpp:102
const char *const FABCOIN_PID_FILENAME
Definition: util.cpp:92
bool TruncateFile(FILE *file, unsigned int length)
Definition: util.cpp:761
std::string category
Definition: util.cpp:241
#define LogPrintf(...)
Definition: util.h:153
uint32_t flag
Definition: util.cpp:240
#define LEAVE_CRITICAL_SECTION(cs)
Definition: sync.h:185
const char *const FABCOIN_CONF_FILENAME
Definition: util.cpp:91
#define LOCK(cs)
Definition: sync.h:175
const char * name
Definition: rest.cpp:36
fs::path GetPidFile()
Definition: util.cpp:696
bool fLogTimeMicros
Definition: util.cpp:99
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by Boost&#39;s create_directories if the requested directory exists...
Definition: util.cpp:730
~CInit()
Definition: util.cpp:143
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length)
this function tries to make a particular range of a file allocated (corresponding to disk space) it i...
Definition: util.cpp:796
std::string FormatParagraph(const std::string &in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line...
bool RenameOver(fs::path src, fs::path dest)
Definition: util.cpp:714
std::string CopyrightHolders(const std::string &strPrefix)
Definition: util.cpp:968
fs::path GetDefaultDataDir()
Definition: util.cpp:593
bool fLogTimestamps
Definition: util.cpp:98
bool CheckHex(const std::string &str)
Definition: util.cpp:985
#define ENTER_CRITICAL_SECTION(cs)
Definition: sync.h:179
bool fLogIPs
Definition: util.cpp:100
#define f(x)
Definition: gost.cpp:57
ArgsManager gArgs
Definition: util.cpp:94
bool fPrintToConsole
Definition: util.cpp:95
#define COPYRIGHT_HOLDERS_SUBSTITUTION
#define ARRAYLEN(array)
void OpenDebugLog()
Definition: util.cpp:198
fs::path GetConfigFile(const std::string &confPath)
Definition: util.cpp:660
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
Definition: util.cpp:504
bool fPrintToDebugLog
Definition: util.cpp:96
void runCommand(const std::string &strCommand)
Definition: util.cpp:881
std::atomic< uint32_t > logCategories(0)
Log categories bitfield.
Signals for translation.
Definition: util.h:46
void ClearDatadirCache()
Definition: util.cpp:652
std::string category
Definition: util.h:82
std::atomic< bool > fReopenDebugLog(false)
int64_t atoi64(const char *psz)
CInit()
Definition: util.cpp:122
int LogPrintStr(const std::string &str, bool useVMLog)
Send a string to the log output.
Definition: util.cpp:388
void RandAddSeed()
Definition: random.cpp:130
const fs::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:623
void CreatePidFile(const fs::path &path, pid_t pid)
Definition: util.cpp:703
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
Definition: utiltime.cpp:19
int GetNumCores()
Return the number of physical cores available on the current system.
Definition: util.cpp:959
int64_t GetMockTime()
Definition: utiltime.cpp:34
void SetupEnvironment()
Definition: util.cpp:904
bool LogAcceptCategoryChar(const char *category)
Return true if log accepts specified category.
Definition: util.cpp:321
bool GetLogCategory(uint32_t *f, const std::string *str)
Return true if str parses as a log category and set the flags in f.
Definition: util.cpp:274
uint8_t const * data
Definition: sha3.h:19
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
Definition: util.cpp:559
const std::string & DataDir() const
std::vector< CLogCategoryActive > ListActiveLogCategories()
Returns a vector of the active log categories.
Definition: util.cpp:306
void ShrinkDebugFile()
Definition: util.cpp:838
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
Definition: util.h:71
const CLogCategoryDesc LogCategories[]
Definition: util.cpp:244
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
Definition: sync.h:91
int atoi(const std::string &str)