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