fs.cpp
1 // Copyright (c) 2017-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <util/fs.h> 6 #include <util/syserror.h> 7 8 #ifndef WIN32 9 #include <cstring> 10 #include <fcntl.h> 11 #include <sys/file.h> 12 #include <sys/utsname.h> 13 #include <unistd.h> 14 #else 15 #include <limits> 16 #include <windows.h> 17 #endif 18 19 #include <cassert> 20 #include <cerrno> 21 #include <string> 22 23 namespace fsbridge { 24 25 FILE *fopen(const fs::path& p, const char *mode) 26 { 27 #ifndef WIN32 28 return ::fopen(p.c_str(), mode); 29 #else 30 return ::fopen(p.utf8string().c_str(), mode); 31 #endif 32 } 33 34 fs::path AbsPathJoin(const fs::path& base, const fs::path& path) 35 { 36 assert(base.is_absolute()); 37 return path.empty() ? base : fs::path(base / path); 38 } 39 40 #ifndef WIN32 41 42 static std::string GetErrorReason() 43 { 44 return SysErrorString(errno); 45 } 46 47 FileLock::FileLock(const fs::path& file) 48 { 49 fd = open(file.c_str(), O_RDWR); 50 if (fd == -1) { 51 reason = GetErrorReason(); 52 } 53 } 54 55 FileLock::~FileLock() 56 { 57 if (fd != -1) { 58 close(fd); 59 } 60 } 61 62 bool FileLock::TryLock() 63 { 64 if (fd == -1) { 65 return false; 66 } 67 68 struct flock lock; 69 lock.l_type = F_WRLCK; 70 lock.l_whence = SEEK_SET; 71 lock.l_start = 0; 72 lock.l_len = 0; 73 if (fcntl(fd, F_SETLK, &lock) == -1) { 74 reason = GetErrorReason(); 75 return false; 76 } 77 78 return true; 79 } 80 #else 81 82 static std::string GetErrorReason() { 83 return Win32ErrorString(GetLastError()); 84 } 85 86 FileLock::FileLock(const fs::path& file) 87 { 88 hFile = CreateFileW(file.wstring().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 89 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 90 if (hFile == INVALID_HANDLE_VALUE) { 91 reason = GetErrorReason(); 92 } 93 } 94 95 FileLock::~FileLock() 96 { 97 if (hFile != INVALID_HANDLE_VALUE) { 98 CloseHandle(hFile); 99 } 100 } 101 102 bool FileLock::TryLock() 103 { 104 if (hFile == INVALID_HANDLE_VALUE) { 105 return false; 106 } 107 _OVERLAPPED overlapped = {}; 108 if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, std::numeric_limits<DWORD>::max(), std::numeric_limits<DWORD>::max(), &overlapped)) { 109 reason = GetErrorReason(); 110 return false; 111 } 112 return true; 113 } 114 #endif 115 116 } // namespace fsbridge