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