diff --git a/src/fs.cpp b/src/fs.cpp index 74c86303b2..6b09dec34b 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -1,14 +1,99 @@ // Copyright (c) 2017 The Bitcoin Core developers // Copyright (c) 2019 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#ifndef WIN32 +#include +#else +#include +#include +#endif + namespace fsbridge { FILE *fopen(const fs::path &p, const char *mode) { return ::fopen(p.string().c_str(), mode); } +#ifndef WIN32 + +static std::string GetErrorReason() { + return std::strerror(errno); +} + +FileLock::FileLock(const fs::path &file) { + fd = open(file.string().c_str(), O_RDWR); + if (fd == -1) { + reason = GetErrorReason(); + } +} + +FileLock::~FileLock() { + if (fd != -1) { + close(fd); + } +} + +bool FileLock::TryLock() { + if (fd == -1) { + return false; + } + struct flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + if (fcntl(fd, F_SETLK, &lock) == -1) { + reason = GetErrorReason(); + return false; + } + return true; +} +#else + +static std::string GetErrorReason() { + wchar_t *err; + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&err), 0, nullptr); + std::wstring err_str(err); + LocalFree(err); + return std::wstring_convert>().to_bytes( + err_str); +} + +FileLock::FileLock(const fs::path &file) { + hFile = CreateFileW(file.wstring().c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile == INVALID_HANDLE_VALUE) { + reason = GetErrorReason(); + } +} + +FileLock::~FileLock() { + if (hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + } +} + +bool FileLock::TryLock() { + if (hFile == INVALID_HANDLE_VALUE) { + return false; + } + _OVERLAPPED overlapped = {0}; + if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, + 0, 0, 0, &overlapped)) { + reason = GetErrorReason(); + return false; + } + return true; +} +#endif + } // namespace fsbridge diff --git a/src/fs.h b/src/fs.h index bbd2a0c1e3..6022f1b48c 100644 --- a/src/fs.h +++ b/src/fs.h @@ -1,22 +1,43 @@ // Copyright (c) 2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_FS_H #define BITCOIN_FS_H #include #include #include #include /** Filesystem operations and types */ namespace fs = boost::filesystem; /** Bridge operations to C stdio */ namespace fsbridge { FILE *fopen(const fs::path &p, const char *mode); +FILE *freopen(const fs::path &p, const char *mode, FILE *stream); + +class FileLock { +public: + FileLock() = delete; + FileLock(const FileLock &) = delete; + FileLock(FileLock &&) = delete; + explicit FileLock(const fs::path &file); + ~FileLock(); + bool TryLock(); + std::string GetReason() { return reason; } + +private: + std::string reason; +#ifndef WIN32 + int fd = -1; +#else + // INVALID_HANDLE_VALUE + void *hFile = (void *)-1; +#endif +}; }; // namespace fsbridge #endif // BITCOIN_FS_H diff --git a/src/init.cpp b/src/init.cpp index 8e6103d04e..6257a8f1e7 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,2481 +1,2481 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include