Bitcoin ABC  0.29.1
P2P Digital Currency
fs.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 The Bitcoin Core developers
2 // Copyright (c) 2019 The Bitcoin 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 #include <fs.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 #ifndef NOMINMAX
16 #define NOMINMAX
17 #endif
18 #include <codecvt>
19 #include <windows.h>
20 #endif
21 
22 #include <cassert>
23 #include <limits>
24 #include <string>
25 
26 namespace fsbridge {
27 
28 FILE *fopen(const fs::path &p, const char *mode) {
29 #ifndef WIN32
30  return ::fopen(p.c_str(), mode);
31 #else
32  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_cvt;
33  return ::_wfopen(p.wstring().c_str(), utf8_cvt.from_bytes(mode).c_str());
34 #endif
35 }
36 
37 fs::path AbsPathJoin(const fs::path &base, const fs::path &path) {
38  assert(base.is_absolute());
39  return path.empty() ? base : fs::path(base / path);
40 }
41 
42 #ifndef WIN32
43 
44 static std::string GetErrorReason() {
45  return std::strerror(errno);
46 }
47 
49  fd = open(file.c_str(), O_RDWR);
50  if (fd == -1) {
52  }
53 }
54 
56  if (fd != -1) {
57  close(fd);
58  }
59 }
60 
61 static bool IsWSL() {
62  struct utsname uname_data;
63  return uname(&uname_data) == 0 &&
64  std::string(uname_data.version).find("Microsoft") !=
65  std::string::npos;
66 }
67 
69  if (fd == -1) {
70  return false;
71  }
72 
73  // Exclusive file locking is broken on WSL using fcntl (issue #18622)
74  // This workaround can be removed once the bug on WSL is fixed
75  static const bool is_wsl = IsWSL();
76  if (is_wsl) {
77  if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
79  return false;
80  }
81  } else {
82  struct flock lock;
83  lock.l_type = F_WRLCK;
84  lock.l_whence = SEEK_SET;
85  lock.l_start = 0;
86  lock.l_len = 0;
87  if (fcntl(fd, F_SETLK, &lock) == -1) {
89  return false;
90  }
91  }
92 
93  return true;
94 }
95 #else
96 
97 static std::string GetErrorReason() {
98  wchar_t *err;
99  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
100  FORMAT_MESSAGE_IGNORE_INSERTS,
101  nullptr, GetLastError(),
102  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
103  reinterpret_cast<WCHAR *>(&err), 0, nullptr);
104  std::wstring err_str(err);
105  LocalFree(err);
106  return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(
107  err_str);
108 }
109 
110 FileLock::FileLock(const fs::path &file) {
111  hFile = CreateFileW(file.wstring().c_str(), GENERIC_READ | GENERIC_WRITE,
112  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
113  nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
114  if (hFile == INVALID_HANDLE_VALUE) {
116  }
117 }
118 
120  if (hFile != INVALID_HANDLE_VALUE) {
121  CloseHandle(hFile);
122  }
123 }
124 
125 bool FileLock::TryLock() {
126  if (hFile == INVALID_HANDLE_VALUE) {
127  return false;
128  }
129  _OVERLAPPED overlapped = {0};
130  if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
131  0, std::numeric_limits<DWORD>::max(),
132  std::numeric_limits<DWORD>::max(), &overlapped)) {
134  return false;
135  }
136  return true;
137 }
138 #endif
139 
140 std::string get_filesystem_error_message(const fs::filesystem_error &e) {
141 #ifndef WIN32
142  return e.what();
143 #else
144  // Convert from Multi Byte to utf-16
145  std::string mb_string(e.what());
146  int size = MultiByteToWideChar(CP_ACP, 0, mb_string.data(),
147  mb_string.size(), nullptr, 0);
148 
149  std::wstring utf16_string(size, L'\0');
150  MultiByteToWideChar(CP_ACP, 0, mb_string.data(), mb_string.size(),
151  &*utf16_string.begin(), size);
152  // Convert from utf-16 to utf-8
153  return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>()
154  .to_bytes(utf16_string);
155 #endif
156 }
157 
159 #ifndef WIN32
160  return fs::temp_directory_path();
161 #else
162  wchar_t dirPathWchars[MAX_PATH];
163  GetTempPathW(MAX_PATH, dirPathWchars);
164  std::wstring dirPathWstring(dirPathWchars);
165  return fs::PathFromString(
166  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(
167  dirPathWstring));
168 #endif
169 }
170 
171 } // namespace fsbridge
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
std::string reason
Definition: fs.h:225
bool TryLock()
Definition: fs.cpp:68
#define MAX_PATH
Definition: compat.h:70
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:165
Bridge operations to C stdio.
Definition: fs.cpp:26
fs::path GetTempDirectoryPath()
Definition: fs.cpp:158
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:28
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:140
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:37
static std::string GetErrorReason()
Definition: fs.cpp:44
static bool IsWSL()
Definition: fs.cpp:61
assert(!tx.IsCoinBase())