Bitcoin Core 22.99.0
P2P Digital Currency
fs.h
Go to the documentation of this file.
1// Copyright (c) 2017-2019 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#ifndef BITCOIN_FS_H
6#define BITCOIN_FS_H
7
8#include <stdio.h>
9#include <string>
10#if defined WIN32 && defined __GLIBCXX__
11#include <ext/stdio_filebuf.h>
12#endif
13
14#include <boost/filesystem.hpp>
15#include <boost/filesystem/fstream.hpp>
16#include <tinyformat.h>
17
19namespace fs {
20
21using namespace boost::filesystem;
22
33class path : public boost::filesystem::path
34{
35public:
36 using boost::filesystem::path::path;
37
38 // Allow path objects arguments for compatibility.
39 path(boost::filesystem::path path) : boost::filesystem::path::path(std::move(path)) {}
40 path& operator=(boost::filesystem::path path) { boost::filesystem::path::operator=(std::move(path)); return *this; }
41 path& operator/=(boost::filesystem::path path) { boost::filesystem::path::operator/=(std::move(path)); return *this; }
42
43 // Allow literal string arguments, which are safe as long as the literals are ASCII.
44 path(const char* c) : boost::filesystem::path(c) {}
45 path& operator=(const char* c) { boost::filesystem::path::operator=(c); return *this; }
46 path& operator/=(const char* c) { boost::filesystem::path::operator/=(c); return *this; }
47 path& append(const char* c) { boost::filesystem::path::append(c); return *this; }
48
49 // Disallow std::string arguments to avoid locale-dependent decoding on windows.
50 path(std::string) = delete;
51 path& operator=(std::string) = delete;
52 path& operator/=(std::string) = delete;
53 path& append(std::string) = delete;
54
55 // Disallow std::string conversion method to avoid locale-dependent encoding on windows.
56 std::string string() const = delete;
57
58 // Define UTF-8 string conversion method not present in boost::filesystem but present in std::filesystem.
59 std::string u8string() const { return boost::filesystem::path::string(); }
60};
61
62// Define UTF-8 string conversion function not present in boost::filesystem but present in std::filesystem.
63static inline path u8path(const std::string& string)
64{
65 return boost::filesystem::path(string);
66}
67
68// Disallow implicit std::string conversion for system_complete to avoid
69// locale-dependent encoding on windows.
70static inline path system_complete(const path& p)
71{
73}
74
75// Disallow implicit std::string conversion for exists to avoid
76// locale-dependent encoding on windows.
77static inline bool exists(const path& p)
78{
80}
81
82// Allow explicit quoted stream I/O.
83static inline auto quoted(const std::string& s)
84{
85 return boost::io::quoted(s, '&');
86}
87
88// Allow safe path append operations.
89static inline path operator+(path p1, path p2)
90{
91 p1 += std::move(p2);
92 return p1;
93}
94
120static inline std::string PathToString(const path& path)
121{
122#ifdef WIN32
123 return path.u8string();
124#else
125 static_assert(std::is_same<path::string_type, std::string>::value, "PathToString not implemented on this platform");
126 return path.boost::filesystem::path::string();
127#endif
128}
129
133static inline path PathFromString(const std::string& string)
134{
135#ifdef WIN32
136 return u8path(string);
137#else
138 return boost::filesystem::path(string);
139#endif
140}
141} // namespace fs
142
144namespace fsbridge {
145 FILE *fopen(const fs::path& p, const char *mode);
146
156 fs::path AbsPathJoin(const fs::path& base, const fs::path& path);
157
159 {
160 public:
161 FileLock() = delete;
162 FileLock(const FileLock&) = delete;
163 FileLock(FileLock&&) = delete;
164 explicit FileLock(const fs::path& file);
165 ~FileLock();
166 bool TryLock();
167 std::string GetReason() { return reason; }
168
169 private:
170 std::string reason;
171#ifndef WIN32
172 int fd = -1;
173#else
174 void* hFile = (void*)-1; // INVALID_HANDLE_VALUE
175#endif
176 };
177
178 std::string get_filesystem_error_message(const fs::filesystem_error& e);
179
180 // GNU libstdc++ specific workaround for opening UTF-8 paths on Windows.
181 //
182 // On Windows, it is only possible to reliably access multibyte file paths through
183 // `wchar_t` APIs, not `char` APIs. But because the C++ standard doesn't
184 // require ifstream/ofstream `wchar_t` constructors, and the GNU library doesn't
185 // provide them (in contrast to the Microsoft C++ library, see
186 // https://stackoverflow.com/questions/821873/how-to-open-an-stdfstream-ofstream-or-ifstream-with-a-unicode-filename/822032#822032),
187 // Boost is forced to fall back to `char` constructors which may not work properly.
188 //
189 // Work around this issue by creating stream objects with `_wfopen` in
190 // combination with `__gnu_cxx::stdio_filebuf`. This workaround can be removed
191 // with an upgrade to C++17, where streams can be constructed directly from
192 // `std::filesystem::path` objects.
193
194#if defined WIN32 && defined __GLIBCXX__
195 class ifstream : public std::istream
196 {
197 public:
198 ifstream() = default;
199 explicit ifstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in) { open(p, mode); }
200 ~ifstream() { close(); }
201 void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in);
202 bool is_open() { return m_filebuf.is_open(); }
203 void close();
204
205 private:
206 __gnu_cxx::stdio_filebuf<char> m_filebuf;
207 FILE* m_file = nullptr;
208 };
209 class ofstream : public std::ostream
210 {
211 public:
212 ofstream() = default;
213 explicit ofstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out) { open(p, mode); }
214 ~ofstream() { close(); }
215 void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out);
216 bool is_open() { return m_filebuf.is_open(); }
217 void close();
218
219 private:
220 __gnu_cxx::stdio_filebuf<char> m_filebuf;
221 FILE* m_file = nullptr;
222 };
223#else // !(WIN32 && __GLIBCXX__)
226#endif // WIN32 && __GLIBCXX__
227};
228
229// Disallow path operator<< formatting in tinyformat to avoid locale-dependent
230// encoding on windows.
231namespace tinyformat {
232template<> inline void formatValue(std::ostream&, const char*, const char*, int, const boost::filesystem::path&) = delete;
233template<> inline void formatValue(std::ostream&, const char*, const char*, int, const fs::path&) = delete;
234} // namespace tinyformat
235
236#endif // BITCOIN_FS_H
Path class wrapper to prepare application code for transition from boost::filesystem library to std::...
Definition: fs.h:34
path & operator=(std::string)=delete
std::string string() const =delete
std::string u8string() const
Definition: fs.h:59
path & operator/=(std::string)=delete
path & operator=(boost::filesystem::path path)
Definition: fs.h:40
path & append(std::string)=delete
path & append(const char *c)
Definition: fs.h:47
path & operator=(const char *c)
Definition: fs.h:45
path(boost::filesystem::path path)
Definition: fs.h:39
path(std::string)=delete
path & operator/=(boost::filesystem::path path)
Definition: fs.h:41
path & operator/=(const char *c)
Definition: fs.h:46
path(const char *c)
Definition: fs.h:44
FileLock(FileLock &&)=delete
FileLock(const FileLock &)=delete
std::string reason
Definition: fs.h:170
std::string GetReason()
Definition: fs.h:167
bool TryLock()
Definition: fs.cpp:69
Filesystem operations and types.
Definition: fs.h:19
static path system_complete(const path &p)
Definition: fs.h:70
static path u8path(const std::string &string)
Definition: fs.h:63
static auto quoted(const std::string &s)
Definition: fs.h:83
static bool exists(const path &p)
Definition: fs.h:77
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:120
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:133
static path operator+(path p1, path p2)
Definition: fs.h:89
Bridge operations to C stdio.
Definition: fs.cpp:23
fs::ofstream ofstream
Definition: fs.h:225
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:25
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:138
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:35
fs::ifstream ifstream
Definition: fs.h:224
Definition: fs.h:231
void formatValue(std::ostream &, const char *, const char *, int, const boost::filesystem::path &)=delete