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