diff --git a/build-aux/m4/ax_boost_filesystem.m4 b/build-aux/m4/ax_boost_filesystem.m4 deleted file mode 100644 index 12f7bc5e2eb..00000000000 --- a/build-aux/m4/ax_boost_filesystem.m4 +++ /dev/null @@ -1,118 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_BOOST_FILESYSTEM -# -# DESCRIPTION -# -# Test for Filesystem library from the Boost C++ libraries. The macro -# requires a preceding call to AX_BOOST_BASE. Further documentation is -# available at . -# -# This macro calls: -# -# AC_SUBST(BOOST_FILESYSTEM_LIB) -# -# And sets: -# -# HAVE_BOOST_FILESYSTEM -# -# LICENSE -# -# Copyright (c) 2009 Thomas Porschberg -# Copyright (c) 2009 Michael Tindal -# Copyright (c) 2009 Roman Rybalko -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 28 - -AC_DEFUN([AX_BOOST_FILESYSTEM], -[ - AC_ARG_WITH([boost-filesystem], - AS_HELP_STRING([--with-boost-filesystem@<:@=special-lib@:>@], - [use the Filesystem library from boost - it is possible to specify a certain library for the linker - e.g. --with-boost-filesystem=boost_filesystem-gcc-mt ]), - [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ax_boost_user_filesystem_lib="" - else - want_boost="yes" - ax_boost_user_filesystem_lib="$withval" - fi - ], - [want_boost="yes"] - ) - - if test "x$want_boost" = "xyes"; then - AC_REQUIRE([AC_PROG_CC]) - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - LIBS_SAVED=$LIBS - LIBS="$LIBS $BOOST_SYSTEM_LIB" - export LIBS - - AC_CACHE_CHECK(whether the Boost::Filesystem library is available, - ax_cv_boost_filesystem, - [AC_LANG_PUSH([C++]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[using namespace boost::filesystem; - path my_path( "foo/bar/data.txt" ); - return 0;]])], - ax_cv_boost_filesystem=yes, ax_cv_boost_filesystem=no) - AC_LANG_POP([C++]) - ]) - if test "x$ax_cv_boost_filesystem" = "xyes"; then - AC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available]) - BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` - if test "x$ax_boost_user_filesystem_lib" = "x"; then - for libextension in `ls -r $BOOSTLIBDIR/libboost_filesystem* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do - ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], - [link_filesystem="no"]) - done - if test "x$link_filesystem" != "xyes"; then - for libextension in `ls -r $BOOSTLIBDIR/boost_filesystem* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do - ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], - [link_filesystem="no"]) - done - fi - else - for ax_lib in $ax_boost_user_filesystem_lib boost_filesystem-$ax_boost_user_filesystem_lib; do - AC_CHECK_LIB($ax_lib, exit, - [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], - [link_filesystem="no"]) - done - - fi - if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the Boost::Filesystem library!) - fi - if test "x$link_filesystem" != "xyes"; then - AC_MSG_ERROR(Could not link against $ax_lib !) - fi - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - LIBS="$LIBS_SAVED" - fi -]) diff --git a/build-aux/m4/ax_boost_system.m4 b/build-aux/m4/ax_boost_system.m4 deleted file mode 100644 index 323e2a676a8..00000000000 --- a/build-aux/m4/ax_boost_system.m4 +++ /dev/null @@ -1,121 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_boost_system.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_BOOST_SYSTEM -# -# DESCRIPTION -# -# Test for System library from the Boost C++ libraries. The macro requires -# a preceding call to AX_BOOST_BASE. Further documentation is available at -# . -# -# This macro calls: -# -# AC_SUBST(BOOST_SYSTEM_LIB) -# -# And sets: -# -# HAVE_BOOST_SYSTEM -# -# LICENSE -# -# Copyright (c) 2008 Thomas Porschberg -# Copyright (c) 2008 Michael Tindal -# Copyright (c) 2008 Daniel Casimiro -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 20 - -AC_DEFUN([AX_BOOST_SYSTEM], -[ - AC_ARG_WITH([boost-system], - AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@], - [use the System library from boost - it is possible to specify a certain library for the linker - e.g. --with-boost-system=boost_system-gcc-mt ]), - [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ax_boost_user_system_lib="" - else - want_boost="yes" - ax_boost_user_system_lib="$withval" - fi - ], - [want_boost="yes"] - ) - - if test "x$want_boost" = "xyes"; then - AC_REQUIRE([AC_PROG_CC]) - AC_REQUIRE([AC_CANONICAL_BUILD]) - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - AC_CACHE_CHECK(whether the Boost::System library is available, - ax_cv_boost_system, - [AC_LANG_PUSH([C++]) - CXXFLAGS_SAVE=$CXXFLAGS - CXXFLAGS= - - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[boost::system::error_category *a = 0;]])], - ax_cv_boost_system=yes, ax_cv_boost_system=no) - CXXFLAGS=$CXXFLAGS_SAVE - AC_LANG_POP([C++]) - ]) - if test "x$ax_cv_boost_system" = "xyes"; then - AC_SUBST(BOOST_CPPFLAGS) - - AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available]) - BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` - - LDFLAGS_SAVE=$LDFLAGS - if test "x$ax_boost_user_system_lib" = "x"; then - for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do - ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], - [link_system="no"]) - done - if test "x$link_system" != "xyes"; then - for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do - ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], - [link_system="no"]) - done - fi - - else - for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do - AC_CHECK_LIB($ax_lib, exit, - [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], - [link_system="no"]) - done - - fi - if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the Boost::System library!) - fi - if test "x$link_system" = "xno"; then - AC_MSG_ERROR(Could not link against $ax_lib !) - fi - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi -]) diff --git a/build-aux/m4/l_filesystem.m4 b/build-aux/m4/l_filesystem.m4 new file mode 100644 index 00000000000..ca3a0cd41c0 --- /dev/null +++ b/build-aux/m4/l_filesystem.m4 @@ -0,0 +1,47 @@ +dnl Copyright (c) 2022 The Bitcoin Core developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# GCC 8.1 and earlier requires -lstdc++fs +# Clang 8.0.0 (libc++) and earlier requires -lc++fs + +m4_define([_CHECK_FILESYSTEM_testbody], [[ + #include + + namespace fs = std::filesystem; + + int main() { + (void)fs::current_path().root_name(); + return 0; + } +]]) + +AC_DEFUN([CHECK_FILESYSTEM], [ + + AC_LANG_PUSH(C++) + + AC_MSG_CHECKING([whether std::filesystem can be used without link library]) + + AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_FILESYSTEM_testbody])],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + SAVED_LIBS="$LIBS" + LIBS="$SAVED_LIBS -lstdc++fs" + AC_MSG_CHECKING([whether std::filesystem needs -lstdc++fs]) + AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_FILESYSTEM_testbody])],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + AC_MSG_CHECKING([whether std::filesystem needs -lc++fs]) + LIBS="$SAVED_LIBS -lc++fs" + AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_FILESYSTEM_testbody])],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_FAILURE([cannot figure out how to use std::filesystem]) + ]) + ]) + ]) + + AC_LANG_POP +]) diff --git a/build_msvc/bitcoin_config.h.in b/build_msvc/bitcoin_config.h.in index 83e53c8d567..c5ed6eb9030 100644 --- a/build_msvc/bitcoin_config.h.in +++ b/build_msvc/bitcoin_config.h.in @@ -44,15 +44,9 @@ /* define if the Boost library is available */ #define HAVE_BOOST /**/ -/* define if the Boost::Filesystem library is available */ -#define HAVE_BOOST_FILESYSTEM /**/ - /* define if external signer support is enabled (requires Boost::Process) */ #define ENABLE_EXTERNAL_SIGNER /**/ -/* define if the Boost::System library is available */ -#define HAVE_BOOST_SYSTEM /**/ - /* define if the Boost::Unit_Test_Framework library is available */ #define HAVE_BOOST_UNIT_TEST_FRAMEWORK /**/ diff --git a/build_msvc/vcpkg.json b/build_msvc/vcpkg.json index 42b9a5d16fc..d8753ec21f4 100644 --- a/build_msvc/vcpkg.json +++ b/build_msvc/vcpkg.json @@ -3,7 +3,6 @@ "version-string": "1", "dependencies": [ "berkeleydb", - "boost-filesystem", "boost-multi-index", "boost-process", "boost-signals2", diff --git a/ci/test/00_setup_env_native_asan.sh b/ci/test/00_setup_env_native_asan.sh index 109b1214668..79caa607a88 100755 --- a/ci/test/00_setup_env_native_asan.sh +++ b/ci/test/00_setup_env_native_asan.sh @@ -7,7 +7,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_asan -export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libsqlite3-dev" +export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libsqlite3-dev" export DOCKER_NAME_TAG=ubuntu:22.04 export NO_DEPENDS=1 export GOAL="install" diff --git a/ci/test/00_setup_env_native_fuzz.sh b/ci/test/00_setup_env_native_fuzz.sh index 34b25438a44..af03ac4f5db 100755 --- a/ci/test/00_setup_env_native_fuzz.sh +++ b/ci/test/00_setup_env_native_fuzz.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export DOCKER_NAME_TAG="ubuntu:20.04" export CONTAINER_NAME=ci_native_fuzz -export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libsqlite3-dev" +export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-test-dev libsqlite3-dev" export NO_DEPENDS=1 export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false diff --git a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh index fe6df0cbb75..607c0a43d03 100755 --- a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh +++ b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export DOCKER_NAME_TAG="ubuntu:20.04" export CONTAINER_NAME=ci_native_fuzz_valgrind -export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libsqlite3-dev valgrind" +export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-test-dev libsqlite3-dev valgrind" export NO_DEPENDS=1 export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false diff --git a/ci/test/00_setup_env_native_valgrind.sh b/ci/test/00_setup_env_native_valgrind.sh index e414385cc4d..b0852f52a7e 100755 --- a/ci/test/00_setup_env_native_valgrind.sh +++ b/ci/test/00_setup_env_native_valgrind.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export DOCKER_NAME_TAG="ubuntu:20.04" export CONTAINER_NAME=ci_native_valgrind -export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libsqlite3-dev" +export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libsqlite3-dev" export USE_VALGRIND=1 export NO_DEPENDS=1 export TEST_RUNNER_EXTRA="--nosandbox --exclude rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 diff --git a/configure.ac b/configure.ac index bef39739963..078e113e958 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,9 @@ AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory]) dnl Check if -latomic is required for CHECK_ATOMIC +dnl check if additional link flags are required for std::filesystem +CHECK_FILESYSTEM + dnl Unless the user specified OBJCXX, force it to be the same as CXX. This ensures dnl that we get the same -std flags for both. m4_ifdef([AC_PROG_OBJCXX],[ @@ -1404,14 +1407,12 @@ if test "$use_boost" = "yes"; then if test "$want_boost" = "no"; then AC_MSG_ERROR([only libbitcoinconsensus can be built without Boost]) fi - AX_BOOST_SYSTEM - AX_BOOST_FILESYSTEM if test "$suppress_external_warnings" != "no"; then BOOST_CPPFLAGS=SUPPRESS_WARNINGS($BOOST_CPPFLAGS) fi - BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB" + BOOST_LIBS="$BOOST_LDFLAGS" fi if test "$use_external_signer" != "no"; then diff --git a/contrib/valgrind.supp b/contrib/valgrind.supp index ece02dc24e8..35f3d792ffd 100644 --- a/contrib/valgrind.supp +++ b/contrib/valgrind.supp @@ -118,12 +118,6 @@ fun:__wcsnlen_sse4_1 fun:wcsnrtombs } -{ - Suppress wcsnrtombs warning (remove after removing boost::fs) - Memcheck:Cond - ... - fun:_ZN5boost10filesystem6detail11unique_pathERKNS0_4pathEPNS_6system10error_codeE -} { Suppress boost warning Memcheck:Leak @@ -134,21 +128,6 @@ fun:_ZN5boost9unit_test14unit_test_mainEPFbvEiPPc fun:main } -{ - Suppress boost::filesystem warning (fixed in boost 1.70: https://github.com/boostorg/filesystem/commit/bbe9d1771e5d679b3f10c42a58fc81f7e8c024a9) - Memcheck:Cond - fun:_ZN5boost10filesystem6detail28directory_iterator_incrementERNS0_18directory_iteratorEPNS_6system10error_codeE - ... - obj:*/libboost_filesystem.so.* -} -{ - Suppress boost::filesystem warning (could be related: https://stackoverflow.com/questions/9830182/function-boostfilesystemcomplete-being-reported-as-possible-memory-leak-by-v) - Memcheck:Leak - match-leak-kinds: reachable - fun:_Znwm - ... - fun:_ZN5boost10filesystem8absoluteERKNS0_4pathES3_ -} { Suppress boost still reachable memory warning Memcheck:Leak diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 9d3ba321f96..820a7ff4e70 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -22,7 +22,7 @@ $(package)_toolset_$(host_os)=clang else $(package)_toolset_$(host_os)=gcc endif -$(package)_config_libraries=filesystem,system,test +$(package)_config_libraries=test $(package)_cxxflags+=-std=c++17 $(package)_cxxflags_linux=-fPIC $(package)_cxxflags_freebsd=-fPIC diff --git a/doc/build-unix.md b/doc/build-unix.md index f50a9b23c00..38844cdf819 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -82,7 +82,7 @@ Build requirements: Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies: - sudo apt-get install libevent-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev + sudo apt-get install libevent-dev libboost-dev libboost-test-dev SQLite is required for the descriptor wallet: diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 94518b88d86..4f22e688db6 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index 9bd176f0a07..5c24b712a74 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -29,7 +30,7 @@ void GenerateTemplateResults(const std::vector& bench // nothing to write, bail out return; } - fsbridge::ofstream fout{fs::PathFromString(filename)}; + std::ofstream fout{fs::PathFromString(filename)}; if (fout.is_open()) { ankerl::nanobench::render(tpl, benchmarkResults, fout); } else { diff --git a/src/fs.cpp b/src/fs.cpp index 8fcadcb3ef9..219fdee959a 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -37,7 +37,7 @@ FILE *fopen(const fs::path& p, const char *mode) fs::path AbsPathJoin(const fs::path& base, const fs::path& path) { assert(base.is_absolute()); - return fs::absolute(path, base); + return path.empty() ? base : fs::path(base / path); } #ifndef WIN32 @@ -153,118 +153,4 @@ std::string get_filesystem_error_message(const fs::filesystem_error& e) #endif } -#ifdef WIN32 -#ifdef __GLIBCXX__ - -// reference: https://github.com/gcc-mirror/gcc/blob/gcc-7_3_0-release/libstdc%2B%2B-v3/include/std/fstream#L270 -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch" -#endif -static std::string openmodeToStr(std::ios_base::openmode mode) -{ - switch (mode & ~std::ios_base::ate) { - case std::ios_base::out: - case std::ios_base::out | std::ios_base::trunc: - return "w"; - case std::ios_base::out | std::ios_base::app: - case std::ios_base::app: - return "a"; - case std::ios_base::in: - return "r"; - case std::ios_base::in | std::ios_base::out: - return "r+"; - case std::ios_base::in | std::ios_base::out | std::ios_base::trunc: - return "w+"; - case std::ios_base::in | std::ios_base::out | std::ios_base::app: - case std::ios_base::in | std::ios_base::app: - return "a+"; - case std::ios_base::out | std::ios_base::binary: - case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary: - return "wb"; - case std::ios_base::out | std::ios_base::app | std::ios_base::binary: - case std::ios_base::app | std::ios_base::binary: - return "ab"; - case std::ios_base::in | std::ios_base::binary: - return "rb"; - case std::ios_base::in | std::ios_base::out | std::ios_base::binary: - return "r+b"; - case std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary: - return "w+b"; - case std::ios_base::in | std::ios_base::out | std::ios_base::app | std::ios_base::binary: - case std::ios_base::in | std::ios_base::app | std::ios_base::binary: - return "a+b"; - default: - return std::string(); - } -} -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - -void ifstream::open(const fs::path& p, std::ios_base::openmode mode) -{ - close(); - mode |= std::ios_base::in; - m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str()); - if (m_file == nullptr) { - return; - } - m_filebuf = __gnu_cxx::stdio_filebuf(m_file, mode); - rdbuf(&m_filebuf); - if (mode & std::ios_base::ate) { - seekg(0, std::ios_base::end); - } -} - -void ifstream::close() -{ - if (m_file != nullptr) { - m_filebuf.close(); - fclose(m_file); - } - m_file = nullptr; -} - -void ofstream::open(const fs::path& p, std::ios_base::openmode mode) -{ - close(); - mode |= std::ios_base::out; - m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str()); - if (m_file == nullptr) { - return; - } - m_filebuf = __gnu_cxx::stdio_filebuf(m_file, mode); - rdbuf(&m_filebuf); - if (mode & std::ios_base::ate) { - seekp(0, std::ios_base::end); - } -} - -void ofstream::close() -{ - if (m_file != nullptr) { - m_filebuf.close(); - fclose(m_file); - } - m_file = nullptr; -} -#else // __GLIBCXX__ - -#if BOOST_VERSION >= 107700 -static_assert(sizeof(*BOOST_FILESYSTEM_C_STR(boost::filesystem::path())) == sizeof(wchar_t), -#else -static_assert(sizeof(*boost::filesystem::path().BOOST_FILESYSTEM_C_STR) == sizeof(wchar_t), -#endif // BOOST_VERSION >= 107700 - "Warning: This build is using boost::filesystem ofstream and ifstream " - "implementations which will fail to open paths containing multibyte " - "characters. You should delete this static_assert to ignore this warning, " - "or switch to a different C++ standard library like the Microsoft C++ " - "Standard Library (where boost uses non-standard extensions to construct " - "stream objects with wide filenames), or the GNU libstdc++ library (where " - "a more complicated workaround has been implemented above)."); - -#endif // __GLIBCXX__ -#endif // WIN32 - } // fsbridge diff --git a/src/fs.h b/src/fs.h index bc36636084c..d2299db168c 100644 --- a/src/fs.h +++ b/src/fs.h @@ -5,46 +5,42 @@ #ifndef BITCOIN_FS_H #define BITCOIN_FS_H -#include -#include -#if defined WIN32 && defined __GLIBCXX__ -#include -#endif - -#include -#include #include +#include +#include +#include +#include +#include +#include +#include + /** Filesystem operations and types */ namespace fs { -using namespace boost::filesystem; +using namespace std::filesystem; /** - * Path class wrapper to prepare application code for transition from - * boost::filesystem library to std::filesystem implementation. The main - * purpose of the class is to define fs::path::u8string() and fs::u8path() - * functions not present in boost. It also blocks calls to the - * fs::path(std::string) implicit constructor and the fs::path::string() - * method, which worked well in the boost::filesystem implementation, but have - * unsafe and unpredictable behavior on Windows in the std::filesystem - * implementation (see implementation note in \ref PathToString for details). + * Path class wrapper to block calls to the fs::path(std::string) implicit + * constructor and the fs::path::string() method, which have unsafe and + * unpredictable behavior on Windows (see implementation note in + * \ref PathToString for details) */ -class path : public boost::filesystem::path +class path : public std::filesystem::path { public: - using boost::filesystem::path::path; + using std::filesystem::path::path; // Allow path objects arguments for compatibility. - path(boost::filesystem::path path) : boost::filesystem::path::path(std::move(path)) {} - path& operator=(boost::filesystem::path path) { boost::filesystem::path::operator=(std::move(path)); return *this; } - path& operator/=(boost::filesystem::path path) { boost::filesystem::path::operator/=(std::move(path)); return *this; } + path(std::filesystem::path path) : std::filesystem::path::path(std::move(path)) {} + path& operator=(std::filesystem::path path) { std::filesystem::path::operator=(std::move(path)); return *this; } + path& operator/=(std::filesystem::path path) { std::filesystem::path::operator/=(std::move(path)); return *this; } // Allow literal string arguments, which are safe as long as the literals are ASCII. - path(const char* c) : boost::filesystem::path(c) {} - path& operator=(const char* c) { boost::filesystem::path::operator=(c); return *this; } - path& operator/=(const char* c) { boost::filesystem::path::operator/=(c); return *this; } - path& append(const char* c) { boost::filesystem::path::append(c); return *this; } + path(const char* c) : std::filesystem::path(c) {} + path& operator=(const char* c) { std::filesystem::path::operator=(c); return *this; } + path& operator/=(const char* c) { std::filesystem::path::operator/=(c); return *this; } + path& append(const char* c) { std::filesystem::path::append(c); return *this; } // Disallow std::string arguments to avoid locale-dependent decoding on windows. path(std::string) = delete; @@ -55,52 +51,48 @@ public: // Disallow std::string conversion method to avoid locale-dependent encoding on windows. std::string string() const = delete; - // Define UTF-8 string conversion method not present in boost::filesystem but present in std::filesystem. - std::string u8string() const { return boost::filesystem::path::string(); } + // Required for path overloads in . + // See https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=96e0367ead5d8dcac3bec2865582e76e2fbab190 + path& make_preferred() { std::filesystem::path::make_preferred(); return *this; } + path filename() const { return std::filesystem::path::filename(); } }; -// Define UTF-8 string conversion function not present in boost::filesystem but present in std::filesystem. -static inline path u8path(const std::string& string) -{ - return boost::filesystem::path(string); -} - -// Disallow implicit std::string conversion for system_complete to avoid +// Disallow implicit std::string conversion for absolute to avoid // locale-dependent encoding on windows. -static inline path system_complete(const path& p) +static inline path absolute(const path& p) { - return boost::filesystem::system_complete(p); + return std::filesystem::absolute(p); } // Disallow implicit std::string conversion for exists to avoid // locale-dependent encoding on windows. static inline bool exists(const path& p) { - return boost::filesystem::exists(p); + return std::filesystem::exists(p); } // Allow explicit quoted stream I/O. static inline auto quoted(const std::string& s) { - return boost::io::quoted(s, '&'); + return std::quoted(s, '"', '&'); } // Allow safe path append operations. static inline path operator+(path p1, path p2) { - p1 += static_cast(p2); + p1 += std::move(p2); return p1; } // Disallow implicit std::string conversion for copy_file // to avoid locale-dependent encoding on Windows. -static inline void copy_file(const path& from, const path& to, copy_option options) +static inline bool copy_file(const path& from, const path& to, copy_options options) { - boost::filesystem::copy_file(from, to, options); + return std::filesystem::copy_file(from, to, options); } /** - * Convert path object to byte string. On POSIX, paths natively are byte + * Convert path object to a byte string. On POSIX, paths natively are byte * strings, so this is trivial. On Windows, paths natively are Unicode, so an * encoding step is necessary. The inverse of \ref PathToString is \ref * PathFromString. The strings returned and parsed by these functions can be @@ -112,7 +104,7 @@ static inline void copy_file(const path& from, const path& to, copy_option optio * appropriate to use in applications requiring UTF-8, where * fs::path::u8string() and fs::u8path() methods should be used instead. Other * applications could require still different encodings. For example, JSON, XML, - * or URI applications might prefer to use higher level escapes (\uXXXX or + * or URI applications might prefer to use higher-level escapes (\uXXXX or * &XXXX; or %XX) instead of multibyte encoding. Rust, Python, Java applications * may require encoding paths with their respective UTF-8 derivatives WTF-8, * PEP-383, and CESU-8 (see https://en.wikipedia.org/wiki/UTF-8#Derivatives). @@ -133,7 +125,7 @@ static inline std::string PathToString(const path& path) return path.u8string(); #else static_assert(std::is_same::value, "PathToString not implemented on this platform"); - return path.boost::filesystem::path::string(); + return path.std::filesystem::path::string(); #endif } @@ -145,7 +137,7 @@ static inline path PathFromString(const std::string& string) #ifdef WIN32 return u8path(string); #else - return boost::filesystem::path(string); + return std::filesystem::path(string); #endif } } // namespace fs @@ -186,60 +178,12 @@ namespace fsbridge { }; std::string get_filesystem_error_message(const fs::filesystem_error& e); - - // GNU libstdc++ specific workaround for opening UTF-8 paths on Windows. - // - // On Windows, it is only possible to reliably access multibyte file paths through - // `wchar_t` APIs, not `char` APIs. But because the C++ standard doesn't - // require ifstream/ofstream `wchar_t` constructors, and the GNU library doesn't - // provide them (in contrast to the Microsoft C++ library, see - // https://stackoverflow.com/questions/821873/how-to-open-an-stdfstream-ofstream-or-ifstream-with-a-unicode-filename/822032#822032), - // Boost is forced to fall back to `char` constructors which may not work properly. - // - // Work around this issue by creating stream objects with `_wfopen` in - // combination with `__gnu_cxx::stdio_filebuf`. This workaround can be removed - // with an upgrade to C++17, where streams can be constructed directly from - // `std::filesystem::path` objects. - -#if defined WIN32 && defined __GLIBCXX__ - class ifstream : public std::istream - { - public: - ifstream() = default; - explicit ifstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in) { open(p, mode); } - ~ifstream() { close(); } - void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in); - bool is_open() { return m_filebuf.is_open(); } - void close(); - - private: - __gnu_cxx::stdio_filebuf m_filebuf; - FILE* m_file = nullptr; - }; - class ofstream : public std::ostream - { - public: - ofstream() = default; - explicit ofstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out) { open(p, mode); } - ~ofstream() { close(); } - void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out); - bool is_open() { return m_filebuf.is_open(); } - void close(); - - private: - __gnu_cxx::stdio_filebuf m_filebuf; - FILE* m_file = nullptr; - }; -#else // !(WIN32 && __GLIBCXX__) - typedef fs::ifstream ifstream; - typedef fs::ofstream ofstream; -#endif // WIN32 && __GLIBCXX__ }; // Disallow path operator<< formatting in tinyformat to avoid locale-dependent // encoding on windows. namespace tinyformat { -template<> inline void formatValue(std::ostream&, const char*, const char*, int, const boost::filesystem::path&) = delete; +template<> inline void formatValue(std::ostream&, const char*, const char*, int, const std::filesystem::path&) = delete; template<> inline void formatValue(std::ostream&, const char*, const char*, int, const fs::path&) = delete; } // namespace tinyformat diff --git a/src/init.cpp b/src/init.cpp index 015e17596c3..84564cf2aa7 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -72,10 +72,13 @@ #include #include +#include +#include +#include +#include #include #include -#include -#include +#include #include #include @@ -137,7 +140,7 @@ static fs::path GetPidFile(const ArgsManager& args) [[nodiscard]] static bool CreatePidFile(const ArgsManager& args) { - fsbridge::ofstream file{GetPidFile(args)}; + std::ofstream file{GetPidFile(args)}; if (file) { #ifdef WIN32 tfm::format(file, "%d\n", GetCurrentProcessId()); diff --git a/src/logging.cpp b/src/logging.cpp index 6edcebf87e2..764941c8ea5 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include #include #include diff --git a/src/logging.h b/src/logging.h index 31f0bdc6906..710e6c4c322 100644 --- a/src/logging.h +++ b/src/logging.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include diff --git a/src/net.cpp b/src/net.cpp index be56d1e2d25..68569560cef 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c6c8f7b7a6a..dc73bcd911d 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -66,6 +67,10 @@ #include #include +#include +#include +#include +#include #if defined(Q_OS_MAC) @@ -426,7 +431,7 @@ bool openBitcoinConf() fs::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); /* Create the file */ - fsbridge::ofstream configFile(pathConfig, std::ios_base::app); + std::ofstream configFile{pathConfig, std::ios_base::app}; if (!configFile.good()) return false; @@ -586,7 +591,7 @@ fs::path static GetAutostartFilePath() bool GetStartOnSystemStartup() { - fsbridge::ifstream optionFile(GetAutostartFilePath()); + std::ifstream optionFile{GetAutostartFilePath()}; if (!optionFile.good()) return false; // Scan through file for "Hidden=true": @@ -617,7 +622,7 @@ bool SetStartOnSystemStartup(bool fAutoStart) fs::create_directories(GetAutostartDir()); - fsbridge::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc); + std::ofstream optionFile{GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc}; if (!optionFile.good()) return false; std::string chain = gArgs.GetChainName(); diff --git a/src/qt/psbtoperationsdialog.cpp b/src/qt/psbtoperationsdialog.cpp index d328290cbcc..6880c157c0d 100644 --- a/src/qt/psbtoperationsdialog.cpp +++ b/src/qt/psbtoperationsdialog.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -15,7 +16,9 @@ #include #include +#include #include +#include using node::AnalyzePSBT; using node::DEFAULT_MAX_RAW_TX_FEE_RATE; @@ -158,7 +161,7 @@ void PSBTOperationsDialog::saveTransaction() { if (filename.isEmpty()) { return; } - fsbridge::ofstream out{filename.toLocal8Bit().data(), fsbridge::ofstream::out | fsbridge::ofstream::binary}; + std::ofstream out{filename.toLocal8Bit().data(), std::ofstream::out | std::ofstream::binary}; out << ssTx.str(); out.close(); showStatus(tr("PSBT saved to disk."), StatusLevel::INFO); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 1206f610cd2..e37168830ed 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -29,7 +29,10 @@ #include #include +#include #include +#include +#include #include #include @@ -509,7 +512,7 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked) if (filename.isEmpty()) { return; } - fsbridge::ofstream out{filename.toLocal8Bit().data(), fsbridge::ofstream::out | fsbridge::ofstream::binary}; + std::ofstream out{filename.toLocal8Bit().data(), std::ofstream::out | std::ofstream::binary}; out << ssTx.str(); out.close(); Q_EMIT message(tr("PSBT saved"), "PSBT saved to disk", CClientUIInterface::MSG_INFORMATION); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index fba83dd510e..08190f0b9f8 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -14,6 +15,8 @@ #include #include +#include +#include #include #include @@ -210,7 +213,7 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard) Q_EMIT message(tr("Error"), tr("PSBT file must be smaller than 100 MiB"), CClientUIInterface::MSG_ERROR); return; } - fsbridge::ifstream in{filename.toLocal8Bit().data(), std::ios::binary}; + std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary}; data = std::string(std::istreambuf_iterator{in}, {}); } diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp index fbb4e5ddd04..95a7c25b939 100644 --- a/src/rpc/request.cpp +++ b/src/rpc/request.cpp @@ -12,6 +12,11 @@ #include #include +#include +#include +#include +#include + /** * JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, * but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were @@ -83,7 +88,7 @@ bool GenerateAuthCookie(std::string *cookie_out) /** the umask determines what permissions are used to create this file - * these are set to 077 in init.cpp unless overridden with -sysperms. */ - fsbridge::ofstream file; + std::ofstream file; fs::path filepath_tmp = GetAuthCookieFile(true); file.open(filepath_tmp); if (!file.is_open()) { @@ -107,7 +112,7 @@ bool GenerateAuthCookie(std::string *cookie_out) bool GetAuthCookie(std::string *cookie_out) { - fsbridge::ifstream file; + std::ifstream file; std::string cookie; fs::path filepath = GetAuthCookieFile(); file.open(filepath); diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp index d3389c30eb6..1256395849b 100644 --- a/src/test/fs_tests.cpp +++ b/src/test/fs_tests.cpp @@ -9,6 +9,10 @@ #include +#include +#include +#include + BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(fsbridge_pathtostring) @@ -45,37 +49,37 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream) fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃"; fs::path tmpfile2 = tmpfolder / "fs_tests_₿_🏃"; { - fsbridge::ofstream file(tmpfile1); + std::ofstream file{tmpfile1}; file << "bitcoin"; } { - fsbridge::ifstream file(tmpfile2); + std::ifstream file{tmpfile2}; std::string input_buffer; file >> input_buffer; BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); } { - fsbridge::ifstream file(tmpfile1, std::ios_base::in | std::ios_base::ate); + std::ifstream file{tmpfile1, std::ios_base::in | std::ios_base::ate}; std::string input_buffer; file >> input_buffer; BOOST_CHECK_EQUAL(input_buffer, ""); } { - fsbridge::ofstream file(tmpfile2, std::ios_base::out | std::ios_base::app); + std::ofstream file{tmpfile2, std::ios_base::out | std::ios_base::app}; file << "tests"; } { - fsbridge::ifstream file(tmpfile1); + std::ifstream file{tmpfile1}; std::string input_buffer; file >> input_buffer; BOOST_CHECK_EQUAL(input_buffer, "bitcointests"); } { - fsbridge::ofstream file(tmpfile2, std::ios_base::out | std::ios_base::trunc); + std::ofstream file{tmpfile2, std::ios_base::out | std::ios_base::trunc}; file << "bitcoin"; } { - fsbridge::ifstream file(tmpfile1); + std::ifstream file{tmpfile1}; std::string input_buffer; file >> input_buffer; BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index 60c48e7c228..a490bbfa1d2 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -12,9 +13,12 @@ #include #include +#include #include +#include #include #include +#include #include #include @@ -80,7 +84,7 @@ void initialize() } if (const char* out_path = std::getenv("WRITE_ALL_FUZZ_TARGETS_AND_ABORT")) { std::cout << "Writing all fuzz target names to '" << out_path << "'." << std::endl; - fsbridge::ofstream out_stream{out_path, std::ios::binary}; + std::ofstream out_stream{out_path, std::ios::binary}; for (const auto& t : FuzzTargets()) { if (std::get<2>(t.second)) continue; out_stream << t.first << std::endl; diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp index 19ca1f0c996..e513f1883c8 100644 --- a/src/test/fuzz/utxo_snapshot.cpp +++ b/src/test/fuzz/utxo_snapshot.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 4906bd23868..c453f225946 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -24,7 +24,8 @@ #include