Bitcoin Core  22.99.0
P2P Digital Currency
fs.h
Go to the documentation of this file.
1 // Copyright (c) 2017-2021 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 <iomanip>
13 #include <ios>
14 #include <ostream>
15 #include <string>
16 #include <utility>
17 
19 namespace fs {
20 
21 using namespace std::filesystem;
22 
29 class path : public std::filesystem::path
30 {
31 public:
32  using std::filesystem::path::path;
33 
34  // Allow path objects arguments for compatibility.
35  path(std::filesystem::path path) : std::filesystem::path::path(std::move(path)) {}
36  path& operator=(std::filesystem::path path) { std::filesystem::path::operator=(std::move(path)); return *this; }
37  path& operator/=(std::filesystem::path path) { std::filesystem::path::operator/=(std::move(path)); return *this; }
38 
39  // Allow literal string arguments, which are safe as long as the literals are ASCII.
40  path(const char* c) : std::filesystem::path(c) {}
41  path& operator=(const char* c) { std::filesystem::path::operator=(c); return *this; }
42  path& operator/=(const char* c) { std::filesystem::path::operator/=(c); return *this; }
43  path& append(const char* c) { std::filesystem::path::append(c); return *this; }
44 
45  // Disallow std::string arguments to avoid locale-dependent decoding on windows.
46  path(std::string) = delete;
47  path& operator=(std::string) = delete;
48  path& operator/=(std::string) = delete;
49  path& append(std::string) = delete;
50 
51  // Disallow std::string conversion method to avoid locale-dependent encoding on windows.
52  std::string string() const = delete;
53 
54  // Required for path overloads in <fstream>.
55  // See https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=96e0367ead5d8dcac3bec2865582e76e2fbab190
56  path& make_preferred() { std::filesystem::path::make_preferred(); return *this; }
57  path filename() const { return std::filesystem::path::filename(); }
58 };
59 
60 // Disallow implicit std::string conversion for absolute to avoid
61 // locale-dependent encoding on windows.
62 static inline path absolute(const path& p)
63 {
64  return std::filesystem::absolute(p);
65 }
66 
67 // Disallow implicit std::string conversion for exists to avoid
68 // locale-dependent encoding on windows.
69 static inline bool exists(const path& p)
70 {
71  return std::filesystem::exists(p);
72 }
73 
74 // Allow explicit quoted stream I/O.
75 static inline auto quoted(const std::string& s)
76 {
77  return std::quoted(s, '"', '&');
78 }
79 
80 // Allow safe path append operations.
81 static inline path operator+(path p1, path p2)
82 {
83  p1 += std::move(p2);
84  return p1;
85 }
86 
87 // Disallow implicit std::string conversion for copy_file
88 // to avoid locale-dependent encoding on Windows.
89 static inline bool copy_file(const path& from, const path& to, copy_options options)
90 {
91  return std::filesystem::copy_file(from, to, options);
92 }
93 
112 static inline std::string PathToString(const path& path)
113 {
114  // Implementation note: On Windows, the std::filesystem::path(string)
115  // constructor and std::filesystem::path::string() method are not safe to
116  // use here, because these methods encode the path using C++'s narrow
117  // multibyte encoding, which on Windows corresponds to the current "code
118  // page", which is unpredictable and typically not able to represent all
119  // valid paths. So std::filesystem::path::u8string() and
120  // std::filesystem::u8path() functions are used instead on Windows. On
121  // POSIX, u8string/u8path functions are not safe to use because paths are
122  // not always valid UTF-8, so plain string methods which do not transform
123  // the path there are used.
124 #ifdef WIN32
125  return path.u8string();
126 #else
127  static_assert(std::is_same<path::string_type, std::string>::value, "PathToString not implemented on this platform");
128  return path.std::filesystem::path::string();
129 #endif
130 }
131 
135 static inline path PathFromString(const std::string& string)
136 {
137 #ifdef WIN32
138  return u8path(string);
139 #else
140  return std::filesystem::path(string);
141 #endif
142 }
143 
150 static inline bool create_directories(const std::filesystem::path& p)
151 {
152  if (std::filesystem::is_symlink(p) && std::filesystem::is_directory(p)) {
153  return false;
154  }
156 }
157 
163 bool create_directories(const std::filesystem::path& p, std::error_code& ec) = delete;
164 
165 } // namespace fs
166 
168 namespace fsbridge {
169  FILE *fopen(const fs::path& p, const char *mode);
170 
180  fs::path AbsPathJoin(const fs::path& base, const fs::path& path);
181 
182  class FileLock
183  {
184  public:
185  FileLock() = delete;
186  FileLock(const FileLock&) = delete;
187  FileLock(FileLock&&) = delete;
188  explicit FileLock(const fs::path& file);
189  ~FileLock();
190  bool TryLock();
191  std::string GetReason() { return reason; }
192 
193  private:
194  std::string reason;
195 #ifndef WIN32
196  int fd = -1;
197 #else
198  void* hFile = (void*)-1; // INVALID_HANDLE_VALUE
199 #endif
200  };
201 
202  std::string get_filesystem_error_message(const fs::filesystem_error& e);
203 };
204 
205 // Disallow path operator<< formatting in tinyformat to avoid locale-dependent
206 // encoding on windows.
207 namespace tinyformat {
208 template<> inline void formatValue(std::ostream&, const char*, const char*, int, const std::filesystem::path&) = delete;
209 template<> inline void formatValue(std::ostream&, const char*, const char*, int, const fs::path&) = delete;
210 } // namespace tinyformat
211 
212 #endif // BITCOIN_FS_H
tinyformat
Definition: fs.h:207
fs::path::filename
path filename() const
Definition: fs.h:57
fs::exists
static bool exists(const path &p)
Definition: fs.h:69
fs::create_directories
bool create_directories(const std::filesystem::path &p, std::error_code &ec)=delete
This variant is not used.
fsbridge::fopen
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:27
fsbridge::get_filesystem_error_message
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:140
fs::path::make_preferred
path & make_preferred()
Definition: fs.h:56
fs::quoted
static auto quoted(const std::string &s)
Definition: fs.h:75
fsbridge::AbsPathJoin
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:37
fs::PathToString
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:112
fsbridge::FileLock::GetReason
std::string GetReason()
Definition: fs.h:191
fs::path::append
path & append(const char *c)
Definition: fs.h:43
fs::path::operator/=
path & operator/=(const char *c)
Definition: fs.h:42
tinyformat.h
fs::path::operator/=
path & operator/=(std::filesystem::path path)
Definition: fs.h:37
fs::path
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:29
fs::path::operator=
path & operator=(const char *c)
Definition: fs.h:41
fs::PathFromString
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:135
fsbridge::FileLock
Definition: fs.h:182
fs::path::path
path(std::filesystem::path path)
Definition: fs.h:35
fs
Filesystem operations and types.
Definition: fs.h:19
std
Definition: setup_common.h:33
fs::create_directories
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:150
fs::absolute
static path absolute(const path &p)
Definition: fs.h:62
fs::copy_file
static bool copy_file(const path &from, const path &to, copy_options options)
Definition: fs.h:89
tinyformat::formatValue
void formatValue(std::ostream &, const char *, const char *, int, const fs::path &)=delete
fs::path::operator=
path & operator=(std::filesystem::path path)
Definition: fs.h:36
fs::operator+
static path operator+(path p1, path p2)
Definition: fs.h:81
fsbridge::FileLock::reason
std::string reason
Definition: fs.h:194
fsbridge
Bridge operations to C stdio.
Definition: fs.cpp:25
fs::path::path
path(const char *c)
Definition: fs.h:40