Bitcoin ABC 0.32.4
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_UTIL_FS_H
6#define BITCOIN_UTIL_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
20namespace fs {
21
22using namespace std::filesystem;
23
30class path : public std::filesystem::path {
31public:
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
90static inline path u8path(const std::string &utf8_str) {
91#if __cplusplus < 202002L
92 return std::filesystem::u8path(utf8_str);
93#else
94 return std::filesystem::path(
95 std::u8string{utf8_str.begin(), utf8_str.end()});
96#endif
97}
98
99// Disallow implicit std::string conversion for absolute to avoid
100// locale-dependent encoding on windows.
101static inline path absolute(const path &p) {
103}
104
105// Disallow implicit std::string conversion for exists to avoid
106// locale-dependent encoding on windows.
107static inline bool exists(const path &p) {
108 return std::filesystem::exists(p);
109}
110
111// Allow explicit quoted stream I/O.
112static inline auto quoted(const std::string &s) {
113 return std::quoted(s, '"', '&');
114}
115
116// Allow safe path append operations.
117static inline path operator+(path p1, path p2) {
118 p1 += std::move(p2);
119 return p1;
120}
121
122// Disallow implicit std::string conversion for copy_file
123// to avoid locale-dependent encoding on Windows.
124static inline bool copy_file(const path &from, const path &to,
125 copy_options options) {
126 return std::filesystem::copy_file(from, to, options);
127}
128
147static inline std::string PathToString(const path &path) {
148 // Implementation note: On Windows, the std::filesystem::path(string)
149 // constructor and std::filesystem::path::string() method are not safe to
150 // use here, because these methods encode the path using C++'s narrow
151 // multibyte encoding, which on Windows corresponds to the current "code
152 // page", which is unpredictable and typically not able to represent all
153 // valid paths. So fs::path::u8string() and
154 // fs::u8path() functions are used instead on Windows. On
155 // POSIX, u8string/u8path functions are not safe to use because paths are
156 // not always valid UTF-8, so plain string methods which do not transform
157 // the path there are used.
158#ifdef WIN32
159 return path.u8string();
160#else
161 static_assert(std::is_same<path::string_type, std::string>::value,
162 "PathToString not implemented on this platform");
163 return path.std::filesystem::path::string();
164#endif
165}
166
170static inline path PathFromString(const std::string &string) {
171#ifdef WIN32
172 return u8path(string);
173#else
174 return std::filesystem::path(string);
175#endif
176}
177
184static inline bool create_directories(const std::filesystem::path &p) {
185 if (std::filesystem::is_symlink(p) && std::filesystem::is_directory(p)) {
186 return false;
187 }
189}
190
196bool create_directories(const std::filesystem::path &p,
197 std::error_code &ec) = delete;
198
199} // namespace fs
200
202namespace fsbridge {
203using FopenFn = std::function<FILE *(const fs::path &, const char *)>;
204FILE *fopen(const fs::path &p, const char *mode);
205FILE *freopen(const fs::path &p, const char *mode, FILE *stream);
206
217fs::path AbsPathJoin(const fs::path &base, const fs::path &path);
218
219class FileLock {
220public:
221 FileLock() = delete;
222 FileLock(const FileLock &) = delete;
223 FileLock(FileLock &&) = delete;
224 explicit FileLock(const fs::path &file);
225 ~FileLock();
226 bool TryLock();
227 std::string GetReason() { return reason; }
228
229private:
230 std::string reason;
231#ifndef WIN32
232 int fd = -1;
233#else
234 // INVALID_HANDLE_VALUE
235 void *hFile = (void *)-1;
236#endif
237};
238
239std::string get_filesystem_error_message(const fs::filesystem_error &e);
240
242}; // namespace fsbridge
243
244// Disallow path operator<< formatting in tinyformat to avoid locale-dependent
245// encoding on windows.
246namespace tinyformat {
247template <>
248inline void formatValue(std::ostream &, const char *, const char *, int,
249 const std::filesystem::path &) = delete;
250template <>
251inline void formatValue(std::ostream &, const char *, const char *, int,
252 const fs::path &) = delete;
253} // namespace tinyformat
254
255#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:30
path & operator/=(std::filesystem::path path)
Definition: fs.h:40
path(std::filesystem::path path)
Definition: fs.h:34
path & operator=(std::string)=delete
std::string string() const =delete
std::string u8string() const
Definition: fs.h:72
path & operator/=(std::string)=delete
path & append(std::string)=delete
path & operator=(std::filesystem::path path)
Definition: fs.h:36
path & append(const char *c)
Definition: fs.h:56
path & make_preferred()
Definition: fs.h:83
path & operator=(const char *c)
Definition: fs.h:48
path(std::string)=delete
path filename() const
Definition: fs.h:87
path & operator/=(const char *c)
Definition: fs.h:52
path(const char *c)
Definition: fs.h:47
FileLock(FileLock &&)=delete
FileLock(const FileLock &)=delete
std::string reason
Definition: fs.h:230
std::string GetReason()
Definition: fs.h:227
bool TryLock()
Definition: fs.cpp:70
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:101
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:184
static auto quoted(const std::string &s)
Definition: fs.h:112
static bool exists(const path &p)
Definition: fs.h:107
static bool copy_file(const path &from, const path &to, copy_options options)
Definition: fs.h:124
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:147
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:170
static path operator+(path p1, path p2)
Definition: fs.h:117
Bridge operations to C stdio.
Definition: fs.cpp:28
fs::path GetTempDirectoryPath()
Definition: fs.cpp:160
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:30
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:142
FILE * freopen(const fs::path &p, const char *mode, FILE *stream)
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:39
std::function< FILE *(const fs::path &, const char *)> FopenFn
Definition: fs.h:203
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
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:327