Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin Core developers
3 : // Distributed under the MIT software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #if defined(HAVE_CONFIG_H)
7 : #include "config/bitcoin-config.h"
8 : #endif
9 :
10 : #include "util.h"
11 :
12 : #include "chainparamsbase.h"
13 : #include "random.h"
14 : #include "serialize.h"
15 : #include "sync.h"
16 : #include "utilstrencodings.h"
17 : #include "utiltime.h"
18 :
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 : #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>
83 : #include <boost/thread.hpp>
84 : #include <openssl/crypto.h>
85 : #include <openssl/rand.h>
86 : #include <openssl/conf.h>
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
92 : namespace boost {
93 :
94 : namespace program_options {
95 : std::string to_internal(const std::string&);
96 : }
97 :
98 : } // namespace boost
99 :
100 : using namespace std;
101 :
102 203 : map<string, string> mapArgs;
103 203 : map<string, vector<string> > mapMultiArgs;
104 : bool fDebug = false;
105 : bool fPrintToConsole = false;
106 : bool fPrintToDebugLog = true;
107 : bool fDaemon = false;
108 : bool fServer = false;
109 203 : string strMiscWarning;
110 : bool fLogTimestamps = false;
111 : bool fLogIPs = false;
112 : volatile bool fReopenDebugLog = false;
113 203 : CTranslationInterface translationInterface;
114 :
115 : /** Init OpenSSL library multithreading support */
116 : static CCriticalSection** ppmutexOpenSSL;
117 3407602 : void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
118 : {
119 3407602 : if (mode & CRYPTO_LOCK) {
120 1703801 : ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
121 : } else {
122 1703801 : LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
123 : }
124 3407603 : }
125 :
126 : // Init
127 : class CInit
128 : {
129 : public:
130 203 : CInit()
131 : {
132 : // Init OpenSSL library multithreading support
133 203 : ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*));
134 8526 : for (int i = 0; i < CRYPTO_num_locks(); i++)
135 16646 : ppmutexOpenSSL[i] = new CCriticalSection();
136 203 : CRYPTO_set_locking_callback(locking_callback);
137 :
138 : // OpenSSL can optionally load a config file which lists optional loadable modules and engines.
139 : // We don't use them so we don't require the config. However some of our libs may call functions
140 : // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing
141 : // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
142 : // that the config appears to have been loaded and there are no modules/engines available.
143 203 : OPENSSL_no_config();
144 :
145 : #ifdef WIN32
146 : // Seed OpenSSL PRNG with current contents of the screen
147 : RAND_screen();
148 : #endif
149 :
150 : // Seed OpenSSL PRNG with performance counter
151 203 : RandAddSeed();
152 203 : }
153 203 : ~CInit()
154 : {
155 : // Securely erase the memory used by the PRNG
156 203 : RAND_cleanup();
157 : // Shutdown OpenSSL library multithreading support
158 203 : CRYPTO_set_locking_callback(NULL);
159 8323 : for (int i = 0; i < CRYPTO_num_locks(); i++)
160 16646 : delete ppmutexOpenSSL[i];
161 203 : OPENSSL_free(ppmutexOpenSSL);
162 203 : }
163 : }
164 203 : instance_of_cinit;
165 :
166 : /**
167 : * LogPrintf() has been broken a couple of times now
168 : * by well-meaning people adding mutexes in the most straightforward way.
169 : * It breaks because it may be called by global destructors during shutdown.
170 : * Since the order of destruction of static/global objects is undefined,
171 : * defining a mutex as a global object doesn't work (the mutex gets
172 : * destroyed, and then some later destructor calls OutputDebugStringF,
173 : * maybe indirectly, and you get a core dump at shutdown trying to lock
174 : * the mutex).
175 : */
176 :
177 : static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
178 :
179 : /**
180 : * We use boost::call_once() to make sure mutexDebugLog and
181 : * vMsgsBeforeOpenLog are initialized in a thread-safe manner.
182 : *
183 : * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
184 : * are leaked on exit. This is ugly, but will be cleaned up by
185 : * the OS/libc. When the shutdown sequence is fully audited and
186 : * tested, explicit destruction of these objects can be implemented.
187 : */
188 : static FILE* fileout = NULL;
189 : static boost::mutex* mutexDebugLog = NULL;
190 : static list<string> *vMsgsBeforeOpenLog;
191 :
192 : static int FileWriteStr(const std::string &str, FILE *fp)
193 : {
194 46018 : return fwrite(str.data(), 1, str.size(), fp);
195 : }
196 :
197 94 : static void DebugPrintInit()
198 : {
199 94 : assert(mutexDebugLog == NULL);
200 94 : mutexDebugLog = new boost::mutex();
201 188 : vMsgsBeforeOpenLog = new list<string>;
202 94 : }
203 :
204 94 : void OpenDebugLog()
205 : {
206 : boost::call_once(&DebugPrintInit, debugPrintInitFlag);
207 94 : boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
208 :
209 94 : assert(fileout == NULL);
210 94 : assert(vMsgsBeforeOpenLog);
211 188 : boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
212 188 : fileout = fopen(pathDebug.string().c_str(), "a");
213 94 : if (fileout) setbuf(fileout, NULL); // unbuffered
214 :
215 : // dump buffered messages from before we opened the log
216 594 : while (!vMsgsBeforeOpenLog->empty()) {
217 406 : FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
218 203 : vMsgsBeforeOpenLog->pop_front();
219 : }
220 :
221 188 : delete vMsgsBeforeOpenLog;
222 94 : vMsgsBeforeOpenLog = NULL;
223 94 : }
224 :
225 292817 : bool LogAcceptCategory(const char* category)
226 : {
227 292817 : if (category != NULL)
228 : {
229 271412 : if (!fDebug)
230 : return false;
231 :
232 : // Give each thread quick access to -debug settings.
233 : // This helps prevent issues debugging global destructors,
234 : // where mapMultiArgs might be deleted before another
235 : // global destructor calls LogPrint()
236 25126 : static boost::thread_specific_ptr<set<string> > ptrCategory;
237 25126 : if (ptrCategory.get() == NULL)
238 : {
239 327 : const vector<string>& categories = mapMultiArgs["-debug"];
240 327 : ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
241 : // thread_specific_ptr automatically deletes the set when the thread ends.
242 : }
243 25126 : const set<string>& setCategories = *ptrCategory.get();
244 :
245 : // if not debugging everything and not debugging specific category, LogPrint does nothing.
246 78656 : if (setCategories.count(string("")) == 0 &&
247 81934 : setCategories.count(string("1")) == 0 &&
248 30043 : setCategories.count(string(category)) == 0)
249 : return false;
250 : }
251 : return true;
252 : }
253 :
254 : /**
255 : * fStartedNewLine is a state variable held by the calling context that will
256 : * suppress printing of the timestamp when multiple calls are made that don't
257 : * end in a newline. Initialize it to true, and hold it, in the calling context.
258 : */
259 46888 : static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
260 : {
261 : string strStamped;
262 :
263 46888 : if (!fLogTimestamps)
264 870 : return str;
265 :
266 46018 : if (*fStartedNewLine)
267 174331 : strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
268 : else
269 : strStamped = str;
270 :
271 91942 : if (!str.empty() && str[str.size()-1] == '\n')
272 43583 : *fStartedNewLine = true;
273 : else
274 2435 : *fStartedNewLine = false;
275 :
276 46018 : return strStamped;
277 : }
278 :
279 46888 : int LogPrintStr(const std::string &str)
280 : {
281 46888 : int ret = 0; // Returns total number of characters written
282 : static bool fStartedNewLine = true;
283 :
284 46888 : string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
285 :
286 46888 : if (fPrintToConsole)
287 : {
288 : // print to console
289 0 : ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
290 0 : fflush(stdout);
291 : }
292 46888 : else if (fPrintToDebugLog)
293 : {
294 : boost::call_once(&DebugPrintInit, debugPrintInitFlag);
295 46017 : boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
296 :
297 : // buffer if we haven't opened the log yet
298 46018 : if (fileout == NULL) {
299 203 : assert(vMsgsBeforeOpenLog);
300 203 : ret = strTimestamped.length();
301 203 : vMsgsBeforeOpenLog->push_back(strTimestamped);
302 : }
303 : else
304 : {
305 : // reopen the log file, if requested
306 45815 : if (fReopenDebugLog) {
307 0 : fReopenDebugLog = false;
308 0 : boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
309 0 : if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
310 0 : setbuf(fileout, NULL); // unbuffered
311 : }
312 :
313 91630 : ret = FileWriteStr(strTimestamped, fileout);
314 : }
315 : }
316 93776 : return ret;
317 : }
318 :
319 : /** Interpret string as boolean, for argument parsing */
320 : static bool InterpretBool(const std::string& strValue)
321 : {
322 668 : if (strValue.empty())
323 : return true;
324 446 : return (atoi(strValue) != 0);
325 : }
326 :
327 : /** Turn -noX into -X=0 */
328 1601 : static void InterpretNegativeSetting(std::string& strKey, std::string& strValue)
329 : {
330 4799 : if (strKey.length()>3 && strKey[0]=='-' && strKey[1]=='n' && strKey[2]=='o')
331 : {
332 36 : strKey = "-" + strKey.substr(3);
333 12 : strValue = InterpretBool(strValue) ? "0" : "1";
334 : }
335 1601 : }
336 :
337 230 : void ParseParameters(int argc, const char* const argv[])
338 : {
339 : mapArgs.clear();
340 : mapMultiArgs.clear();
341 :
342 901 : for (int i = 1; i < argc; i++)
343 : {
344 1552 : std::string str(argv[i]);
345 : std::string strValue;
346 776 : size_t is_index = str.find('=');
347 776 : if (is_index != std::string::npos)
348 : {
349 900 : strValue = str.substr(is_index+1);
350 900 : str = str.substr(0, is_index);
351 : }
352 : #ifdef WIN32
353 : boost::to_lower(str);
354 : if (boost::algorithm::starts_with(str, "/"))
355 : str = "-" + str.substr(1);
356 : #endif
357 :
358 776 : if (str[0] != '-')
359 : break;
360 :
361 : // Interpret --foo as -foo.
362 : // If both --foo and -foo are set, the last takes effect.
363 1336 : if (str.length() > 1 && str[1] == '-')
364 12 : str = str.substr(1);
365 671 : InterpretNegativeSetting(str, strValue);
366 :
367 671 : mapArgs[str] = strValue;
368 671 : mapMultiArgs[str].push_back(strValue);
369 : }
370 230 : }
371 :
372 5077 : std::string GetArg(const std::string& strArg, const std::string& strDefault)
373 : {
374 5077 : if (mapArgs.count(strArg))
375 23 : return mapArgs[strArg];
376 5054 : return strDefault;
377 : }
378 :
379 116615 : int64_t GetArg(const std::string& strArg, int64_t nDefault)
380 : {
381 116608 : if (mapArgs.count(strArg))
382 1731 : return atoi64(mapArgs[strArg]);
383 : return nDefault;
384 : }
385 :
386 10327 : bool GetBoolArg(const std::string& strArg, bool fDefault)
387 : {
388 10327 : if (mapArgs.count(strArg))
389 1312 : return InterpretBool(mapArgs[strArg]);
390 : return fDefault;
391 : }
392 :
393 127 : bool SoftSetArg(const std::string& strArg, const std::string& strValue)
394 : {
395 127 : if (mapArgs.count(strArg))
396 : return false;
397 115 : mapArgs[strArg] = strValue;
398 115 : return true;
399 : }
400 :
401 124 : bool SoftSetBoolArg(const std::string& strArg, bool fValue)
402 : {
403 124 : if (fValue)
404 294 : return SoftSetArg(strArg, std::string("1"));
405 : else
406 78 : return SoftSetArg(strArg, std::string("0"));
407 : }
408 :
409 : static const int screenWidth = 79;
410 : static const int optIndent = 2;
411 : static const int msgIndent = 7;
412 :
413 0 : std::string HelpMessageGroup(const std::string &message) {
414 0 : return std::string(message) + std::string("\n\n");
415 : }
416 :
417 0 : std::string HelpMessageOpt(const std::string &option, const std::string &message) {
418 0 : return std::string(optIndent,' ') + std::string(option) +
419 0 : std::string("\n") + std::string(msgIndent,' ') +
420 : FormatParagraph(message, screenWidth - msgIndent, msgIndent) +
421 0 : std::string("\n\n");
422 : }
423 :
424 0 : static std::string FormatException(const std::exception* pex, const char* pszThread)
425 : {
426 : #ifdef WIN32
427 : char pszModule[MAX_PATH] = "";
428 : GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
429 : #else
430 0 : const char* pszModule = "bitcoin";
431 : #endif
432 0 : if (pex)
433 : return strprintf(
434 0 : "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
435 : else
436 : return strprintf(
437 0 : "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
438 : }
439 :
440 0 : void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
441 : {
442 0 : std::string message = FormatException(pex, pszThread);
443 0 : LogPrintf("\n\n************************\n%s\n", message);
444 0 : fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
445 : strMiscWarning = message;
446 0 : }
447 :
448 95 : boost::filesystem::path GetDefaultDataDir()
449 : {
450 : namespace fs = boost::filesystem;
451 : // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
452 : // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
453 : // Mac: ~/Library/Application Support/Bitcoin
454 : // Unix: ~/.bitcoin
455 : #ifdef WIN32
456 : // Windows
457 : return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
458 : #else
459 : fs::path pathRet;
460 95 : char* pszHome = getenv("HOME");
461 95 : if (pszHome == NULL || strlen(pszHome) == 0)
462 0 : pathRet = fs::path("/");
463 : else
464 95 : pathRet = fs::path(pszHome);
465 : #ifdef MAC_OSX
466 : // Mac
467 : pathRet /= "Library/Application Support";
468 : TryCreateDirectory(pathRet);
469 : return pathRet / "Bitcoin";
470 : #else
471 : // Unix
472 285 : return pathRet / ".bitcoin";
473 : #endif
474 : #endif
475 : }
476 :
477 203 : static boost::filesystem::path pathCached;
478 203 : static boost::filesystem::path pathCachedNetSpecific;
479 203 : static CCriticalSection csPathCached;
480 :
481 70679 : const boost::filesystem::path &GetDataDir(bool fNetSpecific)
482 : {
483 : namespace fs = boost::filesystem;
484 :
485 70679 : LOCK(csPathCached);
486 :
487 70679 : fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
488 :
489 : // This can be called during exceptions by LogPrintf(), so we cache the
490 : // value so we don't have to do memory allocations after that.
491 70679 : if (!path.empty())
492 : return path;
493 :
494 1600 : if (mapArgs.count("-datadir")) {
495 1995 : path = fs::system_complete(mapArgs["-datadir"]);
496 399 : if (!fs::is_directory(path)) {
497 : path = "";
498 : return path;
499 : }
500 : } else {
501 2 : path = GetDefaultDataDir();
502 : }
503 400 : if (fNetSpecific)
504 240 : path /= BaseParams().DataDir();
505 :
506 : fs::create_directories(path);
507 :
508 : return path;
509 : }
510 :
511 211 : void ClearDatadirCache()
512 : {
513 211 : pathCached = boost::filesystem::path();
514 211 : pathCachedNetSpecific = boost::filesystem::path();
515 211 : }
516 :
517 281 : boost::filesystem::path GetConfigFile()
518 : {
519 1686 : boost::filesystem::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
520 281 : if (!pathConfigFile.is_complete())
521 562 : pathConfigFile = GetDataDir(false) / pathConfigFile;
522 :
523 281 : return pathConfigFile;
524 : }
525 :
526 187 : void ReadConfigFile(map<string, string>& mapSettingsRet,
527 : map<string, vector<string> >& mapMultiSettingsRet)
528 : {
529 374 : boost::filesystem::ifstream streamConfig(GetConfigFile());
530 187 : if (!streamConfig.good())
531 1 : return; // No bitcoin.conf file is OK
532 :
533 : set<string> setOptions;
534 558 : setOptions.insert("*");
535 :
536 1302 : for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
537 : {
538 : // Don't overwrite existing settings so command line settings override bitcoin.conf
539 2790 : string strKey = string("-") + it->string_key;
540 930 : string strValue = it->value[0];
541 930 : InterpretNegativeSetting(strKey, strValue);
542 930 : if (mapSettingsRet.count(strKey) == 0)
543 930 : mapSettingsRet[strKey] = strValue;
544 930 : mapMultiSettingsRet[strKey].push_back(strValue);
545 186 : }
546 : // If datadir is changed in .conf file:
547 372 : ClearDatadirCache();
548 : }
549 :
550 : #ifndef WIN32
551 188 : boost::filesystem::path GetPidFile()
552 : {
553 1128 : boost::filesystem::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
554 376 : if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
555 188 : return pathPidFile;
556 : }
557 :
558 94 : void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
559 : {
560 188 : FILE* file = fopen(path.string().c_str(), "w");
561 94 : if (file)
562 : {
563 : fprintf(file, "%d\n", pid);
564 94 : fclose(file);
565 : }
566 94 : }
567 : #endif
568 :
569 118 : bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
570 : {
571 : #ifdef WIN32
572 : return MoveFileExA(src.string().c_str(), dest.string().c_str(),
573 : MOVEFILE_REPLACE_EXISTING) != 0;
574 : #else
575 472 : int rc = std::rename(src.string().c_str(), dest.string().c_str());
576 118 : return (rc == 0);
577 : #endif /* WIN32 */
578 : }
579 :
580 : /**
581 : * Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
582 : * Specifically handles case where path p exists, but it wasn't possible for the user to
583 : * write to the parent directory.
584 : */
585 286 : bool TryCreateDirectory(const boost::filesystem::path& p)
586 : {
587 : try
588 : {
589 : return boost::filesystem::create_directory(p);
590 0 : } catch (const boost::filesystem::filesystem_error&) {
591 0 : if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p))
592 0 : throw;
593 : }
594 :
595 : // create_directory didn't create the directory, it had to have existed already
596 0 : return false;
597 : }
598 :
599 428 : void FileCommit(FILE *fileout)
600 : {
601 428 : fflush(fileout); // harmless if redundantly called
602 : #ifdef WIN32
603 : HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout));
604 : FlushFileBuffers(hFile);
605 : #else
606 : #if defined(__linux__) || defined(__NetBSD__)
607 428 : fdatasync(fileno(fileout));
608 : #elif defined(__APPLE__) && defined(F_FULLFSYNC)
609 : fcntl(fileno(fileout), F_FULLFSYNC, 0);
610 : #else
611 : fsync(fileno(fileout));
612 : #endif
613 : #endif
614 428 : }
615 :
616 0 : bool TruncateFile(FILE *file, unsigned int length) {
617 : #if defined(WIN32)
618 : return _chsize(_fileno(file), length) == 0;
619 : #else
620 0 : return ftruncate(fileno(file), length) == 0;
621 : #endif
622 : }
623 :
624 : /**
625 : * this function tries to raise the file descriptor limit to the requested number.
626 : * It returns the actual file descriptor limit (which may be more or less than nMinFD)
627 : */
628 94 : int RaiseFileDescriptorLimit(int nMinFD) {
629 : #if defined(WIN32)
630 : return 2048;
631 : #else
632 : struct rlimit limitFD;
633 94 : if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
634 94 : if (limitFD.rlim_cur < (rlim_t)nMinFD) {
635 0 : limitFD.rlim_cur = nMinFD;
636 0 : if (limitFD.rlim_cur > limitFD.rlim_max)
637 0 : limitFD.rlim_cur = limitFD.rlim_max;
638 0 : setrlimit(RLIMIT_NOFILE, &limitFD);
639 0 : getrlimit(RLIMIT_NOFILE, &limitFD);
640 : }
641 94 : return limitFD.rlim_cur;
642 : }
643 : return nMinFD; // getrlimit failed, assume it's fine
644 : #endif
645 : }
646 :
647 : /**
648 : * this function tries to make a particular range of a file allocated (corresponding to disk space)
649 : * it is advisory, and the range specified in the arguments will never contain live data
650 : */
651 98 : void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
652 : #if defined(WIN32)
653 : // Windows-specific version
654 : HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
655 : LARGE_INTEGER nFileSize;
656 : int64_t nEndPos = (int64_t)offset + length;
657 : nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
658 : nFileSize.u.HighPart = nEndPos >> 32;
659 : SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
660 : SetEndOfFile(hFile);
661 : #elif defined(MAC_OSX)
662 : // OSX specific version
663 : fstore_t fst;
664 : fst.fst_flags = F_ALLOCATECONTIG;
665 : fst.fst_posmode = F_PEOFPOSMODE;
666 : fst.fst_offset = 0;
667 : fst.fst_length = (off_t)offset + length;
668 : fst.fst_bytesalloc = 0;
669 : if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
670 : fst.fst_flags = F_ALLOCATEALL;
671 : fcntl(fileno(file), F_PREALLOCATE, &fst);
672 : }
673 : ftruncate(fileno(file), fst.fst_length);
674 : #elif defined(__linux__)
675 : // Version using posix_fallocate
676 98 : off_t nEndPos = (off_t)offset + length;
677 98 : posix_fallocate(fileno(file), 0, nEndPos);
678 : #else
679 : // Fallback version
680 : // TODO: just write one byte per block
681 : static const char buf[65536] = {};
682 : fseek(file, offset, SEEK_SET);
683 : while (length > 0) {
684 : unsigned int now = 65536;
685 : if (length < now)
686 : now = length;
687 : fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
688 : length -= now;
689 : }
690 : #endif
691 98 : }
692 :
693 79 : void ShrinkDebugFile()
694 : {
695 : // Scroll debug.log if it's getting too big
696 158 : boost::filesystem::path pathLog = GetDataDir() / "debug.log";
697 158 : FILE* file = fopen(pathLog.string().c_str(), "r");
698 106 : if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000)
699 : {
700 : // Restart the file with some of the end
701 0 : std::vector <char> vch(200000,0);
702 0 : fseek(file, -((long)vch.size()), SEEK_END);
703 0 : int nBytes = fread(begin_ptr(vch), 1, vch.size(), file);
704 0 : fclose(file);
705 :
706 0 : file = fopen(pathLog.string().c_str(), "w");
707 0 : if (file)
708 : {
709 0 : fwrite(begin_ptr(vch), 1, nBytes, file);
710 0 : fclose(file);
711 : }
712 : }
713 79 : else if (file != NULL)
714 27 : fclose(file);
715 79 : }
716 :
717 : #ifdef WIN32
718 : boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
719 : {
720 : namespace fs = boost::filesystem;
721 :
722 : char pszPath[MAX_PATH] = "";
723 :
724 : if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
725 : {
726 : return fs::path(pszPath);
727 : }
728 :
729 : LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
730 : return fs::path("");
731 : }
732 : #endif
733 :
734 26 : boost::filesystem::path GetTempPath() {
735 : #if BOOST_FILESYSTEM_VERSION == 3
736 26 : return boost::filesystem::temp_directory_path();
737 : #else
738 : // TODO: remove when we don't support filesystem v2 anymore
739 : boost::filesystem::path path;
740 : #ifdef WIN32
741 : char pszPath[MAX_PATH] = "";
742 :
743 : if (GetTempPathA(MAX_PATH, pszPath))
744 : path = boost::filesystem::path(pszPath);
745 : #else
746 : path = boost::filesystem::path("/tmp");
747 : #endif
748 : if (path.empty() || !boost::filesystem::is_directory(path)) {
749 : LogPrintf("GetTempPath(): failed to find temp path\n");
750 : return boost::filesystem::path("");
751 : }
752 : return path;
753 : #endif
754 : }
755 :
756 6 : void runCommand(const std::string& strCommand)
757 : {
758 6 : int nErr = ::system(strCommand.c_str());
759 6 : if (nErr)
760 0 : LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
761 6 : }
762 :
763 1643 : void RenameThread(const char* name)
764 : {
765 : #if defined(PR_SET_NAME)
766 : // Only the first 15 characters are used (16 - NUL terminator)
767 1643 : ::prctl(PR_SET_NAME, name, 0, 0, 0);
768 : #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
769 : pthread_set_name_np(pthread_self(), name);
770 :
771 : #elif defined(MAC_OSX)
772 : pthread_setname_np(name);
773 : #else
774 : // Prevent warnings for unused parameters...
775 : (void)name;
776 : #endif
777 1643 : }
778 :
779 377 : void SetupEnvironment()
780 : {
781 : // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
782 : // may be invalid, in which case the "C" locale is used as fallback.
783 : #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
784 : try {
785 377 : std::locale(""); // Raises a runtime error if current locale is invalid
786 0 : } catch (const std::runtime_error&) {
787 0 : setenv("LC_ALL", "C", 1);
788 : }
789 : #endif
790 : // The path locale is lazy initialized and to avoid deinitialization errors
791 : // in multithreading environments, it is set explicitly by the main thread.
792 : // A dummy locale is used to extract the internal default locale, used by
793 : // boost::filesystem::path, which is then used to explicitly imbue the path.
794 377 : std::locale loc = boost::filesystem::path::imbue(std::locale::classic());
795 377 : boost::filesystem::path::imbue(loc);
796 377 : }
797 :
798 187 : bool SetupNetworking()
799 : {
800 : #ifdef WIN32
801 : // Initialize Windows Sockets
802 : WSADATA wsadata;
803 : int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
804 : if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
805 : return false;
806 : #endif
807 187 : return true;
808 : }
809 :
810 94 : void SetThreadPriority(int nPriority)
811 : {
812 : #ifdef WIN32
813 : SetThreadPriority(GetCurrentThread(), nPriority);
814 : #else // WIN32
815 : #ifdef PRIO_THREAD
816 : setpriority(PRIO_THREAD, 0, nPriority);
817 : #else // PRIO_THREAD
818 94 : setpriority(PRIO_PROCESS, 0, nPriority);
819 : #endif // PRIO_THREAD
820 : #endif // WIN32
821 94 : }
822 :
823 94 : int GetNumCores()
824 : {
825 : #if BOOST_VERSION >= 105600
826 94 : return boost::thread::physical_concurrency();
827 : #else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores
828 : return boost::thread::hardware_concurrency();
829 : #endif
830 609 : }
831 :
|