Merge bitcoin/bitcoin#20744: Use std::filesystem. Remove Boost Filesystem & System

07269321f3 build: remove Boost::system usage (fanquake)
b87f9c5edf build: remove boost::filesystem usage (Kiminuo)
41d7166c8a refactor: replace boost::filesystem with std::filesystem (Kiminuo)
ffc89d1f21 build: add support for std::filesystem (fanquake)

Pull request description:

  This PR replaces our Boost Filesystem usage with [`std::filesystem`](https://en.cppreference.com/w/cpp/filesystem) and includes dropping Boost System as a dependency. It includes a squashed down version of the changes from #19245.

  [A macro has been added](https://github.com/bitcoin/bitcoin/commit/7002c4ade0148c3273659208ae517b79822b289d), modelling how we check for `-latomic` to facilitate linking with `-lstdc++fs` when required. This is  ~GCC < 9.1 & ~Clang < 9.0, however not always. i.e you could be using Clang 7 on top of a GCC 9 installation (i.e Ubuntu Focal) and use `<filesystem>` without passing any additional arguments. I've tested this with GCC 8 on Bionic, Clang 7 on Focal & with Apple Clang 12.0.0 on macOS.

  Guix build:
  ```bash
  bash-5.1# find guix-build-$(git rev-parse --short=12 HEAD)/output/ -type f -print0 | env LC_ALL=C sort -z | xargs -r0 sha256sum
  c1f9b326f9be4140f00cebeae5ff8de428a2fb8ecced539fcc36c53f53bfecf4  guix-build-07269321f38e/output/aarch64-linux-gnu/SHA256SUMS.part
  b44aca3bcf5ea92a3a6c48c24d6f85576f425f59b73528d4d00c20e950cf2128  guix-build-07269321f38e/output/aarch64-linux-gnu/bitcoin-07269321f38e-aarch64-linux-gnu-debug.tar.gz
  27a5553f7bd14797293fc40c5fb131c91e98a61d5481a283f13a1d0497eb5ed8  guix-build-07269321f38e/output/aarch64-linux-gnu/bitcoin-07269321f38e-aarch64-linux-gnu.tar.gz
  99e55a88823f6095864a09c9eaa824e24d9ec527380eb394f751c7205b930f69  guix-build-07269321f38e/output/arm-linux-gnueabihf/SHA256SUMS.part
  b720b2724fa47fde584f58ed3b587f1d1183523540777fd367ab7e582605cfea  guix-build-07269321f38e/output/arm-linux-gnueabihf/bitcoin-07269321f38e-arm-linux-gnueabihf-debug.tar.gz
  c19c247f4e9e0d7f888ac8ba9de1c12d382f48fa828a685d4fe02818a18abd1f  guix-build-07269321f38e/output/arm-linux-gnueabihf/bitcoin-07269321f38e-arm-linux-gnueabihf.tar.gz
  55b49ccb38de03bb95101354a16fd8d2190abede5ccc0d9b00b40c0cd526a2f6  guix-build-07269321f38e/output/arm64-apple-darwin/SHA256SUMS.part
  baa44752470a6be9acae1c2f8fd1b9bc37afb00971787ea11fbaeddc9ab7c4aa  guix-build-07269321f38e/output/arm64-apple-darwin/bitcoin-07269321f38e-arm64-apple-darwin.tar.gz
  ad7df4d8026d5bcce1321cdccc2e1820e8a8bb7e1064ed16e20a7ea354057fd2  guix-build-07269321f38e/output/arm64-apple-darwin/bitcoin-07269321f38e-osx-unsigned.dmg
  f342066dc34a14d67c47779a2413a14633a996e8e7ddca89ae0184e23ef99efd  guix-build-07269321f38e/output/arm64-apple-darwin/bitcoin-07269321f38e-osx-unsigned.tar.gz
  f6905346a5d48f57805fb062d0247ab5007c89047070a0b3125941dd1a2b8aa6  guix-build-07269321f38e/output/dist-archive/bitcoin-07269321f38e.tar.gz
  a1f6c4b2b118dbd89770801f0bcffd2218b82df408cd227e34c40493469bb7a2  guix-build-07269321f38e/output/powerpc64-linux-gnu/SHA256SUMS.part
  ba8359426e523bf013d93579c1bedc57380214c8170a9743b64ec1a8a3bbccbf  guix-build-07269321f38e/output/powerpc64-linux-gnu/bitcoin-07269321f38e-powerpc64-linux-gnu-debug.tar.gz
  b0bb500c274a683ea28ecbc1e8f18c618a9f8acb00045f80ae43c515288402c0  guix-build-07269321f38e/output/powerpc64-linux-gnu/bitcoin-07269321f38e-powerpc64-linux-gnu.tar.gz
  38c85e9589e092cd3aa08996aa383c0ccd5c73208943389741355a6eb7f72537  guix-build-07269321f38e/output/powerpc64le-linux-gnu/SHA256SUMS.part
  50fcba7942ff48d91e84c093fda0affc17e46167fe1d5137c6e14c5c41f289d1  guix-build-07269321f38e/output/powerpc64le-linux-gnu/bitcoin-07269321f38e-powerpc64le-linux-gnu-debug.tar.gz
  fa08ef1ceca072e014faa95ffee945954b2976fa28f90926b87ab0e5f15f8ca5  guix-build-07269321f38e/output/powerpc64le-linux-gnu/bitcoin-07269321f38e-powerpc64le-linux-gnu.tar.gz
  e52dd80a9c306d6aeb544acaa1f4ed560b6b92b5184764a05026d45451aa2e94  guix-build-07269321f38e/output/riscv64-linux-gnu/SHA256SUMS.part
  864e0a16c485b4159cec3ee0a83b046f1b1c3bc821670011c5ac5cd09ddfb91f  guix-build-07269321f38e/output/riscv64-linux-gnu/bitcoin-07269321f38e-riscv64-linux-gnu-debug.tar.gz
  4a061172181322e7ad0cf06405bf74f4c8683eaba3a67ecfd46158cba7627f62  guix-build-07269321f38e/output/riscv64-linux-gnu/bitcoin-07269321f38e-riscv64-linux-gnu.tar.gz
  876d82251853205420dffe7237523fc6ee3d09f78bf74cc03dc71f548446f335  guix-build-07269321f38e/output/x86_64-apple-darwin/SHA256SUMS.part
  3f82b2e62c60eee68e7b8fc28e4792e069e3c2cd780ee2d67290ca422cdbc47c  guix-build-07269321f38e/output/x86_64-apple-darwin/bitcoin-07269321f38e-osx-unsigned.dmg
  4ccdd4c410cac9d627e54ce83ee4816608681735da3cb93c60c5eb70ca86337a  guix-build-07269321f38e/output/x86_64-apple-darwin/bitcoin-07269321f38e-osx-unsigned.tar.gz
  2179d36b2f60e28c15262d4e51f27465b5ae077f60e550345e125683ca611066  guix-build-07269321f38e/output/x86_64-apple-darwin/bitcoin-07269321f38e-osx64.tar.gz
  b377e72fe84b6a982b8d414d60c85e6319523dff50dc852a0ba907f6d850ddd0  guix-build-07269321f38e/output/x86_64-linux-gnu/SHA256SUMS.part
  8547e2f582ce05ae6a6224793b64efb2eb63f2816bf0bed5d53fcc4786274597  guix-build-07269321f38e/output/x86_64-linux-gnu/bitcoin-07269321f38e-x86_64-linux-gnu-debug.tar.gz
  83b64805aa39f31a6fa4c2ed41e029c3be084e6dea06b90fac1ebca5c95bce29  guix-build-07269321f38e/output/x86_64-linux-gnu/bitcoin-07269321f38e-x86_64-linux-gnu.tar.gz
  ```

ACKs for top commit:
  laanwj:
    Code review ACK 07269321f3
  MarcoFalke:
    Concept ACK 07269321f3 🎀
  hebasto:
    ACK 07269321f3

Tree-SHA512: 1f11614467d2013ed799f23c1c14716570f4c798f231671c731a69c7773ef32a0aa2acc69d4ac2f1f176ef6f160f56566c6bd75c9c059a0e82ab4c58d2b2a750
This commit is contained in:
MarcoFalke committed 2022-02-03 15:50:10 +01:00
commit 3ace3a17c9
50 files changed
+252 -563

No files matched your search

-118
View File
@@ -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 <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_FILESYSTEM_LIB)
#
# And sets:
#
# HAVE_BOOST_FILESYSTEM
#
# LICENSE
#
# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2009 Michael Tindal
# Copyright (c) 2009 Roman Rybalko <libtorrent@romanr.info>
#
# 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 <boost/filesystem/path.hpp>]],
[[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
])
-121
View File
@@ -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
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_SYSTEM_LIB)
#
# And sets:
#
# HAVE_BOOST_SYSTEM
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2008 Michael Tindal
# Copyright (c) 2008 Daniel Casimiro <dan.casimiro@gmail.com>
#
# 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_code.hpp>]],
[[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
])
+47
View File
@@ -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 <filesystem>
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
])
-6
View File
@@ -44,15 +44,9 @@
/* define if the Boost library is available */ /* define if the Boost library is available */
#define HAVE_BOOST /**/ #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 if external signer support is enabled (requires Boost::Process) */
#define ENABLE_EXTERNAL_SIGNER /**/ #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 if the Boost::Unit_Test_Framework library is available */
#define HAVE_BOOST_UNIT_TEST_FRAMEWORK /**/ #define HAVE_BOOST_UNIT_TEST_FRAMEWORK /**/
-1
View File
@@ -3,7 +3,6 @@
"version-string": "1", "version-string": "1",
"dependencies": [ "dependencies": [
"berkeleydb", "berkeleydb",
"boost-filesystem",
"boost-multi-index", "boost-multi-index",
"boost-process", "boost-process",
"boost-signals2", "boost-signals2",
+1 -1
View File
@@ -7,7 +7,7 @@
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_asan 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 DOCKER_NAME_TAG=ubuntu:22.04
export NO_DEPENDS=1 export NO_DEPENDS=1
export GOAL="install" export GOAL="install"
+1 -1
View File
@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8
export DOCKER_NAME_TAG="ubuntu:20.04" export DOCKER_NAME_TAG="ubuntu:20.04"
export CONTAINER_NAME=ci_native_fuzz 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 NO_DEPENDS=1
export RUN_UNIT_TESTS=false export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false export RUN_FUNCTIONAL_TESTS=false
@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8
export DOCKER_NAME_TAG="ubuntu:20.04" export DOCKER_NAME_TAG="ubuntu:20.04"
export CONTAINER_NAME=ci_native_fuzz_valgrind 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 NO_DEPENDS=1
export RUN_UNIT_TESTS=false export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false export RUN_FUNCTIONAL_TESTS=false
+1 -1
View File
@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8
export DOCKER_NAME_TAG="ubuntu:20.04" export DOCKER_NAME_TAG="ubuntu:20.04"
export CONTAINER_NAME=ci_native_valgrind 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 USE_VALGRIND=1
export NO_DEPENDS=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 export TEST_RUNNER_EXTRA="--nosandbox --exclude rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547
+4 -3
View File
@@ -83,6 +83,9 @@ AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
dnl Check if -latomic is required for <std::atomic> dnl Check if -latomic is required for <std::atomic>
CHECK_ATOMIC 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 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. dnl that we get the same -std flags for both.
m4_ifdef([AC_PROG_OBJCXX],[ m4_ifdef([AC_PROG_OBJCXX],[
@@ -1404,14 +1407,12 @@ if test "$use_boost" = "yes"; then
if test "$want_boost" = "no"; then if test "$want_boost" = "no"; then
AC_MSG_ERROR([only libbitcoinconsensus can be built without Boost]) AC_MSG_ERROR([only libbitcoinconsensus can be built without Boost])
fi fi
AX_BOOST_SYSTEM
AX_BOOST_FILESYSTEM
if test "$suppress_external_warnings" != "no"; then if test "$suppress_external_warnings" != "no"; then
BOOST_CPPFLAGS=SUPPRESS_WARNINGS($BOOST_CPPFLAGS) BOOST_CPPFLAGS=SUPPRESS_WARNINGS($BOOST_CPPFLAGS)
fi fi
BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB" BOOST_LIBS="$BOOST_LDFLAGS"
fi fi
if test "$use_external_signer" != "no"; then if test "$use_external_signer" != "no"; then
-21
View File
@@ -118,12 +118,6 @@
fun:__wcsnlen_sse4_1 fun:__wcsnlen_sse4_1
fun:wcsnrtombs fun:wcsnrtombs
} }
{
Suppress wcsnrtombs warning (remove after removing boost::fs)
Memcheck:Cond
...
fun:_ZN5boost10filesystem6detail11unique_pathERKNS0_4pathEPNS_6system10error_codeE
}
{ {
Suppress boost warning Suppress boost warning
Memcheck:Leak Memcheck:Leak
@@ -134,21 +128,6 @@
fun:_ZN5boost9unit_test14unit_test_mainEPFbvEiPPc fun:_ZN5boost9unit_test14unit_test_mainEPFbvEiPPc
fun:main 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 Suppress boost still reachable memory warning
Memcheck:Leak Memcheck:Leak
+1 -1
View File
@@ -22,7 +22,7 @@ $(package)_toolset_$(host_os)=clang
else else
$(package)_toolset_$(host_os)=gcc $(package)_toolset_$(host_os)=gcc
endif endif
$(package)_config_libraries=filesystem,system,test $(package)_config_libraries=test
$(package)_cxxflags+=-std=c++17 $(package)_cxxflags+=-std=c++17
$(package)_cxxflags_linux=-fPIC $(package)_cxxflags_linux=-fPIC
$(package)_cxxflags_freebsd=-fPIC $(package)_cxxflags_freebsd=-fPIC
+1 -1
View File
@@ -82,7 +82,7 @@ Build requirements:
Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies: 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: SQLite is required for the descriptor wallet:
+1
View File
@@ -9,6 +9,7 @@
#include <chainparams.h> #include <chainparams.h>
#include <clientversion.h> #include <clientversion.h>
#include <cstdint> #include <cstdint>
#include <fs.h>
#include <hash.h> #include <hash.h>
#include <logging/timer.h> #include <logging/timer.h>
#include <netbase.h> #include <netbase.h>
+2 -1
View File
@@ -8,6 +8,7 @@
#include <test/util/setup_common.h> #include <test/util/setup_common.h>
#include <chrono> #include <chrono>
#include <fstream>
#include <functional> #include <functional>
#include <iostream> #include <iostream>
#include <map> #include <map>
@@ -29,7 +30,7 @@ void GenerateTemplateResults(const std::vector<ankerl::nanobench::Result>& bench
// nothing to write, bail out // nothing to write, bail out
return; return;
} }
fsbridge::ofstream fout{fs::PathFromString(filename)}; std::ofstream fout{fs::PathFromString(filename)};
if (fout.is_open()) { if (fout.is_open()) {
ankerl::nanobench::render(tpl, benchmarkResults, fout); ankerl::nanobench::render(tpl, benchmarkResults, fout);
} else { } else {
+1 -115
View File
@@ -37,7 +37,7 @@ FILE *fopen(const fs::path& p, const char *mode)
fs::path AbsPathJoin(const fs::path& base, const fs::path& path) fs::path AbsPathJoin(const fs::path& base, const fs::path& path)
{ {
assert(base.is_absolute()); assert(base.is_absolute());
return fs::absolute(path, base); return path.empty() ? base : fs::path(base / path);
} }
#ifndef WIN32 #ifndef WIN32
@@ -153,118 +153,4 @@ std::string get_filesystem_error_message(const fs::filesystem_error& e)
#endif #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<char>(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<char>(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 } // fsbridge
+39 -95
View File
@@ -5,46 +5,42 @@
#ifndef BITCOIN_FS_H #ifndef BITCOIN_FS_H
#define BITCOIN_FS_H #define BITCOIN_FS_H
#include <stdio.h>
#include <string>
#if defined WIN32 && defined __GLIBCXX__
#include <ext/stdio_filebuf.h>
#endif
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <tinyformat.h> #include <tinyformat.h>
#include <cstdio>
#include <filesystem>
#include <iomanip>
#include <ios>
#include <ostream>
#include <string>
#include <utility>
/** Filesystem operations and types */ /** Filesystem operations and types */
namespace fs { namespace fs {
using namespace boost::filesystem; using namespace std::filesystem;
/** /**
* Path class wrapper to prepare application code for transition from * Path class wrapper to block calls to the fs::path(std::string) implicit
* boost::filesystem library to std::filesystem implementation. The main * constructor and the fs::path::string() method, which have unsafe and
* purpose of the class is to define fs::path::u8string() and fs::u8path() * unpredictable behavior on Windows (see implementation note in
* functions not present in boost. It also blocks calls to the * \ref PathToString for details)
* 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).
*/ */
class path : public boost::filesystem::path class path : public std::filesystem::path
{ {
public: public:
using boost::filesystem::path::path; using std::filesystem::path::path;
// Allow path objects arguments for compatibility. // Allow path objects arguments for compatibility.
path(boost::filesystem::path path) : boost::filesystem::path::path(std::move(path)) {} path(std::filesystem::path path) : std::filesystem::path::path(std::move(path)) {}
path& operator=(boost::filesystem::path path) { boost::filesystem::path::operator=(std::move(path)); return *this; } path& operator=(std::filesystem::path path) { std::filesystem::path::operator=(std::move(path)); return *this; }
path& operator/=(boost::filesystem::path path) { boost::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. // Allow literal string arguments, which are safe as long as the literals are ASCII.
path(const char* c) : boost::filesystem::path(c) {} path(const char* c) : std::filesystem::path(c) {}
path& operator=(const char* c) { boost::filesystem::path::operator=(c); return *this; } path& operator=(const char* c) { std::filesystem::path::operator=(c); return *this; }
path& operator/=(const char* c) { boost::filesystem::path::operator/=(c); return *this; } path& operator/=(const char* c) { std::filesystem::path::operator/=(c); return *this; }
path& append(const char* c) { boost::filesystem::path::append(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. // Disallow std::string arguments to avoid locale-dependent decoding on windows.
path(std::string) = delete; path(std::string) = delete;
@@ -55,52 +51,48 @@ public:
// Disallow std::string conversion method to avoid locale-dependent encoding on windows. // Disallow std::string conversion method to avoid locale-dependent encoding on windows.
std::string string() const = delete; std::string string() const = delete;
// Define UTF-8 string conversion method not present in boost::filesystem but present in std::filesystem. // Required for path overloads in <fstream>.
std::string u8string() const { return boost::filesystem::path::string(); } // 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. // Disallow implicit std::string conversion for absolute to avoid
static inline path u8path(const std::string& string)
{
return boost::filesystem::path(string);
}
// Disallow implicit std::string conversion for system_complete to avoid
// locale-dependent encoding on windows. // 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 // Disallow implicit std::string conversion for exists to avoid
// locale-dependent encoding on windows. // locale-dependent encoding on windows.
static inline bool exists(const path& p) static inline bool exists(const path& p)
{ {
return boost::filesystem::exists(p); return std::filesystem::exists(p);
} }
// Allow explicit quoted stream I/O. // Allow explicit quoted stream I/O.
static inline auto quoted(const std::string& s) static inline auto quoted(const std::string& s)
{ {
return boost::io::quoted(s, '&'); return std::quoted(s, '"', '&');
} }
// Allow safe path append operations. // Allow safe path append operations.
static inline path operator+(path p1, path p2) static inline path operator+(path p1, path p2)
{ {
p1 += static_cast<boost::filesystem::path&&>(p2); p1 += std::move(p2);
return p1; return p1;
} }
// Disallow implicit std::string conversion for copy_file // Disallow implicit std::string conversion for copy_file
// to avoid locale-dependent encoding on Windows. // 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 * strings, so this is trivial. On Windows, paths natively are Unicode, so an
* encoding step is necessary. The inverse of \ref PathToString is \ref * encoding step is necessary. The inverse of \ref PathToString is \ref
* PathFromString. The strings returned and parsed by these functions can be * 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 * appropriate to use in applications requiring UTF-8, where
* fs::path::u8string() and fs::u8path() methods should be used instead. Other * fs::path::u8string() and fs::u8path() methods should be used instead. Other
* applications could require still different encodings. For example, JSON, XML, * 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 * &XXXX; or %XX) instead of multibyte encoding. Rust, Python, Java applications
* may require encoding paths with their respective UTF-8 derivatives WTF-8, * 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). * 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(); return path.u8string();
#else #else
static_assert(std::is_same<path::string_type, std::string>::value, "PathToString not implemented on this platform"); static_assert(std::is_same<path::string_type, std::string>::value, "PathToString not implemented on this platform");
return path.boost::filesystem::path::string(); return path.std::filesystem::path::string();
#endif #endif
} }
@@ -145,7 +137,7 @@ static inline path PathFromString(const std::string& string)
#ifdef WIN32 #ifdef WIN32
return u8path(string); return u8path(string);
#else #else
return boost::filesystem::path(string); return std::filesystem::path(string);
#endif #endif
} }
} // namespace fs } // namespace fs
@@ -186,60 +178,12 @@ namespace fsbridge {
}; };
std::string get_filesystem_error_message(const fs::filesystem_error& e); 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<char> 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<char> 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 // Disallow path operator<< formatting in tinyformat to avoid locale-dependent
// encoding on windows. // encoding on windows.
namespace tinyformat { 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; template<> inline void formatValue(std::ostream&, const char*, const char*, int, const fs::path&) = delete;
} // namespace tinyformat } // namespace tinyformat
+6 -3
View File
@@ -72,10 +72,13 @@
#include <validationinterface.h> #include <validationinterface.h>
#include <walletinitinterface.h> #include <walletinitinterface.h>
#include <condition_variable>
#include <cstdint>
#include <cstdio>
#include <fstream>
#include <functional> #include <functional>
#include <set> #include <set>
#include <stdint.h> #include <string>
#include <stdio.h>
#include <thread> #include <thread>
#include <vector> #include <vector>
@@ -137,7 +140,7 @@ static fs::path GetPidFile(const ArgsManager& args)
[[nodiscard]] static bool CreatePidFile(const ArgsManager& args) [[nodiscard]] static bool CreatePidFile(const ArgsManager& args)
{ {
fsbridge::ofstream file{GetPidFile(args)}; std::ofstream file{GetPidFile(args)};
if (file) { if (file) {
#ifdef WIN32 #ifdef WIN32
tfm::format(file, "%d\n", GetCurrentProcessId()); tfm::format(file, "%d\n", GetCurrentProcessId());
+1
View File
@@ -3,6 +3,7 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <fs.h>
#include <logging.h> #include <logging.h>
#include <util/threadnames.h> #include <util/threadnames.h>
#include <util/string.h> #include <util/string.h>
+1
View File
@@ -13,6 +13,7 @@
#include <atomic> #include <atomic>
#include <cstdint> #include <cstdint>
#include <functional>
#include <list> #include <list>
#include <mutex> #include <mutex>
#include <string> #include <string>
+1
View File
@@ -16,6 +16,7 @@
#include <compat.h> #include <compat.h>
#include <consensus/consensus.h> #include <consensus/consensus.h>
#include <crypto/sha256.h> #include <crypto/sha256.h>
#include <fs.h>
#include <i2p.h> #include <i2p.h>
#include <net_permissions.h> #include <net_permissions.h>
#include <netaddress.h> #include <netaddress.h>
+8 -3
View File
@@ -12,6 +12,7 @@
#include <base58.h> #include <base58.h>
#include <chainparams.h> #include <chainparams.h>
#include <fs.h>
#include <interfaces/node.h> #include <interfaces/node.h>
#include <key_io.h> #include <key_io.h>
#include <policy/policy.h> #include <policy/policy.h>
@@ -66,6 +67,10 @@
#include <cassert> #include <cassert>
#include <chrono> #include <chrono>
#include <exception>
#include <fstream>
#include <string>
#include <vector>
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
@@ -426,7 +431,7 @@ bool openBitcoinConf()
fs::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); fs::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
/* Create the file */ /* Create the file */
fsbridge::ofstream configFile(pathConfig, std::ios_base::app); std::ofstream configFile{pathConfig, std::ios_base::app};
if (!configFile.good()) if (!configFile.good())
return false; return false;
@@ -586,7 +591,7 @@ fs::path static GetAutostartFilePath()
bool GetStartOnSystemStartup() bool GetStartOnSystemStartup()
{ {
fsbridge::ifstream optionFile(GetAutostartFilePath()); std::ifstream optionFile{GetAutostartFilePath()};
if (!optionFile.good()) if (!optionFile.good())
return false; return false;
// Scan through file for "Hidden=true": // Scan through file for "Hidden=true":
@@ -617,7 +622,7 @@ bool SetStartOnSystemStartup(bool fAutoStart)
fs::create_directories(GetAutostartDir()); 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()) if (!optionFile.good())
return false; return false;
std::string chain = gArgs.GetChainName(); std::string chain = gArgs.GetChainName();
+4 -1
View File
@@ -5,6 +5,7 @@
#include <qt/psbtoperationsdialog.h> #include <qt/psbtoperationsdialog.h>
#include <core_io.h> #include <core_io.h>
#include <fs.h>
#include <interfaces/node.h> #include <interfaces/node.h>
#include <key_io.h> #include <key_io.h>
#include <node/psbt.h> #include <node/psbt.h>
@@ -15,7 +16,9 @@
#include <qt/optionsmodel.h> #include <qt/optionsmodel.h>
#include <util/strencodings.h> #include <util/strencodings.h>
#include <fstream>
#include <iostream> #include <iostream>
#include <string>
using node::AnalyzePSBT; using node::AnalyzePSBT;
using node::DEFAULT_MAX_RAW_TX_FEE_RATE; using node::DEFAULT_MAX_RAW_TX_FEE_RATE;
@@ -158,7 +161,7 @@ void PSBTOperationsDialog::saveTransaction() {
if (filename.isEmpty()) { if (filename.isEmpty()) {
return; 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 << ssTx.str();
out.close(); out.close();
showStatus(tr("PSBT saved to disk."), StatusLevel::INFO); showStatus(tr("PSBT saved to disk."), StatusLevel::INFO);
+4 -1
View File
@@ -29,7 +29,10 @@
#include <wallet/fees.h> #include <wallet/fees.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <array>
#include <chrono> #include <chrono>
#include <fstream>
#include <memory>
#include <QFontMetrics> #include <QFontMetrics>
#include <QScrollBar> #include <QScrollBar>
@@ -509,7 +512,7 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
if (filename.isEmpty()) { if (filename.isEmpty()) {
return; 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 << ssTx.str();
out.close(); out.close();
Q_EMIT message(tr("PSBT saved"), "PSBT saved to disk", CClientUIInterface::MSG_INFORMATION); Q_EMIT message(tr("PSBT saved"), "PSBT saved to disk", CClientUIInterface::MSG_INFORMATION);
+4 -1
View File
@@ -4,6 +4,7 @@
#include <qt/walletframe.h> #include <qt/walletframe.h>
#include <fs.h>
#include <node/ui_interface.h> #include <node/ui_interface.h>
#include <psbt.h> #include <psbt.h>
#include <qt/guiutil.h> #include <qt/guiutil.h>
@@ -14,6 +15,8 @@
#include <util/system.h> #include <util/system.h>
#include <cassert> #include <cassert>
#include <fstream>
#include <string>
#include <QApplication> #include <QApplication>
#include <QClipboard> #include <QClipboard>
@@ -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); Q_EMIT message(tr("Error"), tr("PSBT file must be smaller than 100 MiB"), CClientUIInterface::MSG_ERROR);
return; 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<char>{in}, {}); data = std::string(std::istreambuf_iterator<char>{in}, {});
} }
+7 -2
View File
@@ -12,6 +12,11 @@
#include <util/system.h> #include <util/system.h>
#include <util/strencodings.h> #include <util/strencodings.h>
#include <fstream>
#include <stdexcept>
#include <string>
#include <vector>
/** /**
* JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, * 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 * 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 - /** the umask determines what permissions are used to create this file -
* these are set to 077 in init.cpp unless overridden with -sysperms. * these are set to 077 in init.cpp unless overridden with -sysperms.
*/ */
fsbridge::ofstream file; std::ofstream file;
fs::path filepath_tmp = GetAuthCookieFile(true); fs::path filepath_tmp = GetAuthCookieFile(true);
file.open(filepath_tmp); file.open(filepath_tmp);
if (!file.is_open()) { if (!file.is_open()) {
@@ -107,7 +112,7 @@ bool GenerateAuthCookie(std::string *cookie_out)
bool GetAuthCookie(std::string *cookie_out) bool GetAuthCookie(std::string *cookie_out)
{ {
fsbridge::ifstream file; std::ifstream file;
std::string cookie; std::string cookie;
fs::path filepath = GetAuthCookieFile(); fs::path filepath = GetAuthCookieFile();
file.open(filepath); file.open(filepath);
+11 -7
View File
@@ -9,6 +9,10 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <fstream>
#include <ios>
#include <string>
BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(fsbridge_pathtostring) BOOST_AUTO_TEST_CASE(fsbridge_pathtostring)
@@ -45,37 +49,37 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream)
fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃"; fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃";
fs::path tmpfile2 = tmpfolder / "fs_tests_₿_🏃"; fs::path tmpfile2 = tmpfolder / "fs_tests_₿_🏃";
{ {
fsbridge::ofstream file(tmpfile1); std::ofstream file{tmpfile1};
file << "bitcoin"; file << "bitcoin";
} }
{ {
fsbridge::ifstream file(tmpfile2); std::ifstream file{tmpfile2};
std::string input_buffer; std::string input_buffer;
file >> input_buffer; file >> input_buffer;
BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); 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; std::string input_buffer;
file >> input_buffer; file >> input_buffer;
BOOST_CHECK_EQUAL(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"; file << "tests";
} }
{ {
fsbridge::ifstream file(tmpfile1); std::ifstream file{tmpfile1};
std::string input_buffer; std::string input_buffer;
file >> input_buffer; file >> input_buffer;
BOOST_CHECK_EQUAL(input_buffer, "bitcointests"); 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"; file << "bitcoin";
} }
{ {
fsbridge::ifstream file(tmpfile1); std::ifstream file{tmpfile1};
std::string input_buffer; std::string input_buffer;
file >> input_buffer; file >> input_buffer;
BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); BOOST_CHECK_EQUAL(input_buffer, "bitcoin");
+5 -1
View File
@@ -4,6 +4,7 @@
#include <test/fuzz/fuzz.h> #include <test/fuzz/fuzz.h>
#include <fs.h>
#include <netaddress.h> #include <netaddress.h>
#include <netbase.h> #include <netbase.h>
#include <test/util/setup_common.h> #include <test/util/setup_common.h>
@@ -12,9 +13,12 @@
#include <cstdint> #include <cstdint>
#include <exception> #include <exception>
#include <fstream>
#include <functional> #include <functional>
#include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <tuple>
#include <unistd.h> #include <unistd.h>
#include <vector> #include <vector>
@@ -80,7 +84,7 @@ void initialize()
} }
if (const char* out_path = std::getenv("WRITE_ALL_FUZZ_TARGETS_AND_ABORT")) { 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; 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()) { for (const auto& t : FuzzTargets()) {
if (std::get<2>(t.second)) continue; if (std::get<2>(t.second)) continue;
out_stream << t.first << std::endl; out_stream << t.first << std::endl;
+1
View File
@@ -4,6 +4,7 @@
#include <chainparams.h> #include <chainparams.h>
#include <consensus/validation.h> #include <consensus/validation.h>
#include <fs.h>
#include <node/utxo_snapshot.h> #include <node/utxo_snapshot.h>
#include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h> #include <test/fuzz/fuzz.h>
+3 -2
View File
@@ -24,7 +24,8 @@
#include <script/bitcoinconsensus.h> #include <script/bitcoinconsensus.h>
#endif #endif
#include <stdint.h> #include <cstdint>
#include <fstream>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -1727,7 +1728,7 @@ BOOST_AUTO_TEST_CASE(script_assets_test)
bool exists = fs::exists(path); bool exists = fs::exists(path);
BOOST_WARN_MESSAGE(exists, "File $DIR_UNIT_TEST_DATA/script_assets_test.json not found, skipping script_assets_test"); BOOST_WARN_MESSAGE(exists, "File $DIR_UNIT_TEST_DATA/script_assets_test.json not found, skipping script_assets_test");
if (!exists) return; if (!exists) return;
fs::ifstream file(path); std::ifstream file{path};
BOOST_CHECK(file.is_open()); BOOST_CHECK(file.is_open());
file.seekg(0, std::ios::end); file.seekg(0, std::ios::end);
size_t length = file.tellg(); size_t length = file.tellg();
+7 -1
View File
@@ -4,6 +4,7 @@
#include <util/settings.h> #include <util/settings.h>
#include <fs.h>
#include <test/util/setup_common.h> #include <test/util/setup_common.h>
#include <test/util/str.h> #include <test/util/str.h>
@@ -13,6 +14,11 @@
#include <util/strencodings.h> #include <util/strencodings.h>
#include <util/string.h> #include <util/string.h>
#include <util/system.h> #include <util/system.h>
#include <fstream>
#include <map>
#include <string>
#include <system_error>
#include <vector> #include <vector>
inline bool operator==(const util::SettingsValue& a, const util::SettingsValue& b) inline bool operator==(const util::SettingsValue& a, const util::SettingsValue& b)
@@ -36,7 +42,7 @@ inline std::ostream& operator<<(std::ostream& os, const std::pair<std::string, u
inline void WriteText(const fs::path& path, const std::string& text) inline void WriteText(const fs::path& path, const std::string& text)
{ {
fsbridge::ofstream file; std::ofstream file;
file.open(path); file.open(path);
file << text; file << text;
} }
+1
View File
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <fs.h>
#include <streams.h> #include <streams.h>
#include <test/util/setup_common.h> #include <test/util/setup_common.h>
+4
View File
@@ -5,6 +5,7 @@
#include <util/system.h> #include <util/system.h>
#include <clientversion.h> #include <clientversion.h>
#include <fs.h>
#include <hash.h> // For Hash() #include <hash.h> // For Hash()
#include <key.h> // For CKey #include <key.h> // For CKey
#include <sync.h> #include <sync.h>
@@ -70,9 +71,12 @@ BOOST_AUTO_TEST_CASE(util_datadir)
args.ClearPathCache(); args.ClearPathCache();
BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase()); BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
#ifndef WIN32
// Windows does not consider "datadir/.//" to be a valid directory path.
args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/.//"); args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/.//");
args.ClearPathCache(); args.ClearPathCache();
BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase()); BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
#endif
} }
BOOST_AUTO_TEST_CASE(util_check) BOOST_AUTO_TEST_CASE(util_check)
+1
View File
@@ -6,6 +6,7 @@
#include <clientversion.h> #include <clientversion.h>
#include <crypto/common.h> #include <crypto/common.h>
#include <fs.h>
#include <logging.h> #include <logging.h>
#include <streams.h> #include <streams.h>
+8 -2
View File
@@ -2,11 +2,17 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <fs.h>
#include <util/settings.h> #include <util/settings.h>
#include <tinyformat.h> #include <tinyformat.h>
#include <univalue.h> #include <univalue.h>
#include <fstream>
#include <map>
#include <string>
#include <vector>
namespace util { namespace util {
namespace { namespace {
@@ -63,7 +69,7 @@ bool ReadSettings(const fs::path& path, std::map<std::string, SettingsValue>& va
// Ok for file to not exist // Ok for file to not exist
if (!fs::exists(path)) return true; if (!fs::exists(path)) return true;
fsbridge::ifstream file; std::ifstream file;
file.open(path); file.open(path);
if (!file.is_open()) { if (!file.is_open()) {
errors.emplace_back(strprintf("%s. Please check permissions.", fs::PathToString(path))); errors.emplace_back(strprintf("%s. Please check permissions.", fs::PathToString(path)));
@@ -106,7 +112,7 @@ bool WriteSettings(const fs::path& path,
for (const auto& value : values) { for (const auto& value : values) {
out.__pushKV(value.first, value.second); out.__pushKV(value.first, value.second);
} }
fsbridge::ofstream file; std::ofstream file;
file.open(path); file.open(path);
if (file.fail()) { if (file.fail()) {
errors.emplace_back(strprintf("Error: Unable to open settings file %s for writing", fs::PathToString(path))); errors.emplace_back(strprintf("Error: Unable to open settings file %s for writing", fs::PathToString(path)));
+1
View File
@@ -595,6 +595,7 @@ public:
allowed_syscalls.insert(__NR_readlink); // read value of a symbolic link allowed_syscalls.insert(__NR_readlink); // read value of a symbolic link
allowed_syscalls.insert(__NR_rename); // change the name or location of a file allowed_syscalls.insert(__NR_rename); // change the name or location of a file
allowed_syscalls.insert(__NR_rmdir); // delete a directory allowed_syscalls.insert(__NR_rmdir); // delete a directory
allowed_syscalls.insert(__NR_sendfile); // transfer data between file descriptors
allowed_syscalls.insert(__NR_stat); // get file status allowed_syscalls.insert(__NR_stat); // get file status
allowed_syscalls.insert(__NR_statfs); // get filesystem statistics allowed_syscalls.insert(__NR_statfs); // get filesystem statistics
allowed_syscalls.insert(__NR_statx); // get file status (extended) allowed_syscalls.insert(__NR_statx); // get file status (extended)
+15 -20
View File
@@ -10,6 +10,7 @@
#endif // ENABLE_EXTERNAL_SIGNER #endif // ENABLE_EXTERNAL_SIGNER
#include <chainparamsbase.h> #include <chainparamsbase.h>
#include <fs.h>
#include <sync.h> #include <sync.h>
#include <util/check.h> #include <util/check.h>
#include <util/getuniquepath.h> #include <util/getuniquepath.h>
@@ -66,10 +67,15 @@
#endif #endif
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <univalue.h>
#include <fstream>
#include <map>
#include <memory>
#include <optional> #include <optional>
#include <string>
#include <thread> #include <thread>
#include <typeinfo> #include <typeinfo>
#include <univalue.h>
// Application startup time (used for uptime calculation) // Application startup time (used for uptime calculation)
const int64_t nStartupTime = GetTime(); const int64_t nStartupTime = GetTime();
@@ -146,7 +152,7 @@ bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes)
} }
std::streampos GetFileSize(const char* path, std::streamsize max) { std::streampos GetFileSize(const char* path, std::streamsize max) {
fsbridge::ifstream file{path, std::ios::binary}; std::ifstream file{path, std::ios::binary};
file.ignore(max); file.ignore(max);
return file.gcount(); return file.gcount();
} }
@@ -243,7 +249,7 @@ namespace {
fs::path StripRedundantLastElementsOfPath(const fs::path& path) fs::path StripRedundantLastElementsOfPath(const fs::path& path)
{ {
auto result = path; auto result = path;
while (fs::PathToString(result.filename()) == ".") { while (result.filename().empty() || fs::PathToString(result.filename()) == ".") {
result = result.parent_path(); result = result.parent_path();
} }
@@ -403,7 +409,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
if (!path.empty()) return path; if (!path.empty()) return path;
if (IsArgSet("-blocksdir")) { if (IsArgSet("-blocksdir")) {
path = fs::system_complete(fs::PathFromString(GetArg("-blocksdir", ""))); path = fs::absolute(fs::PathFromString(GetArg("-blocksdir", "")));
if (!fs::is_directory(path)) { if (!fs::is_directory(path)) {
path = ""; path = "";
return path; return path;
@@ -415,7 +421,6 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
path /= fs::PathFromString(BaseParams().DataDir()); path /= fs::PathFromString(BaseParams().DataDir());
path /= "blocks"; path /= "blocks";
fs::create_directories(path); fs::create_directories(path);
path = StripRedundantLastElementsOfPath(path);
return path; return path;
} }
@@ -430,7 +435,7 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
std::string datadir = GetArg("-datadir", ""); std::string datadir = GetArg("-datadir", "");
if (!datadir.empty()) { if (!datadir.empty()) {
path = fs::system_complete(fs::PathFromString(datadir)); path = fs::absolute(StripRedundantLastElementsOfPath(fs::PathFromString(datadir)));
if (!fs::is_directory(path)) { if (!fs::is_directory(path)) {
path = ""; path = "";
return path; return path;
@@ -808,7 +813,7 @@ fs::path GetDefaultDataDir()
bool CheckDataDirOption() bool CheckDataDirOption()
{ {
std::string datadir = gArgs.GetArg("-datadir", ""); std::string datadir = gArgs.GetArg("-datadir", "");
return datadir.empty() || fs::is_directory(fs::system_complete(fs::PathFromString(datadir))); return datadir.empty() || fs::is_directory(fs::absolute(fs::PathFromString(datadir)));
} }
fs::path GetConfigFile(const std::string& confPath) fs::path GetConfigFile(const std::string& confPath)
@@ -898,7 +903,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
} }
const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME); const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME);
fsbridge::ifstream stream(GetConfigFile(confPath)); std::ifstream stream{GetConfigFile(confPath)};
// not ok to have a config file specified that cannot be opened // not ok to have a config file specified that cannot be opened
if (IsArgSet("-conf") && !stream.good()) { if (IsArgSet("-conf") && !stream.good()) {
@@ -945,7 +950,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
const size_t default_includes = add_includes({}); const size_t default_includes = add_includes({});
for (const std::string& conf_file_name : conf_file_names) { for (const std::string& conf_file_name : conf_file_names) {
fsbridge::ifstream conf_file_stream(GetConfigFile(conf_file_name)); std::ifstream conf_file_stream{GetConfigFile(conf_file_name)};
if (conf_file_stream.good()) { if (conf_file_stream.good()) {
if (!ReadConfigStream(conf_file_stream, conf_file_name, error, ignore_invalid_keys)) { if (!ReadConfigStream(conf_file_stream, conf_file_name, error, ignore_invalid_keys)) {
return false; return false;
@@ -1069,7 +1074,7 @@ bool RenameOver(fs::path src, fs::path dest)
} }
/** /**
* Ignores exceptions thrown by Boost's create_directories if the requested directory exists. * Ignores exceptions thrown by create_directories if the requested directory exists.
* Specifically handles case where path p exists, but it wasn't possible for the user to * Specifically handles case where path p exists, but it wasn't possible for the user to
* write to the parent directory. * write to the parent directory.
*/ */
@@ -1312,16 +1317,6 @@ void SetupEnvironment()
// Set the default input/output charset is utf-8 // Set the default input/output charset is utf-8
SetConsoleCP(CP_UTF8); SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
#endif
// The path locale is lazy initialized and to avoid deinitialization errors
// in multithreading environments, it is set explicitly by the main thread.
// A dummy locale is used to extract the internal default locale, used by
// fs::path, which is then used to explicitly imbue the path.
std::locale loc = fs::path::imbue(std::locale::classic());
#ifndef WIN32
fs::path::imbue(loc);
#else
fs::path::imbue(std::locale(loc, new std::codecvt_utf8_utf16<wchar_t>()));
#endif #endif
} }
+3 -2
View File
@@ -3,6 +3,7 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <fs.h>
#include <wallet/bdb.h> #include <wallet/bdb.h>
#include <wallet/db.h> #include <wallet/db.h>
@@ -620,12 +621,12 @@ bool BerkeleyDatabase::Backup(const std::string& strDest) const
pathDest /= fs::PathFromString(strFile); pathDest /= fs::PathFromString(strFile);
try { try {
if (fs::equivalent(pathSrc, pathDest)) { if (fs::exists(pathDest) && fs::equivalent(pathSrc, pathDest)) {
LogPrintf("cannot backup to wallet source file %s\n", fs::PathToString(pathDest)); LogPrintf("cannot backup to wallet source file %s\n", fs::PathToString(pathDest));
return false; return false;
} }
fs::copy_file(pathSrc, pathDest, fs::copy_option::overwrite_if_exists); fs::copy_file(pathSrc, pathDest, fs::copy_options::overwrite_existing);
LogPrintf("copied %s to %s\n", strFile, fs::PathToString(pathDest)); LogPrintf("copied %s to %s\n", strFile, fs::PathToString(pathDest));
return true; return true;
} catch (const fs::filesystem_error& e) { } catch (const fs::filesystem_error& e) {
+13 -9
View File
@@ -8,18 +8,22 @@
#include <logging.h> #include <logging.h>
#include <wallet/db.h> #include <wallet/db.h>
#include <exception>
#include <fstream>
#include <string> #include <string>
#include <system_error>
#include <vector>
namespace wallet { namespace wallet {
std::vector<fs::path> ListDatabases(const fs::path& wallet_dir) std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
{ {
std::vector<fs::path> paths; std::vector<fs::path> paths;
boost::system::error_code ec; std::error_code ec;
for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) { for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
if (ec) { if (ec) {
if (fs::is_directory(*it)) { if (fs::is_directory(*it)) {
it.no_push(); it.disable_recursion_pending();
LogPrintf("%s: %s %s -- skipping.\n", __func__, ec.message(), fs::PathToString(it->path())); LogPrintf("%s: %s %s -- skipping.\n", __func__, ec.message(), fs::PathToString(it->path()));
} else { } else {
LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(it->path())); LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(it->path()));
@@ -30,11 +34,11 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
try { try {
const fs::path path{it->path().lexically_relative(wallet_dir)}; const fs::path path{it->path().lexically_relative(wallet_dir)};
if (it->status().type() == fs::directory_file && if (it->status().type() == fs::file_type::directory &&
(IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) { (IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
// Found a directory which contains wallet.dat btree file, add it as a wallet. // Found a directory which contains wallet.dat btree file, add it as a wallet.
paths.emplace_back(path); paths.emplace_back(path);
} else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBDBFile(it->path())) { } else if (it.depth() == 0 && it->symlink_status().type() == fs::file_type::regular && IsBDBFile(it->path())) {
if (it->path().filename() == "wallet.dat") { if (it->path().filename() == "wallet.dat") {
// Found top-level wallet.dat btree file, add top level directory "" // Found top-level wallet.dat btree file, add top level directory ""
// as a wallet. // as a wallet.
@@ -49,7 +53,7 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {
LogPrintf("%s: Error scanning %s: %s\n", __func__, fs::PathToString(it->path()), e.what()); LogPrintf("%s: Error scanning %s: %s\n", __func__, fs::PathToString(it->path()), e.what());
it.no_push(); it.disable_recursion_pending();
} }
} }
@@ -81,12 +85,12 @@ bool IsBDBFile(const fs::path& path)
// A Berkeley DB Btree file has at least 4K. // A Berkeley DB Btree file has at least 4K.
// This check also prevents opening lock files. // This check also prevents opening lock files.
boost::system::error_code ec; std::error_code ec;
auto size = fs::file_size(path, ec); auto size = fs::file_size(path, ec);
if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path)); if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path));
if (size < 4096) return false; if (size < 4096) return false;
fsbridge::ifstream file(path, std::ios::binary); std::ifstream file{path, std::ios::binary};
if (!file.is_open()) return false; if (!file.is_open()) return false;
file.seekg(12, std::ios::beg); // Magic bytes start at offset 12 file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
@@ -105,12 +109,12 @@ bool IsSQLiteFile(const fs::path& path)
if (!fs::exists(path)) return false; if (!fs::exists(path)) return false;
// A SQLite Database file is at least 512 bytes. // A SQLite Database file is at least 512 bytes.
boost::system::error_code ec; std::error_code ec;
auto size = fs::file_size(path, ec); auto size = fs::file_size(path, ec);
if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path)); if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path));
if (size < 512) return false; if (size < 512) return false;
fsbridge::ifstream file(path, std::ios::binary); std::ifstream file{path, std::ios::binary};
if (!file.is_open()) return false; if (!file.is_open()) return false;
// Magic is at beginning and is 16 bytes long // Magic is at beginning and is 16 bytes long
+10 -2
View File
@@ -4,9 +4,17 @@
#include <wallet/dump.h> #include <wallet/dump.h>
#include <fs.h>
#include <util/translation.h> #include <util/translation.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <algorithm>
#include <fstream>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace wallet { namespace wallet {
static const std::string DUMP_MAGIC = "BITCOIN_CORE_WALLET_DUMP"; static const std::string DUMP_MAGIC = "BITCOIN_CORE_WALLET_DUMP";
uint32_t DUMP_VERSION = 1; uint32_t DUMP_VERSION = 1;
@@ -26,7 +34,7 @@ bool DumpWallet(CWallet& wallet, bilingual_str& error)
error = strprintf(_("File %s already exists. If you are sure this is what you want, move it out of the way first."), fs::PathToString(path)); error = strprintf(_("File %s already exists. If you are sure this is what you want, move it out of the way first."), fs::PathToString(path));
return false; return false;
} }
fsbridge::ofstream dump_file; std::ofstream dump_file;
dump_file.open(path); dump_file.open(path);
if (dump_file.fail()) { if (dump_file.fail()) {
error = strprintf(_("Unable to open %s for writing"), fs::PathToString(path)); error = strprintf(_("Unable to open %s for writing"), fs::PathToString(path));
@@ -121,7 +129,7 @@ bool CreateFromDump(const std::string& name, const fs::path& wallet_path, biling
error = strprintf(_("Dump file %s does not exist."), fs::PathToString(dump_path)); error = strprintf(_("Dump file %s does not exist."), fs::PathToString(dump_path));
return false; return false;
} }
fsbridge::ifstream dump_file(dump_path); std::ifstream dump_file{dump_path};
// Compute the checksum // Compute the checksum
CHashWriter hasher(0, 0); CHashWriter hasher(0, 0);
+3
View File
@@ -7,6 +7,9 @@
#include <fs.h> #include <fs.h>
#include <string>
#include <vector>
struct bilingual_str; struct bilingual_str;
namespace wallet { namespace wallet {
+4 -2
View File
@@ -19,6 +19,8 @@
#include <univalue.h> #include <univalue.h>
#include <system_error>
namespace wallet { namespace wallet {
bool VerifyWallets(WalletContext& context) bool VerifyWallets(WalletContext& context)
{ {
@@ -27,9 +29,9 @@ bool VerifyWallets(WalletContext& context)
if (args.IsArgSet("-walletdir")) { if (args.IsArgSet("-walletdir")) {
fs::path wallet_dir = fs::PathFromString(args.GetArg("-walletdir", "")); fs::path wallet_dir = fs::PathFromString(args.GetArg("-walletdir", ""));
boost::system::error_code error; std::error_code error;
// The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error).remove_trailing_separator(); fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
if (error || !fs::exists(wallet_dir)) { if (error || !fs::exists(wallet_dir)) {
chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), fs::PathToString(wallet_dir))); chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), fs::PathToString(wallet_dir)));
return false; return false;
+6 -3
View File
@@ -5,6 +5,7 @@
#include <chain.h> #include <chain.h>
#include <clientversion.h> #include <clientversion.h>
#include <core_io.h> #include <core_io.h>
#include <fs.h>
#include <interfaces/chain.h> #include <interfaces/chain.h>
#include <key_io.h> #include <key_io.h>
#include <merkleblock.h> #include <merkleblock.h>
@@ -20,8 +21,10 @@
#include <wallet/rpc/util.h> #include <wallet/rpc/util.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <stdint.h> #include <cstdint>
#include <fstream>
#include <tuple> #include <tuple>
#include <string>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@@ -521,7 +524,7 @@ RPCHelpMan importwallet()
EnsureWalletIsUnlocked(*pwallet); EnsureWalletIsUnlocked(*pwallet);
fsbridge::ifstream file; std::ifstream file;
file.open(fs::u8path(request.params[0].get_str()), std::ios::in | std::ios::ate); file.open(fs::u8path(request.params[0].get_str()), std::ios::in | std::ios::ate);
if (!file.is_open()) { if (!file.is_open()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
@@ -729,7 +732,7 @@ RPCHelpMan dumpwallet()
throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.u8string() + " already exists. If you are sure this is what you want, move it out of the way first"); throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.u8string() + " already exists. If you are sure this is what you want, move it out of the way first");
} }
fsbridge::ofstream file; std::ofstream file;
file.open(filepath); file.open(filepath);
if (!file.is_open()) if (!file.is_open())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
+4 -3
View File
@@ -2,14 +2,15 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <memory>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <fs.h> #include <fs.h>
#include <test/util/setup_common.h> #include <test/util/setup_common.h>
#include <wallet/bdb.h> #include <wallet/bdb.h>
#include <fstream>
#include <memory>
#include <string>
namespace wallet { namespace wallet {
BOOST_FIXTURE_TEST_SUITE(db_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(db_tests, BasicTestingSetup)
@@ -26,7 +27,7 @@ BOOST_AUTO_TEST_CASE(getwalletenv_file)
std::string test_name = "test_name.dat"; std::string test_name = "test_name.dat";
const fs::path datadir = gArgs.GetDataDirNet(); const fs::path datadir = gArgs.GetDataDirNet();
fs::path file_path = datadir / test_name; fs::path file_path = datadir / test_name;
fs::ofstream f(file_path); std::ofstream f{file_path};
f.close(); f.close();
std::string filename; std::string filename;
+6 -3
View File
@@ -7,6 +7,9 @@
#include <util/check.h> #include <util/check.h>
#include <util/system.h> #include <util/system.h>
#include <fstream>
#include <string>
#include <wallet/test/init_test_fixture.h> #include <wallet/test/init_test_fixture.h>
namespace wallet { namespace wallet {
@@ -24,8 +27,8 @@ InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainNam
m_walletdir_path_cases["custom"] = m_datadir / "my_wallets"; m_walletdir_path_cases["custom"] = m_datadir / "my_wallets";
m_walletdir_path_cases["nonexistent"] = m_datadir / "path_does_not_exist"; m_walletdir_path_cases["nonexistent"] = m_datadir / "path_does_not_exist";
m_walletdir_path_cases["file"] = m_datadir / "not_a_directory.dat"; m_walletdir_path_cases["file"] = m_datadir / "not_a_directory.dat";
m_walletdir_path_cases["trailing"] = m_datadir / "wallets" / sep; m_walletdir_path_cases["trailing"] = m_datadir / ("wallets" + sep);
m_walletdir_path_cases["trailing2"] = m_datadir / "wallets" / sep / sep; m_walletdir_path_cases["trailing2"] = m_datadir / ("wallets" + sep + sep);
fs::current_path(m_datadir); fs::current_path(m_datadir);
m_walletdir_path_cases["relative"] = "wallets"; m_walletdir_path_cases["relative"] = "wallets";
@@ -33,7 +36,7 @@ InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainNam
fs::create_directories(m_walletdir_path_cases["default"]); fs::create_directories(m_walletdir_path_cases["default"]);
fs::create_directories(m_walletdir_path_cases["custom"]); fs::create_directories(m_walletdir_path_cases["custom"]);
fs::create_directories(m_walletdir_path_cases["relative"]); fs::create_directories(m_walletdir_path_cases["relative"]);
fs::ofstream f(m_walletdir_path_cases["file"]); std::ofstream f{m_walletdir_path_cases["file"]};
f.close(); f.close();
} }
+3
View File
@@ -73,6 +73,8 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
BOOST_CHECK_EQUAL(walletdir, expected_path); BOOST_CHECK_EQUAL(walletdir, expected_path);
} }
#ifndef WIN32
// Windows does not consider "datadir/wallets//" to be a valid directory path.
BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2) BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
{ {
SetWalletDir(m_walletdir_path_cases["trailing2"]); SetWalletDir(m_walletdir_path_cases["trailing2"]);
@@ -82,6 +84,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
BOOST_CHECK_EQUAL(walletdir, expected_path); BOOST_CHECK_EQUAL(walletdir, expected_path);
} }
#endif
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet } // namespace wallet
+4 -4
View File
@@ -378,7 +378,7 @@ std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& b
} }
auto wallet_file = wallet_path / "wallet.dat"; auto wallet_file = wallet_path / "wallet.dat";
fs::copy_file(backup_file, wallet_file, fs::copy_option::fail_if_exists); fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
auto wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings); auto wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
@@ -2651,9 +2651,9 @@ std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, cons
// 4. For backwards compatibility, the name of a data file in -walletdir. // 4. For backwards compatibility, the name of a data file in -walletdir.
const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name)); const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name));
fs::file_type path_type = fs::symlink_status(wallet_path).type(); fs::file_type path_type = fs::symlink_status(wallet_path).type();
if (!(path_type == fs::file_not_found || path_type == fs::directory_file || if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) || (path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
(path_type == fs::regular_file && fs::PathFromString(name).filename() == fs::PathFromString(name)))) { (path_type == fs::file_type::regular && fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
error_string = Untranslated(strprintf( error_string = Untranslated(strprintf(
"Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and " "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
"database/log.?????????? files can be stored, a location where such a directory could be created, " "database/log.?????????? files can be stored, a location where such a directory could be created, "
+1 -1
View File
@@ -1105,7 +1105,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
{ {
bool exists; bool exists;
try { try {
exists = fs::symlink_status(path).type() != fs::file_not_found; exists = fs::symlink_status(path).type() != fs::file_type::not_found;
} catch (const fs::filesystem_error& e) { } catch (const fs::filesystem_error& e) {
error = Untranslated(strprintf("Failed to access database path '%s': %s", fs::PathToString(path), fsbridge::get_filesystem_error_message(e))); error = Untranslated(strprintf("Failed to access database path '%s': %s", fs::PathToString(path), fsbridge::get_filesystem_error_message(e)));
status = DatabaseStatus::FAILED_BAD_PATH; status = DatabaseStatus::FAILED_BAD_PATH;
+2 -1
View File
@@ -11,6 +11,7 @@ from threading import Thread
import os import os
import shutil import shutil
import stat import stat
import sys
import time import time
from test_framework.authproxy import JSONRPCException from test_framework.authproxy import JSONRPCException
@@ -141,7 +142,7 @@ class MultiWalletTest(BitcoinTestFramework):
# should raise rpc error if wallet path can't be created # should raise rpc error if wallet path can't be created
err_code = -4 if self.options.descriptors else -1 err_code = -4 if self.options.descriptors else -1
assert_raises_rpc_error(err_code, "boost::filesystem::create_director", self.nodes[0].createwallet, "w8/bad") assert_raises_rpc_error(err_code, "filesystem error:" if sys.platform != 'win32' else "create_directories:", self.nodes[0].createwallet, "w8/bad")
# check that all requested wallets were created # check that all requested wallets were created
self.stop_node(0) self.stop_node(0)
-2
View File
@@ -54,8 +54,6 @@ EXPECTED_BOOST_INCLUDES=(
boost/algorithm/string/replace.hpp boost/algorithm/string/replace.hpp
boost/algorithm/string/split.hpp boost/algorithm/string/split.hpp
boost/date_time/posix_time/posix_time.hpp boost/date_time/posix_time/posix_time.hpp
boost/filesystem.hpp
boost/filesystem/fstream.hpp
boost/multi_index/hashed_index.hpp boost/multi_index/hashed_index.hpp
boost/multi_index/ordered_index.hpp boost/multi_index/ordered_index.hpp
boost/multi_index/sequenced_index.hpp boost/multi_index/sequenced_index.hpp