mirror of
https://github.com/dashpay/dash.git
synced 2024-12-23 19:12:47 +01:00
merge bitcoin#20744: Use std::filesystem. Remove Boost Filesystem & System
This commit is contained in:
parent
be7ac493d0
commit
a3b79267e0
@ -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
|
||||
])
|
47
build-aux/m4/l_filesystem.m4
Normal file
47
build-aux/m4/l_filesystem.m4
Normal 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,7 +6,7 @@
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libboost-filesystem-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-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 libzmq3-dev libqrencode-dev"
|
||||
export NO_DEPENDS=1
|
||||
export TEST_RUNNER_EXTRA="--timeout-factor=4" # Increase timeout because sanitizers slow down
|
||||
export FUNCTIONAL_TESTS_CONFIG="--exclude wallet_multiwallet.py" # Temporarily suppress ASan heap-use-after-free (see issue #14163)
|
||||
|
@ -7,7 +7,7 @@
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
export CONTAINER_NAME=ci_native_fuzz
|
||||
export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-filesystem-dev libboost-test-dev"
|
||||
export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-test-dev"
|
||||
export DEP_OPTS="NO_UPNP=1 DEBUG=1"
|
||||
export CPPFLAGS="-DDEBUG_LOCKORDER -DARENA_DEBUG"
|
||||
export CXXFLAGS="-Werror -Wno-unused-command-line-argument -Wno-unused-value -Wno-deprecated-builtins"
|
||||
|
@ -7,7 +7,7 @@
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
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 valgrind"
|
||||
export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-test-dev valgrind"
|
||||
export NO_DEPENDS=1
|
||||
export RUN_UNIT_TESTS=false
|
||||
export RUN_FUNCTIONAL_TESTS=false
|
||||
|
@ -8,7 +8,7 @@
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
export CONTAINER_NAME=ci_native_ubsan
|
||||
export PACKAGES="clang-16 llvm-16 python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-filesystem-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev"
|
||||
export PACKAGES="clang-16 llvm-16 python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev"
|
||||
export DEP_OPTS="NO_UPNP=1 DEBUG=1"
|
||||
export GOAL="install"
|
||||
export BITCOIN_CONFIG="--enable-zmq --enable-reduce-exports --enable-crash-hooks --with-sanitizers=undefined CC=clang-16 CXX=clang++-16"
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
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 libzmq3-dev"
|
||||
export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev"
|
||||
export USE_VALGRIND=1
|
||||
export NO_DEPENDS=1
|
||||
export TEST_RUNNER_EXTRA="--exclude rpc_bind --timeout-factor=4" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547
|
||||
|
@ -82,6 +82,9 @@ fi
|
||||
dnl Check if -latomic is required for <std::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 that we get the same -std flags for both.
|
||||
m4_ifdef([AC_PROG_OBJCXX],[
|
||||
@ -1472,8 +1475,6 @@ dnl and will generate warnings with newer compilers.
|
||||
dnl See: https://github.com/boostorg/container_hash/issues/22.
|
||||
BOOST_CPPFLAGS="$BOOST_CPPFLAGS -DBOOST_NO_CXX98_FUNCTION_BASE"
|
||||
|
||||
AX_BOOST_FILESYSTEM
|
||||
|
||||
dnl Opt-in to Boost Process
|
||||
if test "x$boost_process" != xno; then
|
||||
AC_MSG_CHECKING(for Boost Process)
|
||||
@ -1488,7 +1489,7 @@ if test x$suppress_external_warnings != xno; then
|
||||
BOOST_CPPFLAGS=SUPPRESS_WARNINGS($BOOST_CPPFLAGS)
|
||||
fi
|
||||
|
||||
BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB"
|
||||
BOOST_LIBS="$BOOST_LDFLAGS"
|
||||
fi
|
||||
|
||||
dnl Check for reduced exports
|
||||
|
@ -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
|
||||
|
@ -26,7 +26,7 @@ $(package)_toolset_$(host_os)=clang
|
||||
else
|
||||
$(package)_toolset_$(host_os)=gcc
|
||||
endif
|
||||
$(package)_config_libraries=filesystem,test
|
||||
$(package)_config_libraries=test
|
||||
$(package)_cxxflags+=-std=c++11
|
||||
$(package)_cxxflags_linux=-fPIC
|
||||
$(package)_cxxflags_freebsd=-fPIC
|
||||
|
@ -81,7 +81,7 @@ sudo apt-get install build-essential libtool autotools-dev automake pkg-config b
|
||||
Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <addrman.h>
|
||||
#include <chainparams.h>
|
||||
#include <clientversion.h>
|
||||
#include <fs.h>
|
||||
#include <hash.h>
|
||||
#include <logging/timer.h>
|
||||
#include <netbase.h>
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <validation.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
|
||||
@ -23,7 +24,7 @@ void GenerateTemplateResults(const std::vector<ankerl::nanobench::Result>& 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 {
|
||||
|
110
src/fs.cpp
110
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,112 +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
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
134
src/fs.h
134
src/fs.h
@ -5,46 +5,42 @@
|
||||
#ifndef 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 <cstdio>
|
||||
#include <filesystem>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
/** 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 <fstream>.
|
||||
// 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<boost::filesystem::path&&>(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<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
|
||||
}
|
||||
|
||||
@ -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<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
|
||||
// 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
|
||||
|
||||
|
@ -105,12 +105,15 @@
|
||||
|
||||
#include <statsd_client.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@ -159,7 +162,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());
|
||||
|
@ -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 <fs.h>
|
||||
#include <logging.h>
|
||||
#include <util/system.h>
|
||||
#include <util/threadnames.h>
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <compat.h>
|
||||
#include <consensus/consensus.h>
|
||||
#include <crypto/sha256.h>
|
||||
#include <fs.h>
|
||||
#include <i2p.h>
|
||||
#include <net_permissions.h>
|
||||
#include <netaddress.h>
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <base58.h>
|
||||
#include <chainparams.h>
|
||||
#include <fs.h>
|
||||
#include <interfaces/node.h>
|
||||
#include <key_io.h>
|
||||
#include <policy/policy.h>
|
||||
@ -77,6 +78,10 @@
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <chrono>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
|
||||
@ -810,7 +815,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":
|
||||
@ -842,7 +847,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();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <qt/psbtoperationsdialog.h>
|
||||
|
||||
#include <core_io.h>
|
||||
#include <fs.h>
|
||||
#include <interfaces/node.h>
|
||||
#include <key_io.h>
|
||||
#include <node/psbt.h>
|
||||
@ -15,7 +16,9 @@
|
||||
#include <qt/optionsmodel.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
PSBTOperationsDialog::PSBTOperationsDialog(
|
||||
@ -150,7 +153,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);
|
||||
|
@ -27,9 +27,12 @@
|
||||
#include <wallet/coincontrol.h>
|
||||
#include <wallet/fees.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <validation.h>
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
#include <QFontMetrics>
|
||||
#include <QScrollBar>
|
||||
#include <QSettings>
|
||||
@ -521,7 +524,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);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <qt/walletframe.h>
|
||||
|
||||
#include <fs.h>
|
||||
#include <node/ui_interface.h>
|
||||
#include <psbt.h>
|
||||
#include <qt/bitcoingui.h>
|
||||
@ -19,6 +20,8 @@
|
||||
#include <util/system.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
@ -285,7 +288,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<char>{in}, {});
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,11 @@
|
||||
#include <util/system.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
@ -9,6 +9,10 @@
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <ios>
|
||||
#include <string>
|
||||
|
||||
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");
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <test/fuzz/fuzz.h>
|
||||
|
||||
#include <fs.h>
|
||||
#include <netaddress.h>
|
||||
#include <netbase.h>
|
||||
#include <test/util/setup_common.h>
|
||||
@ -13,9 +14,10 @@
|
||||
|
||||
#include <csignal>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
@ -59,7 +61,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;
|
||||
|
@ -20,7 +20,8 @@
|
||||
#include <script/bitcoinconsensus.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <util/settings.h>
|
||||
|
||||
#include <fs.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <test/util/str.h>
|
||||
|
||||
@ -13,6 +14,11 @@
|
||||
#include <util/strencodings.h>
|
||||
#include <util/string.h>
|
||||
#include <util/system.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
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)
|
||||
{
|
||||
fsbridge::ofstream file;
|
||||
std::ofstream file;
|
||||
file.open(path);
|
||||
file << text;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <fs.h>
|
||||
#include <streams.h>
|
||||
#include <test/util/setup_common.h>
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <util/system.h>
|
||||
|
||||
#include <clientversion.h>
|
||||
#include <fs.h>
|
||||
#include <hash.h> // For Hash()
|
||||
#include <key.h> // For CKey
|
||||
#include <sync.h>
|
||||
@ -72,9 +73,12 @@ BOOST_AUTO_TEST_CASE(util_datadir)
|
||||
args.ClearPathCache();
|
||||
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.ClearPathCache();
|
||||
BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <clientversion.h>
|
||||
#include <crypto/common.h>
|
||||
#include <fs.h>
|
||||
#include <logging.h>
|
||||
#include <streams.h>
|
||||
|
||||
|
@ -2,11 +2,17 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <fs.h>
|
||||
#include <util/settings.h>
|
||||
|
||||
#include <tinyformat.h>
|
||||
#include <univalue.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace util {
|
||||
namespace {
|
||||
|
||||
@ -63,7 +69,7 @@ bool ReadSettings(const fs::path& path, std::map<std::string, SettingsValue>& va
|
||||
// Ok for file to not exist
|
||||
if (!fs::exists(path)) return true;
|
||||
|
||||
fsbridge::ifstream file;
|
||||
std::ifstream file;
|
||||
file.open(path);
|
||||
if (!file.is_open()) {
|
||||
errors.emplace_back(strprintf("%s. Please check permissions.", fs::PathToString(path)));
|
||||
@ -118,7 +124,7 @@ bool WriteSettings(const fs::path& path,
|
||||
for (const auto& value : values) {
|
||||
out.__pushKV(value.first, value.second);
|
||||
}
|
||||
fsbridge::ofstream file;
|
||||
std::ofstream file;
|
||||
file.open(path);
|
||||
if (file.fail()) {
|
||||
errors.emplace_back(strprintf("Error: Unable to open settings file %s for writing", fs::PathToString(path)));
|
||||
|
@ -74,9 +74,14 @@
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <typeinfo>
|
||||
#include <univalue.h>
|
||||
|
||||
// Application startup time (used for uptime calculation)
|
||||
const int64_t nStartupTime = GetTime();
|
||||
@ -167,7 +172,7 @@ bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes)
|
||||
}
|
||||
|
||||
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);
|
||||
return file.gcount();
|
||||
}
|
||||
@ -259,7 +264,7 @@ namespace {
|
||||
fs::path StripRedundantLastElementsOfPath(const fs::path& path)
|
||||
{
|
||||
auto result = path;
|
||||
while (fs::PathToString(result.filename()) == ".") {
|
||||
while (result.filename().empty() || fs::PathToString(result.filename()) == ".") {
|
||||
result = result.parent_path();
|
||||
}
|
||||
|
||||
@ -424,7 +429,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
|
||||
if (!path.empty()) return path;
|
||||
|
||||
if (IsArgSet("-blocksdir")) {
|
||||
path = fs::system_complete(fs::PathFromString(GetArg("-blocksdir", "")));
|
||||
path = fs::absolute(fs::PathFromString(GetArg("-blocksdir", "")));
|
||||
if (!fs::is_directory(path)) {
|
||||
path = "";
|
||||
return path;
|
||||
@ -436,7 +441,6 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
|
||||
path /= fs::PathFromString(BaseParams().DataDir());
|
||||
path /= "blocks";
|
||||
fs::create_directories(path);
|
||||
path = StripRedundantLastElementsOfPath(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -451,7 +455,7 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
|
||||
|
||||
std::string datadir = GetArg("-datadir", "");
|
||||
if (!datadir.empty()) {
|
||||
path = fs::system_complete(fs::PathFromString(datadir));
|
||||
path = fs::absolute(StripRedundantLastElementsOfPath(fs::PathFromString(datadir)));
|
||||
if (!fs::is_directory(path)) {
|
||||
path = "";
|
||||
return path;
|
||||
@ -863,7 +867,7 @@ fs::path GetBackupsDir()
|
||||
bool CheckDataDirOption()
|
||||
{
|
||||
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)
|
||||
@ -954,7 +958,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
|
||||
}
|
||||
|
||||
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
|
||||
if (IsArgSet("-conf") && !stream.good()) {
|
||||
@ -1001,7 +1005,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
|
||||
const size_t default_includes = add_includes({});
|
||||
|
||||
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 (!ReadConfigStream(conf_file_stream, conf_file_name, error, ignore_invalid_keys)) {
|
||||
return false;
|
||||
@ -1028,9 +1032,10 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
|
||||
}
|
||||
} else {
|
||||
// Create an empty dash.conf if it does not exist
|
||||
FILE* configFile = fsbridge::fopen(GetConfigFile(confPath), "a");
|
||||
if (configFile != nullptr)
|
||||
fclose(configFile);
|
||||
std::ofstream configFile{GetConfigFile(confPath), std::ios_base::app};
|
||||
if (!configFile.good())
|
||||
return false;
|
||||
configFile.close();
|
||||
return true; // Nothing to read, so just return
|
||||
}
|
||||
|
||||
@ -1138,7 +1143,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
|
||||
* write to the parent directory.
|
||||
*/
|
||||
@ -1417,16 +1422,6 @@ void SetupEnvironment()
|
||||
// Set the default input/output charset is utf-8
|
||||
SetConsoleCP(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
|
||||
}
|
||||
|
||||
|
@ -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 <fs.h>
|
||||
#include <wallet/bdb.h>
|
||||
#include <wallet/db.h>
|
||||
|
||||
@ -619,12 +620,12 @@ bool BerkeleyDatabase::Backup(const std::string& strDest) const
|
||||
pathDest /= fs::PathFromString(strFile);
|
||||
|
||||
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));
|
||||
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));
|
||||
return true;
|
||||
} catch (const fs::filesystem_error& e) {
|
||||
|
@ -8,18 +8,22 @@
|
||||
#include <logging.h>
|
||||
#include <wallet/db.h>
|
||||
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
|
||||
{
|
||||
const size_t offset = wallet_dir.native().size() + (wallet_dir == wallet_dir.root_name() ? 0 : 1);
|
||||
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)) {
|
||||
if (ec) {
|
||||
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()));
|
||||
} else {
|
||||
LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(it->path()));
|
||||
@ -33,11 +37,11 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
|
||||
const auto path_str = it->path().native().substr(offset);
|
||||
const fs::path path{path_str.begin(), path_str.end()};
|
||||
|
||||
if (it->status().type() == fs::directory_file &&
|
||||
if (it->status().type() == fs::file_type::directory &&
|
||||
(IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
|
||||
// Found a directory which contains wallet.dat btree file, add it as a wallet.
|
||||
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") {
|
||||
// Found top-level wallet.dat btree file, add top level directory ""
|
||||
// as a wallet.
|
||||
@ -52,7 +56,7 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
LogPrintf("%s: Error scanning %s: %s\n", __func__, fs::PathToString(it->path()), e.what());
|
||||
it.no_push();
|
||||
it.disable_recursion_pending();
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,12 +88,12 @@ bool IsBDBFile(const fs::path& path)
|
||||
|
||||
// A Berkeley DB Btree file has at least 4K.
|
||||
// This check also prevents opening lock files.
|
||||
boost::system::error_code ec;
|
||||
std::error_code ec;
|
||||
auto size = fs::file_size(path, ec);
|
||||
if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path));
|
||||
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;
|
||||
|
||||
file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
|
||||
@ -108,12 +112,12 @@ bool IsSQLiteFile(const fs::path& path)
|
||||
if (!fs::exists(path)) return false;
|
||||
|
||||
// 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);
|
||||
if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path));
|
||||
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;
|
||||
|
||||
// Magic is at beginning and is 16 bytes long
|
||||
|
@ -4,9 +4,17 @@
|
||||
|
||||
#include <wallet/dump.h>
|
||||
|
||||
#include <fs.h>
|
||||
#include <util/translation.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
static const std::string DUMP_MAGIC = "BITCOIN_CORE_WALLET_DUMP";
|
||||
uint32_t DUMP_VERSION = 1;
|
||||
|
||||
@ -25,7 +33,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));
|
||||
return false;
|
||||
}
|
||||
fsbridge::ofstream dump_file;
|
||||
std::ofstream dump_file;
|
||||
dump_file.open(path);
|
||||
if (dump_file.fail()) {
|
||||
error = strprintf(_("Unable to open %s for writing"), fs::PathToString(path));
|
||||
@ -120,7 +128,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));
|
||||
return false;
|
||||
}
|
||||
fsbridge::ifstream dump_file(dump_path);
|
||||
std::ifstream dump_file{dump_path};
|
||||
|
||||
// Compute the checksum
|
||||
CHashWriter hasher(0, 0);
|
||||
|
@ -7,6 +7,9 @@
|
||||
|
||||
#include <fs.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CWallet;
|
||||
|
||||
struct bilingual_str;
|
||||
|
@ -19,13 +19,15 @@
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
#include <system_error>
|
||||
|
||||
bool VerifyWallets(interfaces::Chain& chain)
|
||||
{
|
||||
if (gArgs.IsArgSet("-walletdir")) {
|
||||
fs::path wallet_dir = fs::PathFromString(gArgs.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
|
||||
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)) {
|
||||
chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), fs::PathToString(wallet_dir)));
|
||||
return false;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <chain.h>
|
||||
#include <clientversion.h>
|
||||
#include <core_io.h>
|
||||
#include <fs.h>
|
||||
#include <interfaces/chain.h>
|
||||
#include <key_io.h>
|
||||
#include <merkleblock.h>
|
||||
@ -21,11 +22,12 @@
|
||||
#include <util/translation.h>
|
||||
#include <validation.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <wallet/rpcwallet.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <tuple>
|
||||
#include <string>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
@ -509,7 +511,7 @@ RPCHelpMan importwallet()
|
||||
|
||||
EnsureWalletIsUnlocked(*pwallet);
|
||||
|
||||
fsbridge::ifstream file;
|
||||
std::ifstream file;
|
||||
file.open(fs::u8path(request.params[0].get_str()), std::ios::in | std::ios::ate);
|
||||
if (!file.is_open()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
|
||||
@ -662,7 +664,7 @@ RPCHelpMan importelectrumwallet()
|
||||
|
||||
EnsureWalletIsUnlocked(*pwallet);
|
||||
|
||||
fsbridge::ifstream file;
|
||||
std::ifstream file;
|
||||
std::string strFileName = request.params[0].get_str();
|
||||
size_t nDotPos = strFileName.find_last_of(".");
|
||||
if(nDotPos == std::string::npos)
|
||||
@ -948,7 +950,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");
|
||||
}
|
||||
|
||||
fsbridge::ofstream file;
|
||||
std::ofstream file;
|
||||
file.open(filepath);
|
||||
if (!file.is_open())
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
|
||||
|
@ -2,14 +2,15 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <fs.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <wallet/bdb.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(db_tests, BasicTestingSetup)
|
||||
|
||||
@ -25,7 +26,7 @@ BOOST_AUTO_TEST_CASE(getwalletenv_file)
|
||||
std::string test_name = "test_name.dat";
|
||||
const fs::path datadir = gArgs.GetDataDirNet();
|
||||
fs::path file_path = datadir / test_name;
|
||||
fs::ofstream f(file_path);
|
||||
std::ofstream f{file_path};
|
||||
f.close();
|
||||
|
||||
std::string filename;
|
||||
|
@ -7,6 +7,9 @@
|
||||
#include <util/check.h>
|
||||
#include <util/system.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <wallet/test/init_test_fixture.h>
|
||||
|
||||
InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
|
||||
@ -23,8 +26,8 @@ InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainNam
|
||||
m_walletdir_path_cases["custom"] = m_datadir / "my_wallets";
|
||||
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["trailing"] = m_datadir / "wallets" / sep;
|
||||
m_walletdir_path_cases["trailing2"] = m_datadir / "wallets" / sep / sep;
|
||||
m_walletdir_path_cases["trailing"] = m_datadir / ("wallets" + sep);
|
||||
m_walletdir_path_cases["trailing2"] = m_datadir / ("wallets" + sep + sep);
|
||||
|
||||
fs::current_path(m_datadir);
|
||||
m_walletdir_path_cases["relative"] = "wallets";
|
||||
@ -32,7 +35,7 @@ InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainNam
|
||||
fs::create_directories(m_walletdir_path_cases["default"]);
|
||||
fs::create_directories(m_walletdir_path_cases["custom"]);
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,8 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
|
||||
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)
|
||||
{
|
||||
SetWalletDir(m_walletdir_path_cases["trailing2"]);
|
||||
@ -92,5 +94,6 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
|
||||
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
|
||||
BOOST_CHECK_EQUAL(walletdir, expected_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -385,7 +385,7 @@ std::shared_ptr<CWallet> RestoreWallet(interfaces::Chain& chain, interfaces::Coi
|
||||
}
|
||||
|
||||
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(chain, coinjoin_loader, wallet_name, load_on_start, options, status, error, warnings);
|
||||
|
||||
@ -4662,9 +4662,9 @@ std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, cons
|
||||
// 4. For backwards compatibility, the name of a data file in -walletdir.
|
||||
const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name));
|
||||
fs::file_type path_type = fs::symlink_status(wallet_path).type();
|
||||
if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
|
||||
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
|
||||
(path_type == fs::regular_file && fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
|
||||
if (!(path_type == fs::file_type::not_found || path_type == fs::file_type::directory ||
|
||||
(path_type == fs::file_type::symlink && fs::is_directory(wallet_path)) ||
|
||||
(path_type == fs::file_type::regular && fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
|
||||
error_string = Untranslated(strprintf(
|
||||
"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, "
|
||||
@ -5232,7 +5232,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error
|
||||
}
|
||||
if(fs::exists(sourceFile)) {
|
||||
try {
|
||||
fs::copy_file(sourceFile, backupFile, fs::copy_option::fail_if_exists);
|
||||
fs::copy_file(sourceFile, backupFile, fs::copy_options::none);
|
||||
WalletLogPrintf("Creating backup of %s -> %s\n", fs::PathToString(sourceFile), fs::PathToString(backupFile));
|
||||
} catch(fs::filesystem_error &error) {
|
||||
warnings.push_back(strprintf(_("Failed to create backup, error: %s"), fsbridge::get_filesystem_error_message(error)));
|
||||
@ -5257,7 +5257,16 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error
|
||||
currentFile = dir_iter->path().filename();
|
||||
// Only add the backups for the current wallet, e.g. wallet.dat.*
|
||||
if (fs::PathToString(dir_iter->path().stem()) == strWalletName) {
|
||||
folder_set.insert(folder_set_t::value_type(fs::last_write_time(dir_iter->path()), *dir_iter));
|
||||
folder_set.insert(folder_set_t::value_type(
|
||||
// TODO: C++17 compliant time conversion code is abominable, switch to C++20
|
||||
// compliant code when C++17 support is dropped
|
||||
std::chrono::system_clock::to_time_t(
|
||||
std::chrono::time_point_cast<std::chrono::system_clock::duration>(
|
||||
fs::last_write_time(dir_iter->path()) - fs::file_time_type::clock::now() + std::chrono::system_clock::now()
|
||||
)
|
||||
),
|
||||
*dir_iter
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1073,7 +1073,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
||||
{
|
||||
bool exists;
|
||||
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) {
|
||||
error = Untranslated(strprintf("Failed to access database path '%s': %s", fs::PathToString(path), fsbridge::get_filesystem_error_message(e)));
|
||||
status = DatabaseStatus::FAILED_BAD_PATH;
|
||||
|
@ -11,6 +11,7 @@ from decimal import Decimal
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
import sys
|
||||
import time
|
||||
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
@ -141,7 +142,7 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
|
||||
# should raise rpc error if wallet path can't be created
|
||||
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
|
||||
self.stop_node(0)
|
||||
|
@ -50,8 +50,6 @@ fi
|
||||
|
||||
EXPECTED_BOOST_INCLUDES=(
|
||||
boost/date_time/posix_time/posix_time.hpp
|
||||
boost/filesystem.hpp
|
||||
boost/filesystem/fstream.hpp
|
||||
boost/multi_index/hashed_index.hpp
|
||||
boost/multi_index/ordered_index.hpp
|
||||
boost/multi_index/sequenced_index.hpp
|
||||
|
Loading…
Reference in New Issue
Block a user