Bitcoin Core 31.99.0
P2P Digital Currency
fs.h
Go to the documentation of this file.
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#ifndef BITCOIN_UTIL_FS_H
6#define BITCOIN_UTIL_FS_H
7
8// IWYU incorrectly suggests removing this header.
9// See https://github.com/include-what-you-use/include-what-you-use/issues/1931.
10#include <tinyformat.h> // IWYU pragma: keep
11
12#include <cstdio>
13// The `util/fs.h` header is designed to be a drop-in replacement for `filesystem`.
14#include <filesystem> // IWYU pragma: export
15#include <functional>
16#include <iomanip>
17#include <ios>
18#include <string>
19#include <string_view>
20#include <type_traits>
21#include <utility>
22
24namespace fs {
25
26using namespace std::filesystem;
27
34class path : public std::filesystem::path
35{
36public:
37 using std::filesystem::path::path;
38
39 // Convenience method for accessing standard path type without needing a cast.
40 std::filesystem::path& std_path() { return *this; }
41 const std::filesystem::path& std_path() const { return *this; }
42
43 // Allow path objects arguments for compatibility.
44 path(std::filesystem::path path) : std::filesystem::path::path(std::move(path)) {}
45 path& operator=(std::filesystem::path path) { std::filesystem::path::operator=(std::move(path)); return *this; }
46 path& operator/=(const std::filesystem::path& path) { std::filesystem::path::operator/=(path); return *this; }
47
48 // Allow literal string arguments, which are safe as long as the literals are ASCII.
49 path(const char* c) : std::filesystem::path(c) {}
50 path& operator=(const char* c) { std::filesystem::path::operator=(c); return *this; }
51 path& operator/=(const char* c) { std::filesystem::path::operator/=(c); return *this; }
52 path& append(const char* c) { std::filesystem::path::append(c); return *this; }
53
54 // Disallow std::string arguments to avoid locale-dependent decoding on windows.
55 path(std::string) = delete;
56 path& operator=(std::string) = delete;
57 path& operator/=(std::string) = delete;
58 path& append(std::string) = delete;
59
60 // Disallow std::string conversion method to avoid locale-dependent encoding on windows.
61 std::string string() const = delete;
62
63 // Disallow implicit string conversion to ensure code is portable.
64 // `string_type` may be `string` or `wstring` depending on the platform, so
65 // using this conversion could result in code that compiles on unix but
66 // fails to compile on windows, or vice versa.
67 operator string_type() const = delete;
68
75 std::string utf8string() const
76 {
77 const std::u8string& utf8_str{std::filesystem::path::u8string()};
78 return std::string{utf8_str.begin(), utf8_str.end()};
79 }
80};
81
82static inline path u8path(std::string_view utf8_str)
83{
84 return std::filesystem::path(std::u8string{utf8_str.begin(), utf8_str.end()});
85}
86
87// Disallow implicit std::string conversion for absolute to avoid
88// locale-dependent encoding on windows.
89static inline path absolute(const path& p)
90{
92}
93
94// Disallow implicit std::string conversion for exists to avoid
95// locale-dependent encoding on windows.
96static inline bool exists(const path& p)
97{
99}
100static inline bool exists(const std::filesystem::file_status& s)
101{
103}
104
105// Allow explicit quoted stream I/O.
106static inline auto quoted(const std::string& s)
107{
108 return std::quoted(s, '"', '&');
109}
110
111// Allow safe path append operations.
112static inline path operator/(path p1, const path& p2)
113{
114 p1 /= p2;
115 return p1;
116}
117static inline path operator/(path p1, const char* p2)
118{
119 p1 /= p2;
120 return p1;
121}
122static inline path operator+(path p1, const char* p2)
123{
124 p1 += p2;
125 return p1;
126}
127static inline path operator+(path p1, path::value_type p2)
128{
129 p1 += p2;
130 return p1;
131}
132
133// Disallow unsafe path append operations.
134template<typename T> static inline path operator/(path p1, T p2) = delete;
135template<typename T> static inline path operator+(path p1, T p2) = delete;
136
137// Disallow implicit std::string conversion for copy_file
138// to avoid locale-dependent encoding on Windows.
139static inline bool copy_file(const path& from, const path& to, copy_options options)
140{
141 return std::filesystem::copy_file(from, to, options);
142}
143
162static inline std::string PathToString(const path& path)
163{
164 // Implementation note: On Windows, the std::filesystem::path(string)
165 // constructor and std::filesystem::path::string() method are not safe to
166 // use here, because these methods encode the path using C++'s narrow
167 // multibyte encoding, which on Windows corresponds to the current "code
168 // page", which is unpredictable and typically not able to represent all
169 // valid paths. So fs::path::utf8string() and
170 // fs::u8path() functions are used instead on Windows. On
171 // POSIX, u8string/utf8string/u8path functions are not safe to use because paths are
172 // not always valid UTF-8, so plain string methods which do not transform
173 // the path there are used.
174#ifdef WIN32
175 return path.utf8string();
176#else
177 static_assert(std::is_same_v<path::string_type, std::string>, "PathToString not implemented on this platform");
178 return path.std::filesystem::path::string();
179#endif
180}
181
185static inline path PathFromString(const std::string& string)
186{
187#ifdef WIN32
188 return u8path(string);
189#else
190 return std::filesystem::path(string);
191#endif
192}
193} // namespace fs
194
196namespace fsbridge {
197 using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
198 FILE *fopen(const fs::path& p, const char *mode);
199
209 fs::path AbsPathJoin(const fs::path& base, const fs::path& path);
210
212 {
213 public:
214 FileLock() = delete;
215 FileLock(const FileLock&) = delete;
216 FileLock(FileLock&&) = delete;
217 explicit FileLock(const fs::path& file);
218 ~FileLock();
219 bool TryLock();
220 std::string GetReason() { return reason; }
221
222 private:
223 std::string reason;
224#ifndef WIN32
225 int fd = -1;
226#else
227 void* hFile = (void*)-1; // INVALID_HANDLE_VALUE
228#endif
229 };
230};
231
232// Disallow path operator<< formatting in tinyformat to avoid locale-dependent
233// encoding on windows.
234namespace tinyformat {
235template<> inline void formatValue(std::ostream&, const char*, const char*, int, const std::filesystem::path&) = delete;
236template<> inline void formatValue(std::ostream&, const char*, const char*, int, const fs::path&) = delete;
237} // namespace tinyformat
238
239#endif // BITCOIN_UTIL_FS_H
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:35
const std::filesystem::path & std_path() const
Definition: fs.h:41
path(std::filesystem::path path)
Definition: fs.h:44
path & operator=(std::string)=delete
std::filesystem::path & std_path()
Definition: fs.h:40
std::string string() const =delete
path & operator/=(const std::filesystem::path &path)
Definition: fs.h:46
path & operator/=(std::string)=delete
std::string utf8string() const
Return a UTF-8 representation of the path as a std::string, for compatibility with code using std::st...
Definition: fs.h:75
path & append(std::string)=delete
path & operator=(std::filesystem::path path)
Definition: fs.h:45
path & append(const char *c)
Definition: fs.h:52
path & operator=(const char *c)
Definition: fs.h:50
path(std::string)=delete
path & operator/=(const char *c)
Definition: fs.h:51
path(const char *c)
Definition: fs.h:49
FileLock(FileLock &&)=delete
FileLock(const FileLock &)=delete
std::string reason
Definition: fs.h:223
std::string GetReason()
Definition: fs.h:220
bool TryLock()
Definition: fs.cpp:60
static path absolute(const path &p)
Definition: fs.h:89
static path u8path(std::string_view utf8_str)
Definition: fs.h:82
static auto quoted(const std::string &s)
Definition: fs.h:106
static bool exists(const path &p)
Definition: fs.h:96
static bool copy_file(const path &from, const path &to, copy_options options)
Definition: fs.h:139
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:162
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:185
static path operator/(path p1, const path &p2)
Definition: fs.h:112
Bridge operations to C stdio.
Definition: fs.cpp:21
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:23
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:32
std::function< FILE *(const fs::path &, const char *)> FopenFn
Definition: fs.h:197
Definition: common.h:29
void formatValue(std::ostream &out, const char *, const char *fmtEnd, int ntrunc, const T &value)
Format a value into a stream, delegating to operator<< by default.
Definition: tinyformat.h:349
bilingual_str operator+(bilingual_str lhs, const bilingual_str &rhs)
Definition: translation.h:47