Line data Source code
1 : // Copyright (c) 2017-2020 The Bitcoin Core developers 2 : // Copyright (c) 2020-2021 The PIVX Core developers 3 : // Distributed under the MIT/X11 software license, see the accompanying 4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 : 6 : #ifndef PIVX_FS_H 7 : #define PIVX_FS_H 8 : 9 : #include <stdio.h> 10 : #include <string> 11 : #if defined WIN32 && defined __GLIBCXX__ 12 : #include <ext/stdio_filebuf.h> 13 : #endif 14 : 15 : #define BOOST_FILESYSTEM_NO_DEPRECATED 16 : #include <boost/filesystem.hpp> 17 : #include <boost/filesystem/fstream.hpp> 18 : 19 : /** Filesystem operations and types */ 20 : namespace fs = boost::filesystem; 21 : 22 : /** Bridge operations to C stdio */ 23 : namespace fsbridge { 24 : FILE *fopen(const fs::path& p, const char *mode); 25 : 26 : class FileLock 27 : { 28 : public: 29 : FileLock() = delete; 30 : FileLock(const FileLock&) = delete; 31 : FileLock(FileLock&&) = delete; 32 : explicit FileLock(const fs::path& file); 33 : ~FileLock(); 34 : bool TryLock(); 35 12 : std::string GetReason() { return reason; } 36 : 37 : private: 38 : std::string reason; 39 : #ifndef WIN32 40 : int fd = -1; 41 : #else 42 : void* hFile = (void*)-1; // INVALID_HANDLE_VALUE 43 : #endif 44 : }; 45 : 46 : std::string get_filesystem_error_message(const fs::filesystem_error& e); 47 : 48 : // GNU libstdc++ specific workaround for opening UTF-8 paths on Windows. 49 : // 50 : // On Windows, it is only possible to reliably access multibyte file paths through 51 : // `wchar_t` APIs, not `char` APIs. But because the C++ standard doesn't 52 : // require ifstream/ofstream `wchar_t` constructors, and the GNU library doesn't 53 : // provide them (in contrast to the Microsoft C++ library, see 54 : // https://stackoverflow.com/questions/821873/how-to-open-an-stdfstream-ofstream-or-ifstream-with-a-unicode-filename/822032#822032), 55 : // Boost is forced to fall back to `char` constructors which may not work properly. 56 : // 57 : // Work around this issue by creating stream objects with `_wfopen` in 58 : // combination with `__gnu_cxx::stdio_filebuf`. This workaround can be removed 59 : // with an upgrade to C++17, where streams can be constructed directly from 60 : // `std::filesystem::path` objects. 61 : 62 : #if defined WIN32 && defined __GLIBCXX__ 63 : class ifstream : public std::istream 64 : { 65 : public: 66 : ifstream() = default; 67 : explicit ifstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in) { open(p, mode); } 68 : ~ifstream() { close(); } 69 : void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in); 70 : bool is_open() { return m_filebuf.is_open(); } 71 : void close(); 72 : 73 : private: 74 : __gnu_cxx::stdio_filebuf<char> m_filebuf; 75 : FILE* m_file = nullptr; 76 : }; 77 : class ofstream : public std::ostream 78 : { 79 : public: 80 : ofstream() = default; 81 : explicit ofstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out) { open(p, mode); } 82 : ~ofstream() { close(); } 83 : void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out); 84 : bool is_open() { return m_filebuf.is_open(); } 85 : void close(); 86 : 87 : private: 88 : __gnu_cxx::stdio_filebuf<char> m_filebuf; 89 : FILE* m_file = nullptr; 90 : }; 91 : #else // !(WIN32 && __GLIBCXX__) 92 : typedef fs::ifstream ifstream; 93 : typedef fs::ofstream ofstream; 94 : #endif // WIN32 && __GLIBCXX__ 95 : }; 96 : 97 : #endif // PIVX_FS_H