Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2017-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_UTIL_FS_H6#define BITCOIN_UTIL_FS_H8#include <tinyformat.h>10#include <cstdio>11// The `util/fs.h` header is designed to be a drop-in replacement for `filesystem`.12#include <filesystem> // IWYU pragma: export13#include <functional>14#include <iomanip>15#include <ios>16#include <string>17#include <string_view>18#include <type_traits>19#include <utility>21/** Filesystem operations and types */22namespace fs {24using namespace std::filesystem;26/**27* Path class wrapper to block calls to the fs::path(std::string) implicit28* constructor and the fs::path::string() method, which have unsafe and29* unpredictable behavior on Windows (see implementation note in30* \ref PathToString for details)31*/32class path : public std::filesystem::path33{34public:35using std::filesystem::path::path;37// Convenience method for accessing standard path type without needing a cast.38std::filesystem::path& std_path() { return *this; }39const std::filesystem::path& std_path() const { return *this; }41// Allow path objects arguments for compatibility.42path(std::filesystem::path path) : std::filesystem::path::path(std::move(path)) {}43path& operator=(std::filesystem::path path) { std::filesystem::path::operator=(std::move(path)); return *this; }44path& operator/=(const std::filesystem::path& path) { std::filesystem::path::operator/=(path); return *this; }46// Allow literal string arguments, which are safe as long as the literals are ASCII.47path(const char* c) : std::filesystem::path(c) {}48path& operator=(const char* c) { std::filesystem::path::operator=(c); return *this; }49path& operator/=(const char* c) { std::filesystem::path::operator/=(c); return *this; }50path& append(const char* c) { std::filesystem::path::append(c); return *this; }52// Disallow std::string arguments to avoid locale-dependent decoding on windows.53path(std::string) = delete;54path& operator=(std::string) = delete;55path& operator/=(std::string) = delete;56path& append(std::string) = delete;58// Disallow std::string conversion method to avoid locale-dependent encoding on windows.59std::string string() const = delete;61// Disallow implicit string conversion to ensure code is portable.62// `string_type` may be `string` or `wstring` depending on the platform, so63// using this conversion could result in code that compiles on unix but64// fails to compile on windows, or vice versa.65operator string_type() const = delete;67/**68* Return a UTF-8 representation of the path as a std::string, for69* compatibility with code using std::string. For code using the newer70* std::u8string type, it is more efficient to call the inherited71* std::filesystem::path::u8string method instead.72*/73std::string utf8string() const74{75const std::u8string& utf8_str{std::filesystem::path::u8string()};76return std::string{utf8_str.begin(), utf8_str.end()};77}78};80static inline path u8path(std::string_view utf8_str)81{82return std::filesystem::path(std::u8string{utf8_str.begin(), utf8_str.end()});83}85// Disallow implicit std::string conversion for absolute to avoid86// locale-dependent encoding on windows.87static inline path absolute(const path& p)88{89return std::filesystem::absolute(p);90}92// Disallow implicit std::string conversion for exists to avoid93// locale-dependent encoding on windows.94static inline bool exists(const path& p)95{96return std::filesystem::exists(p);97}98static inline bool exists(const std::filesystem::file_status& s)99{100return std::filesystem::exists(s);101}103// Allow explicit quoted stream I/O.104static inline auto quoted(const std::string& s)105{106return std::quoted(s, '"', '&');107}109// Allow safe path append operations.110static inline path operator/(path p1, const path& p2)111{112p1 /= p2;113return p1;114}115static inline path operator/(path p1, const char* p2)116{117p1 /= p2;118return p1;119}120static inline path operator+(path p1, const char* p2)121{122p1 += p2;123return p1;124}125static inline path operator+(path p1, path::value_type p2)126{127p1 += p2;128return p1;129}131// Disallow unsafe path append operations.132template<typename T> static inline path operator/(path p1, T p2) = delete;133template<typename T> static inline path operator+(path p1, T p2) = delete;135// Disallow implicit std::string conversion for copy_file136// to avoid locale-dependent encoding on Windows.137static inline bool copy_file(const path& from, const path& to, copy_options options)138{139return std::filesystem::copy_file(from, to, options);140}142/**143* Convert path object to a byte string. On POSIX, paths natively are byte144* strings, so this is trivial. On Windows, paths natively are Unicode, so an145* encoding step is necessary. The inverse of \ref PathToString is \ref146* PathFromString. The strings returned and parsed by these functions can be147* used to call POSIX APIs, and for roundtrip conversion, logging, and148* debugging.149*150* Because \ref PathToString and \ref PathFromString functions don't specify an151* encoding, they are meant to be used internally, not externally. They are not152* appropriate to use in applications requiring UTF-8, where153* fs::path::u8string() / fs::path::utf8string() and fs::u8path() methods should be used instead. Other154* applications could require still different encodings. For example, JSON, XML,155* or URI applications might prefer to use higher-level escapes (\uXXXX or156* &XXXX; or %XX) instead of multibyte encoding. Rust, Python, Java applications157* may require encoding paths with their respective UTF-8 derivatives WTF-8,158* PEP-383, and CESU-8 (see https://en.wikipedia.org/wiki/UTF-8#Derivatives).159*/160static inline std::string PathToString(const path& path)161{162// Implementation note: On Windows, the std::filesystem::path(string)163// constructor and std::filesystem::path::string() method are not safe to164// use here, because these methods encode the path using C++'s narrow165// multibyte encoding, which on Windows corresponds to the current "code166// page", which is unpredictable and typically not able to represent all167// valid paths. So fs::path::utf8string() and168// fs::u8path() functions are used instead on Windows. On169// POSIX, u8string/utf8string/u8path functions are not safe to use because paths are170// not always valid UTF-8, so plain string methods which do not transform171// the path there are used.172#ifdef WIN32173return path.utf8string();174#else175static_assert(std::is_same_v<path::string_type, std::string>, "PathToString not implemented on this platform");176return path.std::filesystem::path::string();177#endif178}180/**181* Convert byte string to path object. Inverse of \ref PathToString.182*/183static inline path PathFromString(const std::string& string)184{185#ifdef WIN32186return u8path(string);187#else188return std::filesystem::path(string);189#endif190}191} // namespace fs193/** Bridge operations to C stdio */194namespace fsbridge {195using FopenFn = std::function<FILE*(const fs::path&, const char*)>;196FILE *fopen(const fs::path& p, const char *mode);198/**199* Helper function for joining two paths200*201* @param[in] base Base path202* @param[in] path Path to combine with base203* @returns path unchanged if it is an absolute path, otherwise returns base joined with path. Returns base unchanged if path is empty.204* @pre Base path must be absolute205* @post Returned path will always be absolute206*/207fs::path AbsPathJoin(const fs::path& base, const fs::path& path);209class FileLock210{211public:212FileLock() = delete;213FileLock(const FileLock&) = delete;214FileLock(FileLock&&) = delete;215explicit FileLock(const fs::path& file);216~FileLock();217bool TryLock();218std::string GetReason() { return reason; }220private:221std::string reason;222#ifndef WIN32223int fd = -1;224#else225void* hFile = (void*)-1; // INVALID_HANDLE_VALUE226#endif227};228};230// Disallow path operator<< formatting in tinyformat to avoid locale-dependent231// encoding on windows.232namespace tinyformat {233template<> inline void formatValue(std::ostream&, const char*, const char*, int, const std::filesystem::path&) = delete;234template<> inline void formatValue(std::ostream&, const char*, const char*, int, const fs::path&) = delete;235} // namespace tinyformat237#endif // BITCOIN_UTIL_FS_H
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.