Bitcoin ABC  0.29.1
P2P Digital Currency
fs.h
Go to the documentation of this file.
1 // Copyright (c) 2017 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 <tinyformat.h>
9 
10 #include <cstdio>
11 #include <filesystem>
12 #include <functional>
13 #include <iomanip>
14 #include <ios>
15 #include <ostream>
16 #include <string>
17 #include <utility>
18 
20 namespace fs {
21 
22 using namespace std::filesystem;
23 
30 class path : public std::filesystem::path {
31 public:
32  using std::filesystem::path::path;
33  // Allow path objects arguments for compatibility.
34  path(std::filesystem::path path)
35  : std::filesystem::path::path(std::move(path)) {}
36  path &operator=(std::filesystem::path path) {
37  std::filesystem::path::operator=(std::move(path));
38  return *this;
39  }
40  path &operator/=(std::filesystem::path path) {
41  std::filesystem::path::operator/=(std::move(path));
42  return *this;
43  }
44 
45  // Allow literal string arguments, which are safe as long as the literals
46  // are ASCII.
47  path(const char *c) : std::filesystem::path(c) {}
48  path &operator=(const char *c) {
49  std::filesystem::path::operator=(c);
50  return *this;
51  }
52  path &operator/=(const char *c) {
53  std::filesystem::path::operator/=(c);
54  return *this;
55  }
56  path &append(const char *c) {
57  std::filesystem::path::append(c);
58  return *this;
59  }
60 
61  // Disallow std::string arguments to avoid locale-dependent decoding on
62  // windows.
63  path(std::string) = delete;
64  path &operator=(std::string) = delete;
65  path &operator/=(std::string) = delete;
66  path &append(std::string) = delete;
67 
68  // Disallow std::string conversion method to avoid locale-dependent encoding
69  // on windows.
70  std::string string() const = delete;
71 
72  std::string u8string() const {
73  const auto &utf8_str{std::filesystem::path::u8string()};
74  // utf8_str might either be std::string (C++17) or std::u8string
75  // (C++20). Convert both to std::string. This method can be removed
76  // after switching to C++20.
77  return std::string{utf8_str.begin(), utf8_str.end()};
78  }
79 
80  // Required for path overloads in <fstream>.
81  // See
82  // https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=96e0367ead5d8dcac3bec2865582e76e2fbab190
84  std::filesystem::path::make_preferred();
85  return *this;
86  }
87  path filename() const { return std::filesystem::path::filename(); }
88 };
89 
90 static inline path u8path(const std::string &utf8_str) {
91  return std::filesystem::u8path(utf8_str);
92 }
93 
94 // Disallow implicit std::string conversion for absolute to avoid
95 // locale-dependent encoding on windows.
96 static inline path absolute(const path &p) {
97  return std::filesystem::absolute(p);
98 }
99 
100 // Disallow implicit std::string conversion for exists to avoid
101 // locale-dependent encoding on windows.
102 static inline bool exists(const path &p) {
103  return std::filesystem::exists(p);
104 }
105 
106 // Allow explicit quoted stream I/O.
107 static inline auto quoted(const std::string &s) {
108  return std::quoted(s, '"', '&');
109 }
110 
111 // Allow safe path append operations.
112 static inline path operator+(path p1, path p2) {
113  p1 += std::move(p2);
114  return p1;
115 }
116 
117 // Disallow implicit std::string conversion for copy_file
118 // to avoid locale-dependent encoding on Windows.
119 static inline bool copy_file(const path &from, const path &to,
120  copy_options options) {
121  return std::filesystem::copy_file(from, to, options);
122 }
123 
142 static inline std::string PathToString(const path &path) {
143  // Implementation note: On Windows, the std::filesystem::path(string)
144  // constructor and std::filesystem::path::string() method are not safe to
145  // use here, because these methods encode the path using C++'s narrow
146  // multibyte encoding, which on Windows corresponds to the current "code
147  // page", which is unpredictable and typically not able to represent all
148  // valid paths. So fs::path::u8string() and
149  // fs::u8path() functions are used instead on Windows. On
150  // POSIX, u8string/u8path functions are not safe to use because paths are
151  // not always valid UTF-8, so plain string methods which do not transform
152  // the path there are used.
153 #ifdef WIN32
154  return path.u8string();
155 #else
156  static_assert(std::is_same<path::string_type, std::string>::value,
157  "PathToString not implemented on this platform");
158  return path.std::filesystem::path::string();
159 #endif
160 }
161 
165 static inline path PathFromString(const std::string &string) {
166 #ifdef WIN32
167  return u8path(string);
168 #else
169  return std::filesystem::path(string);
170 #endif
171 }
172 
179 static inline bool create_directories(const std::filesystem::path &p) {
180  if (std::filesystem::is_symlink(p) && std::filesystem::is_directory(p)) {
181  return false;
182  }
184 }
185 
191 bool create_directories(const std::filesystem::path &p,
192  std::error_code &ec) = delete;
193 
194 } // namespace fs
195 
197 namespace fsbridge {
198 using FopenFn = std::function<FILE *(const fs::path &, const char *)>;
199 FILE *fopen(const fs::path &p, const char *mode);
200 FILE *freopen(const fs::path &p, const char *mode, FILE *stream);
201 
212 fs::path AbsPathJoin(const fs::path &base, const fs::path &path);
213 
214 class FileLock {
215 public:
216  FileLock() = delete;
217  FileLock(const FileLock &) = delete;
218  FileLock(FileLock &&) = delete;
219  explicit FileLock(const fs::path &file);
220  ~FileLock();
221  bool TryLock();
222  std::string GetReason() { return reason; }
223 
224 private:
225  std::string reason;
226 #ifndef WIN32
227  int fd = -1;
228 #else
229  // INVALID_HANDLE_VALUE
230  void *hFile = (void *)-1;
231 #endif
232 };
233 
234 std::string get_filesystem_error_message(const fs::filesystem_error &e);
235 
237 }; // namespace fsbridge
238 
239 // Disallow path operator<< formatting in tinyformat to avoid locale-dependent
240 // encoding on windows.
241 namespace tinyformat {
242 template <>
243 inline void formatValue(std::ostream &, const char *, const char *, int,
244  const std::filesystem::path &) = delete;
245 template <>
246 inline void formatValue(std::ostream &, const char *, const char *, int,
247  const fs::path &) = delete;
248 } // namespace tinyformat
249 
250 #endif // BITCOIN_FS_H
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
path & append(const char *c)
Definition: fs.h:56
path(std::filesystem::path path)
Definition: fs.h:34
path & make_preferred()
Definition: fs.h:83
std::string string() const =delete
std::string u8string() const
Definition: fs.h:72
path & append(std::string)=delete
path & operator=(std::string)=delete
path & operator=(std::filesystem::path path)
Definition: fs.h:36
path & operator=(const char *c)
Definition: fs.h:48
path & operator/=(std::string)=delete
path(std::string)=delete
path & operator/=(const char *c)
Definition: fs.h:52
path filename() const
Definition: fs.h:87
path & operator/=(std::filesystem::path path)
Definition: fs.h:40
path(const char *c)
Definition: fs.h:47
FileLock(FileLock &&)=delete
FileLock(const FileLock &)=delete
std::string reason
Definition: fs.h:225
std::string GetReason()
Definition: fs.h:222
Filesystem operations and types.
Definition: fs.h:20
bool create_directories(const std::filesystem::path &p, std::error_code &ec)=delete
This variant is not used.
static path absolute(const path &p)
Definition: fs.h:96
static path u8path(const std::string &utf8_str)
Definition: fs.h:90
static bool create_directories(const std::filesystem::path &p)
Create directory (and if necessary its parents), unless the leaf directory already exists or is a sym...
Definition: fs.h:179
static auto quoted(const std::string &s)
Definition: fs.h:107
static bool exists(const path &p)
Definition: fs.h:102
static bool copy_file(const path &from, const path &to, copy_options options)
Definition: fs.h:119
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:142
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:165
static path operator+(path p1, path p2)
Definition: fs.h:112
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
FILE * freopen(const fs::path &p, const char *mode, FILE *stream)
std::function< FILE *(const fs::path &, const char *)> FopenFn
Definition: fs.h:198
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:257
Definition: fs.h:241
void formatValue(std::ostream &, const char *, const char *, int, const fs::path &)=delete