mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-09 10:43:19 -05:00
Merge bitcoin/bitcoin#22937: refactor: Forbid calling unsafe fs::path(std::string) constructor and fs::path::string() method
6544ea5035
refactor: Block unsafe fs::path std::string conversion calls (Russell Yanofsky)b39a477ec6
refactor: Add fs::PathToString, fs::PathFromString, u8string, u8path functions (Russell Yanofsky) Pull request description: The `fs::path` class has a `std::string` constructor which will implicitly convert from strings. Implicit conversions like this are not great in general because they can hide complexity and inefficiencies in the code, but this case is especially bad, because after the transition from `boost::filesystem` to `std::filesystem` in #20744 the behavior of this constructor on windows will be more complicated and can mangle path strings. The `fs::path` class also has a `.string()` method which is inverse of the constructor and has the same problems. Fix this by replacing the unsafe method calls with `PathToString` and `PathFromString` function calls, and by forbidding unsafe method calls in the future. ACKs for top commit: kiminuo: ACK6544ea5035
laanwj: Code review ACK6544ea5035
hebasto: re-ACK6544ea5035
, only added `fsbridge_stem` test case, updated comment, and rebased since my [previous](https://github.com/bitcoin/bitcoin/pull/22937#pullrequestreview-765503126) review. Verified with the following command: Tree-SHA512: c36324740eb4ee55151146626166c00d5ccc4b6f3df777e75c112bcb4d1db436c1d9cc8c29a1e7fb96051457d317961ab42e6c380c3be2771d135771b2b49fa0
This commit is contained in:
commit
1884ce2f4c
44 changed files with 346 additions and 195 deletions
|
@ -58,7 +58,7 @@ bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data
|
||||||
if (fileout.IsNull()) {
|
if (fileout.IsNull()) {
|
||||||
fileout.fclose();
|
fileout.fclose();
|
||||||
remove(pathTmp);
|
remove(pathTmp);
|
||||||
return error("%s: Failed to open file %s", __func__, pathTmp.string());
|
return error("%s: Failed to open file %s", __func__, fs::PathToString(pathTmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize
|
// Serialize
|
||||||
|
@ -70,7 +70,7 @@ bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data
|
||||||
if (!FileCommit(fileout.Get())) {
|
if (!FileCommit(fileout.Get())) {
|
||||||
fileout.fclose();
|
fileout.fclose();
|
||||||
remove(pathTmp);
|
remove(pathTmp);
|
||||||
return error("%s: Failed to flush file %s", __func__, pathTmp.string());
|
return error("%s: Failed to flush file %s", __func__, fs::PathToString(pathTmp));
|
||||||
}
|
}
|
||||||
fileout.fclose();
|
fileout.fclose();
|
||||||
|
|
||||||
|
@ -122,8 +122,8 @@ void DeserializeFileDB(const fs::path& path, Data& data, int version)
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CBanDB::CBanDB(fs::path ban_list_path)
|
CBanDB::CBanDB(fs::path ban_list_path)
|
||||||
: m_banlist_dat(ban_list_path.string() + ".dat"),
|
: m_banlist_dat(ban_list_path + ".dat"),
|
||||||
m_banlist_json(ban_list_path.string() + ".json")
|
m_banlist_json(ban_list_path + ".json")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ bool CBanDB::Write(const banmap_t& banSet)
|
||||||
bool CBanDB::Read(banmap_t& banSet)
|
bool CBanDB::Read(banmap_t& banSet)
|
||||||
{
|
{
|
||||||
if (fs::exists(m_banlist_dat)) {
|
if (fs::exists(m_banlist_dat)) {
|
||||||
LogPrintf("banlist.dat ignored because it can only be read by " PACKAGE_NAME " version 22.x. Remove %s to silence this warning.\n", m_banlist_dat);
|
LogPrintf("banlist.dat ignored because it can only be read by " PACKAGE_NAME " version 22.x. Remove %s to silence this warning.\n", fs::quoted(fs::PathToString(m_banlist_dat)));
|
||||||
}
|
}
|
||||||
// If the JSON banlist does not exist, then recreate it
|
// If the JSON banlist does not exist, then recreate it
|
||||||
if (!fs::exists(m_banlist_json)) {
|
if (!fs::exists(m_banlist_json)) {
|
||||||
|
@ -155,7 +155,7 @@ bool CBanDB::Read(banmap_t& banSet)
|
||||||
|
|
||||||
if (!util::ReadSettings(m_banlist_json, settings, errors)) {
|
if (!util::ReadSettings(m_banlist_json, settings, errors)) {
|
||||||
for (const auto& err : errors) {
|
for (const auto& err : errors) {
|
||||||
LogPrintf("Cannot load banlist %s: %s\n", m_banlist_json.string(), err);
|
LogPrintf("Cannot load banlist %s: %s\n", fs::PathToString(m_banlist_json), err);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ bool CBanDB::Read(banmap_t& banSet)
|
||||||
try {
|
try {
|
||||||
BanMapFromJson(settings[JSON_KEY], banSet);
|
BanMapFromJson(settings[JSON_KEY], banSet);
|
||||||
} catch (const std::runtime_error& e) {
|
} catch (const std::runtime_error& e) {
|
||||||
LogPrintf("Cannot parse banlist %s: %s\n", m_banlist_json.string(), e.what());
|
LogPrintf("Cannot parse banlist %s: %s\n", fs::PathToString(m_banlist_json), e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,12 +194,12 @@ std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const A
|
||||||
} catch (const DbNotFoundError&) {
|
} catch (const DbNotFoundError&) {
|
||||||
// Addrman can be in an inconsistent state after failure, reset it
|
// Addrman can be in an inconsistent state after failure, reset it
|
||||||
addrman = std::make_unique<AddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
|
addrman = std::make_unique<AddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
|
||||||
LogPrintf("Creating peers.dat because the file was not found (%s)\n", path_addr);
|
LogPrintf("Creating peers.dat because the file was not found (%s)\n", fs::quoted(fs::PathToString(path_addr)));
|
||||||
DumpPeerAddresses(args, *addrman);
|
DumpPeerAddresses(args, *addrman);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
addrman = nullptr;
|
addrman = nullptr;
|
||||||
return strprintf(_("Invalid or corrupt peers.dat (%s). If you believe this is a bug, please report it to %s. As a workaround, you can move the file (%s) out of the way (rename, move, or delete) to have a new one created on the next start."),
|
return strprintf(_("Invalid or corrupt peers.dat (%s). If you believe this is a bug, please report it to %s. As a workaround, you can move the file (%s) out of the way (rename, move, or delete) to have a new one created on the next start."),
|
||||||
e.what(), PACKAGE_BUGREPORT, path_addr);
|
e.what(), PACKAGE_BUGREPORT, fs::quoted(fs::PathToString(path_addr)));
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ std::vector<CAddress> ReadAnchors(const fs::path& anchors_db_path)
|
||||||
std::vector<CAddress> anchors;
|
std::vector<CAddress> anchors;
|
||||||
try {
|
try {
|
||||||
DeserializeFileDB(anchors_db_path, anchors, CLIENT_VERSION | ADDRV2_FORMAT);
|
DeserializeFileDB(anchors_db_path, anchors, CLIENT_VERSION | ADDRV2_FORMAT);
|
||||||
LogPrintf("Loaded %i addresses from %s\n", anchors.size(), anchors_db_path.filename());
|
LogPrintf("Loaded %i addresses from %s\n", anchors.size(), fs::quoted(fs::PathToString(anchors_db_path.filename())));
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
anchors.clear();
|
anchors.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -786,7 +786,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
|
||||||
if (failedToGetAuthCookie) {
|
if (failedToGetAuthCookie) {
|
||||||
throw std::runtime_error(strprintf(
|
throw std::runtime_error(strprintf(
|
||||||
"Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
|
"Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
|
||||||
GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string()));
|
fs::PathToString(GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)))));
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
|
throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ static leveldb::Options GetOptions(size_t nCacheSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
|
CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
|
||||||
: m_name{path.stem().string()}
|
: m_name{fs::PathToString(path.stem())}
|
||||||
{
|
{
|
||||||
penv = nullptr;
|
penv = nullptr;
|
||||||
readoptions.verify_checksums = true;
|
readoptions.verify_checksums = true;
|
||||||
|
@ -129,21 +129,21 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo
|
||||||
options.env = penv;
|
options.env = penv;
|
||||||
} else {
|
} else {
|
||||||
if (fWipe) {
|
if (fWipe) {
|
||||||
LogPrintf("Wiping LevelDB in %s\n", path.string());
|
LogPrintf("Wiping LevelDB in %s\n", fs::PathToString(path));
|
||||||
leveldb::Status result = leveldb::DestroyDB(path.string(), options);
|
leveldb::Status result = leveldb::DestroyDB(fs::PathToString(path), options);
|
||||||
dbwrapper_private::HandleError(result);
|
dbwrapper_private::HandleError(result);
|
||||||
}
|
}
|
||||||
TryCreateDirectories(path);
|
TryCreateDirectories(path);
|
||||||
LogPrintf("Opening LevelDB in %s\n", path.string());
|
LogPrintf("Opening LevelDB in %s\n", fs::PathToString(path));
|
||||||
}
|
}
|
||||||
leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
|
leveldb::Status status = leveldb::DB::Open(options, fs::PathToString(path), &pdb);
|
||||||
dbwrapper_private::HandleError(status);
|
dbwrapper_private::HandleError(status);
|
||||||
LogPrintf("Opened LevelDB successfully\n");
|
LogPrintf("Opened LevelDB successfully\n");
|
||||||
|
|
||||||
if (gArgs.GetBoolArg("-forcecompactdb", false)) {
|
if (gArgs.GetBoolArg("-forcecompactdb", false)) {
|
||||||
LogPrintf("Starting database compaction of %s\n", path.string());
|
LogPrintf("Starting database compaction of %s\n", fs::PathToString(path));
|
||||||
pdb->CompactRange(nullptr, nullptr);
|
pdb->CompactRange(nullptr, nullptr);
|
||||||
LogPrintf("Finished database compaction of %s\n", path.string());
|
LogPrintf("Finished database compaction of %s\n", fs::PathToString(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The base-case obfuscation key, which is a noop.
|
// The base-case obfuscation key, which is a noop.
|
||||||
|
@ -160,10 +160,10 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo
|
||||||
Write(OBFUSCATE_KEY_KEY, new_key);
|
Write(OBFUSCATE_KEY_KEY, new_key);
|
||||||
obfuscate_key = new_key;
|
obfuscate_key = new_key;
|
||||||
|
|
||||||
LogPrintf("Wrote new obfuscate key for %s: %s\n", path.string(), HexStr(obfuscate_key));
|
LogPrintf("Wrote new obfuscate key for %s: %s\n", fs::PathToString(path), HexStr(obfuscate_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrintf("Using obfuscation key for %s: %s\n", path.string(), HexStr(obfuscate_key));
|
LogPrintf("Using obfuscation key for %s: %s\n", fs::PathToString(path), HexStr(obfuscate_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
CDBWrapper::~CDBWrapper()
|
CDBWrapper::~CDBWrapper()
|
||||||
|
|
|
@ -41,11 +41,11 @@ FILE* FlatFileSeq::Open(const FlatFilePos& pos, bool read_only)
|
||||||
if (!file && !read_only)
|
if (!file && !read_only)
|
||||||
file = fsbridge::fopen(path, "wb+");
|
file = fsbridge::fopen(path, "wb+");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
LogPrintf("Unable to open file %s\n", path.string());
|
LogPrintf("Unable to open file %s\n", fs::PathToString(path));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (pos.nPos && fseek(file, pos.nPos, SEEK_SET)) {
|
if (pos.nPos && fseek(file, pos.nPos, SEEK_SET)) {
|
||||||
LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string());
|
LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, fs::PathToString(path));
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace fsbridge {
|
||||||
FILE *fopen(const fs::path& p, const char *mode)
|
FILE *fopen(const fs::path& p, const char *mode)
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
return ::fopen(p.string().c_str(), mode);
|
return ::fopen(p.c_str(), mode);
|
||||||
#else
|
#else
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> utf8_cvt;
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> utf8_cvt;
|
||||||
return ::_wfopen(p.wstring().c_str(), utf8_cvt.from_bytes(mode).c_str());
|
return ::_wfopen(p.wstring().c_str(), utf8_cvt.from_bytes(mode).c_str());
|
||||||
|
@ -46,7 +46,7 @@ static std::string GetErrorReason()
|
||||||
|
|
||||||
FileLock::FileLock(const fs::path& file)
|
FileLock::FileLock(const fs::path& file)
|
||||||
{
|
{
|
||||||
fd = open(file.string().c_str(), O_RDWR);
|
fd = open(file.c_str(), O_RDWR);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
reason = GetErrorReason();
|
reason = GetErrorReason();
|
||||||
}
|
}
|
||||||
|
@ -249,9 +249,9 @@ void ofstream::close()
|
||||||
#else // __GLIBCXX__
|
#else // __GLIBCXX__
|
||||||
|
|
||||||
#if BOOST_VERSION >= 107700
|
#if BOOST_VERSION >= 107700
|
||||||
static_assert(sizeof(*BOOST_FILESYSTEM_C_STR(fs::path())) == sizeof(wchar_t),
|
static_assert(sizeof(*BOOST_FILESYSTEM_C_STR(boost::filesystem::path())) == sizeof(wchar_t),
|
||||||
#else
|
#else
|
||||||
static_assert(sizeof(*fs::path().BOOST_FILESYSTEM_C_STR) == sizeof(wchar_t),
|
static_assert(sizeof(*boost::filesystem::path().BOOST_FILESYSTEM_C_STR) == sizeof(wchar_t),
|
||||||
#endif // BOOST_VERSION >= 107700
|
#endif // BOOST_VERSION >= 107700
|
||||||
"Warning: This build is using boost::filesystem ofstream and ifstream "
|
"Warning: This build is using boost::filesystem ofstream and ifstream "
|
||||||
"implementations which will fail to open paths containing multibyte "
|
"implementations which will fail to open paths containing multibyte "
|
||||||
|
|
132
src/fs.h
132
src/fs.h
|
@ -13,9 +13,132 @@
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <tinyformat.h>
|
||||||
|
|
||||||
/** Filesystem operations and types */
|
/** Filesystem operations and types */
|
||||||
namespace fs = boost::filesystem;
|
namespace fs {
|
||||||
|
|
||||||
|
using namespace boost::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).
|
||||||
|
*/
|
||||||
|
class path : public boost::filesystem::path
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using boost::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; }
|
||||||
|
|
||||||
|
// 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; }
|
||||||
|
|
||||||
|
// Disallow std::string arguments to avoid locale-dependent decoding on windows.
|
||||||
|
path(std::string) = delete;
|
||||||
|
path& operator=(std::string) = delete;
|
||||||
|
path& operator/=(std::string) = delete;
|
||||||
|
path& append(std::string) = delete;
|
||||||
|
|
||||||
|
// 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(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// locale-dependent encoding on windows.
|
||||||
|
static inline path system_complete(const path& p)
|
||||||
|
{
|
||||||
|
return boost::filesystem::system_complete(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow explicit quoted stream I/O.
|
||||||
|
static inline auto quoted(const std::string& s)
|
||||||
|
{
|
||||||
|
return boost::io::quoted(s, '&');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow safe path append operations.
|
||||||
|
static inline path operator+(path p1, path p2)
|
||||||
|
{
|
||||||
|
p1 += std::move(p2);
|
||||||
|
return p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert path object to 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 used to call POSIX APIs, and
|
||||||
|
* for roundtrip conversion, logging, and debugging. But they are not
|
||||||
|
* guaranteed to be valid UTF-8, and are generally meant to be used internally,
|
||||||
|
* not externally. When communicating with external programs and libraries that
|
||||||
|
* require UTF-8, fs::path::u8string() and fs::u8path() methods can be used.
|
||||||
|
* For other applications, if support for non UTF-8 paths is required, or if
|
||||||
|
* higher-level JSON or XML or URI or C-style escapes are preferred, it may be
|
||||||
|
* also be appropriate to use different path encoding functions.
|
||||||
|
*
|
||||||
|
* Implementation note: On Windows, the std::filesystem::path(string)
|
||||||
|
* constructor and std::filesystem::path::string() method are not safe to use
|
||||||
|
* here, because these methods encode the path using C++'s narrow multibyte
|
||||||
|
* encoding, which on Windows corresponds to the current "code page", which is
|
||||||
|
* unpredictable and typically not able to represent all valid paths. So
|
||||||
|
* std::filesystem::path::u8string() and std::filesystem::u8path() functions
|
||||||
|
* are used instead on Windows. On POSIX, u8string/u8path functions are not
|
||||||
|
* safe to use because paths are not always valid UTF-8, so plain string
|
||||||
|
* methods which do not transform the path there are used.
|
||||||
|
*/
|
||||||
|
static inline std::string PathToString(const path& path)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
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();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert byte string to path object. Inverse of \ref PathToString.
|
||||||
|
*/
|
||||||
|
static inline path PathFromString(const std::string& string)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return u8path(string);
|
||||||
|
#else
|
||||||
|
return boost::filesystem::path(string);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} // namespace fs
|
||||||
|
|
||||||
/** Bridge operations to C stdio */
|
/** Bridge operations to C stdio */
|
||||||
namespace fsbridge {
|
namespace fsbridge {
|
||||||
|
@ -103,4 +226,11 @@ namespace fsbridge {
|
||||||
#endif // WIN32 && __GLIBCXX__
|
#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 fs::path&) = delete;
|
||||||
|
} // namespace tinyformat
|
||||||
|
|
||||||
#endif // BITCOIN_FS_H
|
#endif // BITCOIN_FS_H
|
||||||
|
|
|
@ -328,7 +328,7 @@ void Session::GenerateAndSavePrivateKey(const Sock& sock)
|
||||||
if (!WriteBinaryFile(m_private_key_file,
|
if (!WriteBinaryFile(m_private_key_file,
|
||||||
std::string(m_private_key.begin(), m_private_key.end()))) {
|
std::string(m_private_key.begin(), m_private_key.end()))) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
strprintf("Cannot save I2P private key to %s", m_private_key_file));
|
strprintf("Cannot save I2P private key to %s", fs::quoted(fs::PathToString(m_private_key_file))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
src/init.cpp
26
src/init.cpp
|
@ -113,7 +113,7 @@ static const char* BITCOIN_PID_FILENAME = "bitcoind.pid";
|
||||||
|
|
||||||
static fs::path GetPidFile(const ArgsManager& args)
|
static fs::path GetPidFile(const ArgsManager& args)
|
||||||
{
|
{
|
||||||
return AbsPathForConfigVal(fs::path(args.GetArg("-pid", BITCOIN_PID_FILENAME)));
|
return AbsPathForConfigVal(fs::PathFromString(args.GetArg("-pid", BITCOIN_PID_FILENAME)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static bool CreatePidFile(const ArgsManager& args)
|
[[nodiscard]] static bool CreatePidFile(const ArgsManager& args)
|
||||||
|
@ -127,7 +127,7 @@ static fs::path GetPidFile(const ArgsManager& args)
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile(args).string(), std::strerror(errno)));
|
return InitError(strprintf(_("Unable to create the PID file '%s': %s"), fs::PathToString(GetPidFile(args)), std::strerror(errno)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1062,10 +1062,10 @@ static bool LockDataDirectory(bool probeOnly)
|
||||||
// Make sure only a single Bitcoin process is using the data directory.
|
// Make sure only a single Bitcoin process is using the data directory.
|
||||||
fs::path datadir = gArgs.GetDataDirNet();
|
fs::path datadir = gArgs.GetDataDirNet();
|
||||||
if (!DirIsWritable(datadir)) {
|
if (!DirIsWritable(datadir)) {
|
||||||
return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), datadir.string()));
|
return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), fs::PathToString(datadir)));
|
||||||
}
|
}
|
||||||
if (!LockDirectory(datadir, ".lock", probeOnly)) {
|
if (!LockDirectory(datadir, ".lock", probeOnly)) {
|
||||||
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), datadir.string(), PACKAGE_NAME));
|
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), fs::PathToString(datadir), PACKAGE_NAME));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1126,12 +1126,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
|
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
|
||||||
|
|
||||||
// Warn about relative -datadir path.
|
// Warn about relative -datadir path.
|
||||||
if (args.IsArgSet("-datadir") && !fs::path(args.GetArg("-datadir", "")).is_absolute()) {
|
if (args.IsArgSet("-datadir") && !fs::PathFromString(args.GetArg("-datadir", "")).is_absolute()) {
|
||||||
LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " /* Continued */
|
LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " /* Continued */
|
||||||
"current working directory '%s'. This is fragile, because if bitcoin is started in the future "
|
"current working directory '%s'. This is fragile, because if bitcoin is started in the future "
|
||||||
"from a different location, it will be unable to locate the current data files. There could "
|
"from a different location, it will be unable to locate the current data files. There could "
|
||||||
"also be data loss if bitcoin is started while in a temporary directory.\n",
|
"also be data loss if bitcoin is started while in a temporary directory.\n",
|
||||||
args.GetArg("-datadir", ""), fs::current_path().string());
|
args.GetArg("-datadir", ""), fs::PathToString(fs::current_path()));
|
||||||
}
|
}
|
||||||
|
|
||||||
InitSignatureCache();
|
InitSignatureCache();
|
||||||
|
@ -1215,20 +1215,20 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
// Read asmap file if configured
|
// Read asmap file if configured
|
||||||
std::vector<bool> asmap;
|
std::vector<bool> asmap;
|
||||||
if (args.IsArgSet("-asmap")) {
|
if (args.IsArgSet("-asmap")) {
|
||||||
fs::path asmap_path = fs::path(args.GetArg("-asmap", ""));
|
fs::path asmap_path = fs::PathFromString(args.GetArg("-asmap", ""));
|
||||||
if (asmap_path.empty()) {
|
if (asmap_path.empty()) {
|
||||||
asmap_path = DEFAULT_ASMAP_FILENAME;
|
asmap_path = fs::PathFromString(DEFAULT_ASMAP_FILENAME);
|
||||||
}
|
}
|
||||||
if (!asmap_path.is_absolute()) {
|
if (!asmap_path.is_absolute()) {
|
||||||
asmap_path = gArgs.GetDataDirNet() / asmap_path;
|
asmap_path = gArgs.GetDataDirNet() / asmap_path;
|
||||||
}
|
}
|
||||||
if (!fs::exists(asmap_path)) {
|
if (!fs::exists(asmap_path)) {
|
||||||
InitError(strprintf(_("Could not find asmap file %s"), asmap_path));
|
InitError(strprintf(_("Could not find asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
asmap = DecodeAsmap(asmap_path);
|
asmap = DecodeAsmap(asmap_path);
|
||||||
if (asmap.size() == 0) {
|
if (asmap.size() == 0) {
|
||||||
InitError(strprintf(_("Could not parse asmap file %s"), asmap_path));
|
InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint256 asmap_version = SerializeHash(asmap);
|
const uint256 asmap_version = SerializeHash(asmap);
|
||||||
|
@ -1653,11 +1653,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
// ********************************************************* Step 11: import blocks
|
// ********************************************************* Step 11: import blocks
|
||||||
|
|
||||||
if (!CheckDiskSpace(gArgs.GetDataDirNet())) {
|
if (!CheckDiskSpace(gArgs.GetDataDirNet())) {
|
||||||
InitError(strprintf(_("Error: Disk space is low for %s"), gArgs.GetDataDirNet()));
|
InitError(strprintf(_("Error: Disk space is low for %s"), fs::quoted(fs::PathToString(gArgs.GetDataDirNet()))));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!CheckDiskSpace(gArgs.GetBlocksDirPath())) {
|
if (!CheckDiskSpace(gArgs.GetBlocksDirPath())) {
|
||||||
InitError(strprintf(_("Error: Disk space is low for %s"), gArgs.GetBlocksDirPath()));
|
InitError(strprintf(_("Error: Disk space is low for %s"), fs::quoted(fs::PathToString(gArgs.GetBlocksDirPath()))));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1685,7 +1685,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
|
|
||||||
std::vector<fs::path> vImportFiles;
|
std::vector<fs::path> vImportFiles;
|
||||||
for (const std::string& strFile : args.GetArgs("-loadblock")) {
|
for (const std::string& strFile : args.GetArgs("-loadblock")) {
|
||||||
vImportFiles.push_back(strFile);
|
vImportFiles.push_back(fs::PathFromString(strFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
chainman.m_load_block = std::thread(&util::TraceThread, "loadblk", [=, &chainman, &args] {
|
chainman.m_load_block = std::thread(&util::TraceThread, "loadblk", [=, &chainman, &args] {
|
||||||
|
|
|
@ -81,7 +81,7 @@ void AddLoggingArgs(ArgsManager& argsman)
|
||||||
void SetLoggingOptions(const ArgsManager& args)
|
void SetLoggingOptions(const ArgsManager& args)
|
||||||
{
|
{
|
||||||
LogInstance().m_print_to_file = !args.IsArgNegated("-debuglogfile");
|
LogInstance().m_print_to_file = !args.IsArgNegated("-debuglogfile");
|
||||||
LogInstance().m_file_path = AbsPathForConfigVal(args.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
|
LogInstance().m_file_path = AbsPathForConfigVal(fs::PathFromString(args.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)));
|
||||||
LogInstance().m_print_to_console = args.GetBoolArg("-printtoconsole", !args.GetBoolArg("-daemon", false));
|
LogInstance().m_print_to_console = args.GetBoolArg("-printtoconsole", !args.GetBoolArg("-daemon", false));
|
||||||
LogInstance().m_log_timestamps = args.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
|
LogInstance().m_log_timestamps = args.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
|
||||||
LogInstance().m_log_time_micros = args.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
|
LogInstance().m_log_time_micros = args.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
|
||||||
|
@ -128,24 +128,24 @@ bool StartLogging(const ArgsManager& args)
|
||||||
}
|
}
|
||||||
if (!LogInstance().StartLogging()) {
|
if (!LogInstance().StartLogging()) {
|
||||||
return InitError(strprintf(Untranslated("Could not open debug log file %s"),
|
return InitError(strprintf(Untranslated("Could not open debug log file %s"),
|
||||||
LogInstance().m_file_path.string()));
|
fs::PathToString(LogInstance().m_file_path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LogInstance().m_log_timestamps)
|
if (!LogInstance().m_log_timestamps)
|
||||||
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
|
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
|
||||||
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
|
LogPrintf("Default data directory %s\n", fs::PathToString(GetDefaultDataDir()));
|
||||||
LogPrintf("Using data directory %s\n", gArgs.GetDataDirNet().string());
|
LogPrintf("Using data directory %s\n", fs::PathToString(gArgs.GetDataDirNet()));
|
||||||
|
|
||||||
// Only log conf file usage message if conf file actually exists.
|
// Only log conf file usage message if conf file actually exists.
|
||||||
fs::path config_file_path = GetConfigFile(args.GetArg("-conf", BITCOIN_CONF_FILENAME));
|
fs::path config_file_path = GetConfigFile(args.GetArg("-conf", BITCOIN_CONF_FILENAME));
|
||||||
if (fs::exists(config_file_path)) {
|
if (fs::exists(config_file_path)) {
|
||||||
LogPrintf("Config file: %s\n", config_file_path.string());
|
LogPrintf("Config file: %s\n", fs::PathToString(config_file_path));
|
||||||
} else if (args.IsArgSet("-conf")) {
|
} else if (args.IsArgSet("-conf")) {
|
||||||
// Warn if no conf file exists at path provided by user
|
// Warn if no conf file exists at path provided by user
|
||||||
InitWarning(strprintf(_("The specified config file %s does not exist"), config_file_path.string()));
|
InitWarning(strprintf(_("The specified config file %s does not exist"), fs::PathToString(config_file_path)));
|
||||||
} else {
|
} else {
|
||||||
// Not categorizing as "Warning" because it's the default behavior
|
// Not categorizing as "Warning" because it's the default behavior
|
||||||
LogPrintf("Config file: %s (not found, skipping)\n", config_file_path.string());
|
LogPrintf("Config file: %s (not found, skipping)\n", fs::PathToString(config_file_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the config arguments to debug.log
|
// Log the config arguments to debug.log
|
||||||
|
|
|
@ -30,8 +30,8 @@ public:
|
||||||
return mp::SpawnProcess(pid, [&](int fd) {
|
return mp::SpawnProcess(pid, [&](int fd) {
|
||||||
fs::path path = argv0_path;
|
fs::path path = argv0_path;
|
||||||
path.remove_filename();
|
path.remove_filename();
|
||||||
path.append(new_exe_name);
|
path /= fs::PathFromString(new_exe_name);
|
||||||
return std::vector<std::string>{path.string(), "-ipcfd", strprintf("%i", fd)};
|
return std::vector<std::string>{fs::PathToString(path), "-ipcfd", strprintf("%i", fd)};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
int waitSpawned(int pid) override { return mp::WaitProcess(pid); }
|
int waitSpawned(int pid) override { return mp::WaitProcess(pid); }
|
||||||
|
|
|
@ -68,13 +68,14 @@ void CleanupBlockRevFiles()
|
||||||
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
|
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
|
||||||
fs::path blocksdir = gArgs.GetBlocksDirPath();
|
fs::path blocksdir = gArgs.GetBlocksDirPath();
|
||||||
for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
|
for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
|
||||||
|
const std::string path = fs::PathToString(it->path().filename());
|
||||||
if (fs::is_regular_file(*it) &&
|
if (fs::is_regular_file(*it) &&
|
||||||
it->path().filename().string().length() == 12 &&
|
path.length() == 12 &&
|
||||||
it->path().filename().string().substr(8,4) == ".dat")
|
path.substr(8,4) == ".dat")
|
||||||
{
|
{
|
||||||
if (it->path().filename().string().substr(0, 3) == "blk") {
|
if (path.substr(0, 3) == "blk") {
|
||||||
mapBlockFiles[it->path().filename().string().substr(3, 5)] = it->path();
|
mapBlockFiles[path.substr(3, 5)] = it->path();
|
||||||
} else if (it->path().filename().string().substr(0, 3) == "rev") {
|
} else if (path.substr(0, 3) == "rev") {
|
||||||
remove(it->path());
|
remove(it->path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,14 +528,14 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
|
||||||
for (const fs::path& path : vImportFiles) {
|
for (const fs::path& path : vImportFiles) {
|
||||||
FILE* file = fsbridge::fopen(path, "rb");
|
FILE* file = fsbridge::fopen(path, "rb");
|
||||||
if (file) {
|
if (file) {
|
||||||
LogPrintf("Importing blocks file %s...\n", path.string());
|
LogPrintf("Importing blocks file %s...\n", fs::PathToString(path));
|
||||||
chainman.ActiveChainstate().LoadExternalBlockFile(file);
|
chainman.ActiveChainstate().LoadExternalBlockFile(file);
|
||||||
if (ShutdownRequested()) {
|
if (ShutdownRequested()) {
|
||||||
LogPrintf("Shutdown requested. Exit %s\n", __func__);
|
LogPrintf("Shutdown requested. Exit %s\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("Warning: Could not open blocks file %s\n", path.string());
|
LogPrintf("Warning: Could not open blocks file %s\n", fs::PathToString(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -527,7 +527,7 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
|
||||||
fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
|
fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
|
||||||
CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
|
CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
|
||||||
if (est_file.IsNull() || !Read(est_file)) {
|
if (est_file.IsNull() || !Read(est_file)) {
|
||||||
LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", est_filepath.string());
|
LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", fs::PathToString(est_filepath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,7 +887,7 @@ void CBlockPolicyEstimator::Flush() {
|
||||||
fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
|
fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
|
||||||
CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
|
CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
|
||||||
if (est_file.IsNull() || !Write(est_file)) {
|
if (est_file.IsNull() || !Write(est_file)) {
|
||||||
LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", est_filepath.string());
|
LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", fs::PathToString(est_filepath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -653,12 +653,12 @@ void setClipboard(const QString& str)
|
||||||
|
|
||||||
fs::path qstringToBoostPath(const QString &path)
|
fs::path qstringToBoostPath(const QString &path)
|
||||||
{
|
{
|
||||||
return fs::path(path.toStdString());
|
return fs::u8path(path.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString boostPathToQString(const fs::path &path)
|
QString boostPathToQString(const fs::path &path)
|
||||||
{
|
{
|
||||||
return QString::fromStdString(path.string());
|
return QString::fromStdString(path.u8string());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString NetworkToQString(Network net)
|
QString NetworkToQString(Network net)
|
||||||
|
|
|
@ -263,7 +263,7 @@ bool Intro::showIfNeeded(bool& did_show_intro, int64_t& prune_MiB)
|
||||||
* (to be consistent with bitcoind behavior)
|
* (to be consistent with bitcoind behavior)
|
||||||
*/
|
*/
|
||||||
if(dataDir != GUIUtil::getDefaultDataDirectory()) {
|
if(dataDir != GUIUtil::getDefaultDataDirectory()) {
|
||||||
gArgs.SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting
|
gArgs.SoftSetArg("-datadir", fs::PathToString(GUIUtil::qstringToBoostPath(dataDir))); // use OS locale for path setting
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2537,15 +2537,15 @@ static RPCHelpMan dumptxoutset()
|
||||||
},
|
},
|
||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||||
{
|
{
|
||||||
const fs::path path = fsbridge::AbsPathJoin(gArgs.GetDataDirNet(), request.params[0].get_str());
|
const fs::path path = fsbridge::AbsPathJoin(gArgs.GetDataDirNet(), fs::u8path(request.params[0].get_str()));
|
||||||
// Write to a temporary path and then move into `path` on completion
|
// Write to a temporary path and then move into `path` on completion
|
||||||
// to avoid confusion due to an interruption.
|
// to avoid confusion due to an interruption.
|
||||||
const fs::path temppath = fsbridge::AbsPathJoin(gArgs.GetDataDirNet(), request.params[0].get_str() + ".incomplete");
|
const fs::path temppath = fsbridge::AbsPathJoin(gArgs.GetDataDirNet(), fs::u8path(request.params[0].get_str() + ".incomplete"));
|
||||||
|
|
||||||
if (fs::exists(path)) {
|
if (fs::exists(path)) {
|
||||||
throw JSONRPCError(
|
throw JSONRPCError(
|
||||||
RPC_INVALID_PARAMETER,
|
RPC_INVALID_PARAMETER,
|
||||||
path.string() + " already exists. If you are sure this is what you want, "
|
path.u8string() + " already exists. If you are sure this is what you want, "
|
||||||
"move it out of the way first");
|
"move it out of the way first");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2555,7 +2555,7 @@ static RPCHelpMan dumptxoutset()
|
||||||
UniValue result = CreateUTXOSnapshot(node, node.chainman->ActiveChainstate(), afile);
|
UniValue result = CreateUTXOSnapshot(node, node.chainman->ActiveChainstate(), afile);
|
||||||
fs::rename(temppath, path);
|
fs::rename(temppath, path);
|
||||||
|
|
||||||
result.pushKV("path", path.string());
|
result.pushKV("path", path.u8string());
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,7 +70,7 @@ static fs::path GetAuthCookieFile(bool temp=false)
|
||||||
if (temp) {
|
if (temp) {
|
||||||
arg += ".tmp";
|
arg += ".tmp";
|
||||||
}
|
}
|
||||||
return AbsPathForConfigVal(fs::path(arg));
|
return AbsPathForConfigVal(fs::PathFromString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GenerateAuthCookie(std::string *cookie_out)
|
bool GenerateAuthCookie(std::string *cookie_out)
|
||||||
|
@ -87,7 +87,7 @@ bool GenerateAuthCookie(std::string *cookie_out)
|
||||||
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()) {
|
||||||
LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath_tmp.string());
|
LogPrintf("Unable to open cookie authentication file %s for writing\n", fs::PathToString(filepath_tmp));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file << cookie;
|
file << cookie;
|
||||||
|
@ -95,10 +95,10 @@ bool GenerateAuthCookie(std::string *cookie_out)
|
||||||
|
|
||||||
fs::path filepath = GetAuthCookieFile(false);
|
fs::path filepath = GetAuthCookieFile(false);
|
||||||
if (!RenameOver(filepath_tmp, filepath)) {
|
if (!RenameOver(filepath_tmp, filepath)) {
|
||||||
LogPrintf("Unable to rename cookie authentication file %s to %s\n", filepath_tmp.string(), filepath.string());
|
LogPrintf("Unable to rename cookie authentication file %s to %s\n", fs::PathToString(filepath_tmp), fs::PathToString(filepath));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LogPrintf("Generated RPC authentication cookie %s\n", filepath.string());
|
LogPrintf("Generated RPC authentication cookie %s\n", fs::PathToString(filepath));
|
||||||
|
|
||||||
if (cookie_out)
|
if (cookie_out)
|
||||||
*cookie_out = cookie;
|
*cookie_out = cookie;
|
||||||
|
|
|
@ -239,7 +239,7 @@ static RPCHelpMan getrpcinfo()
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
result.pushKV("active_commands", active_commands);
|
result.pushKV("active_commands", active_commands);
|
||||||
|
|
||||||
const std::string path = LogInstance().m_file_path.string();
|
const std::string path = LogInstance().m_file_path.u8string();
|
||||||
UniValue log_path(UniValue::VSTR, path);
|
UniValue log_path(UniValue::VSTR, path);
|
||||||
result.pushKV("logpath", log_path);
|
result.pushKV("logpath", log_path);
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,33 @@
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(fsbridge_pathtostring)
|
||||||
|
{
|
||||||
|
std::string u8_str = "fs_tests_₿_🏃";
|
||||||
|
BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(u8_str)), u8_str);
|
||||||
|
BOOST_CHECK_EQUAL(fs::u8path(u8_str).u8string(), u8_str);
|
||||||
|
BOOST_CHECK_EQUAL(fs::PathFromString(u8_str).u8string(), u8_str);
|
||||||
|
BOOST_CHECK_EQUAL(fs::PathToString(fs::u8path(u8_str)), u8_str);
|
||||||
|
#ifndef WIN32
|
||||||
|
// On non-windows systems, verify that arbitrary byte strings containing
|
||||||
|
// invalid UTF-8 can be round tripped successfully with PathToString and
|
||||||
|
// PathFromString. On non-windows systems, paths are just byte strings so
|
||||||
|
// these functions do not do any encoding. On windows, paths are Unicode,
|
||||||
|
// and these functions do encoding and decoding, so the behavior of this
|
||||||
|
// test would be undefined.
|
||||||
|
std::string invalid_u8_str = "\xf0";
|
||||||
|
BOOST_CHECK_EQUAL(invalid_u8_str.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(invalid_u8_str)), invalid_u8_str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(fsbridge_stem)
|
||||||
|
{
|
||||||
|
std::string test_filename = "fs_tests_₿_🏃.dat";
|
||||||
|
std::string expected_stem = "fs_tests_₿_🏃";
|
||||||
|
BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(test_filename).stem()), expected_stem);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(fsbridge_fstream)
|
BOOST_AUTO_TEST_CASE(fsbridge_fstream)
|
||||||
{
|
{
|
||||||
fs::path tmpfolder = m_args.GetDataDirBase();
|
fs::path tmpfolder = m_args.GetDataDirBase();
|
||||||
|
|
|
@ -48,7 +48,7 @@ FUZZ_TARGET_INIT(banman, initialize_banman)
|
||||||
const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()};
|
const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()};
|
||||||
bool force_read_and_write_to_err{false};
|
bool force_read_and_write_to_err{false};
|
||||||
if (start_with_corrupted_banlist) {
|
if (start_with_corrupted_banlist) {
|
||||||
assert(WriteBinaryFile(banlist_file.string() + ".json",
|
assert(WriteBinaryFile(banlist_file + ".json",
|
||||||
fuzzed_data_provider.ConsumeRandomLengthString()));
|
fuzzed_data_provider.ConsumeRandomLengthString()));
|
||||||
} else {
|
} else {
|
||||||
force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool();
|
force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool();
|
||||||
|
@ -111,5 +111,5 @@ FUZZ_TARGET_INIT(banman, initialize_banman)
|
||||||
assert(banmap == banmap_read);
|
assert(banmap == banmap_read);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fs::remove(banlist_file.string() + ".json");
|
fs::remove(fs::PathToString(banlist_file + ".json"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,19 +80,19 @@ BOOST_AUTO_TEST_CASE(ReadWrite)
|
||||||
"dupe": "dupe"
|
"dupe": "dupe"
|
||||||
})");
|
})");
|
||||||
BOOST_CHECK(!util::ReadSettings(path, values, errors));
|
BOOST_CHECK(!util::ReadSettings(path, values, errors));
|
||||||
std::vector<std::string> dup_keys = {strprintf("Found duplicate key dupe in settings file %s", path.string())};
|
std::vector<std::string> dup_keys = {strprintf("Found duplicate key dupe in settings file %s", fs::PathToString(path))};
|
||||||
BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), dup_keys.begin(), dup_keys.end());
|
BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), dup_keys.begin(), dup_keys.end());
|
||||||
|
|
||||||
// Check non-kv json files not allowed
|
// Check non-kv json files not allowed
|
||||||
WriteText(path, R"("non-kv")");
|
WriteText(path, R"("non-kv")");
|
||||||
BOOST_CHECK(!util::ReadSettings(path, values, errors));
|
BOOST_CHECK(!util::ReadSettings(path, values, errors));
|
||||||
std::vector<std::string> non_kv = {strprintf("Found non-object value \"non-kv\" in settings file %s", path.string())};
|
std::vector<std::string> non_kv = {strprintf("Found non-object value \"non-kv\" in settings file %s", fs::PathToString(path))};
|
||||||
BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), non_kv.begin(), non_kv.end());
|
BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), non_kv.begin(), non_kv.end());
|
||||||
|
|
||||||
// Check invalid json not allowed
|
// Check invalid json not allowed
|
||||||
WriteText(path, R"(invalid json)");
|
WriteText(path, R"(invalid json)");
|
||||||
BOOST_CHECK(!util::ReadSettings(path, values, errors));
|
BOOST_CHECK(!util::ReadSettings(path, values, errors));
|
||||||
std::vector<std::string> fail_parse = {strprintf("Unable to parse settings file %s", path.string())};
|
std::vector<std::string> fail_parse = {strprintf("Unable to parse settings file %s", fs::PathToString(path))};
|
||||||
BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), fail_parse.begin(), fail_parse.end());
|
BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), fail_parse.begin(), fail_parse.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ CreateAndActivateUTXOSnapshot(NodeContext& node, const fs::path root, F malleati
|
||||||
|
|
||||||
UniValue result = CreateUTXOSnapshot(node, node.chainman->ActiveChainstate(), auto_outfile);
|
UniValue result = CreateUTXOSnapshot(node, node.chainman->ActiveChainstate(), auto_outfile);
|
||||||
BOOST_TEST_MESSAGE(
|
BOOST_TEST_MESSAGE(
|
||||||
"Wrote UTXO snapshot to " << snapshot_path.make_preferred().string() << ": " << result.write());
|
"Wrote UTXO snapshot to " << fs::PathToString(snapshot_path.make_preferred()) << ": " << result.write());
|
||||||
|
|
||||||
// Read the written snapshot in and then activate it.
|
// Read the written snapshot in and then activate it.
|
||||||
//
|
//
|
||||||
|
|
|
@ -91,8 +91,8 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
|
||||||
extra_args);
|
extra_args);
|
||||||
util::ThreadRename("test");
|
util::ThreadRename("test");
|
||||||
fs::create_directories(m_path_root);
|
fs::create_directories(m_path_root);
|
||||||
m_args.ForceSetArg("-datadir", m_path_root.string());
|
m_args.ForceSetArg("-datadir", fs::PathToString(m_path_root));
|
||||||
gArgs.ForceSetArg("-datadir", m_path_root.string());
|
gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root));
|
||||||
gArgs.ClearPathCache();
|
gArgs.ClearPathCache();
|
||||||
{
|
{
|
||||||
SetupServerArgs(*m_node.args);
|
SetupServerArgs(*m_node.args);
|
||||||
|
|
|
@ -51,23 +51,23 @@ BOOST_AUTO_TEST_CASE(util_datadir)
|
||||||
{
|
{
|
||||||
// Use local args variable instead of m_args to avoid making assumptions about test setup
|
// Use local args variable instead of m_args to avoid making assumptions about test setup
|
||||||
ArgsManager args;
|
ArgsManager args;
|
||||||
args.ForceSetArg("-datadir", m_path_root.string());
|
args.ForceSetArg("-datadir", fs::PathToString(m_path_root));
|
||||||
|
|
||||||
const fs::path dd_norm = args.GetDataDirBase();
|
const fs::path dd_norm = args.GetDataDirBase();
|
||||||
|
|
||||||
args.ForceSetArg("-datadir", dd_norm.string() + "/");
|
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());
|
||||||
|
|
||||||
args.ForceSetArg("-datadir", dd_norm.string() + "/.");
|
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());
|
||||||
|
|
||||||
args.ForceSetArg("-datadir", dd_norm.string() + "/./");
|
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());
|
||||||
|
|
||||||
args.ForceSetArg("-datadir", dd_norm.string() + "/.//");
|
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());
|
||||||
}
|
}
|
||||||
|
@ -1181,13 +1181,13 @@ BOOST_AUTO_TEST_CASE(util_ReadWriteSettings)
|
||||||
{
|
{
|
||||||
// Test writing setting.
|
// Test writing setting.
|
||||||
TestArgsManager args1;
|
TestArgsManager args1;
|
||||||
args1.ForceSetArg("-datadir", m_path_root.string());
|
args1.ForceSetArg("-datadir", fs::PathToString(m_path_root));
|
||||||
args1.LockSettings([&](util::Settings& settings) { settings.rw_settings["name"] = "value"; });
|
args1.LockSettings([&](util::Settings& settings) { settings.rw_settings["name"] = "value"; });
|
||||||
args1.WriteSettingsFile();
|
args1.WriteSettingsFile();
|
||||||
|
|
||||||
// Test reading setting.
|
// Test reading setting.
|
||||||
TestArgsManager args2;
|
TestArgsManager args2;
|
||||||
args2.ForceSetArg("-datadir", m_path_root.string());
|
args2.ForceSetArg("-datadir", fs::PathToString(m_path_root));
|
||||||
args2.ReadSettingsFile();
|
args2.ReadSettingsFile();
|
||||||
args2.LockSettings([&](util::Settings& settings) { BOOST_CHECK_EQUAL(settings.rw_settings["name"].get_str(), "value"); });
|
args2.LockSettings([&](util::Settings& settings) { BOOST_CHECK_EQUAL(settings.rw_settings["name"].get_str(), "value"); });
|
||||||
|
|
||||||
|
|
|
@ -318,7 +318,7 @@ TorController::TorController(struct event_base* _base, const std::string& tor_co
|
||||||
// Read service private key if cached
|
// Read service private key if cached
|
||||||
std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
|
std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
|
||||||
if (pkf.first) {
|
if (pkf.first) {
|
||||||
LogPrint(BCLog::TOR, "tor: Reading cached private key from %s\n", GetPrivateKeyFile().string());
|
LogPrint(BCLog::TOR, "tor: Reading cached private key from %s\n", fs::PathToString(GetPrivateKeyFile()));
|
||||||
private_key = pkf.second;
|
private_key = pkf.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,9 +356,9 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe
|
||||||
service = LookupNumeric(std::string(service_id+".onion"), Params().GetDefaultPort());
|
service = LookupNumeric(std::string(service_id+".onion"), Params().GetDefaultPort());
|
||||||
LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString());
|
LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString());
|
||||||
if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) {
|
if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) {
|
||||||
LogPrint(BCLog::TOR, "tor: Cached service private key to %s\n", GetPrivateKeyFile().string());
|
LogPrint(BCLog::TOR, "tor: Cached service private key to %s\n", fs::PathToString(GetPrivateKeyFile()));
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("tor: Error writing service private key to %s\n", GetPrivateKeyFile().string());
|
LogPrintf("tor: Error writing service private key to %s\n", fs::PathToString(GetPrivateKeyFile()));
|
||||||
}
|
}
|
||||||
AddLocal(service, LOCAL_MANUAL);
|
AddLocal(service, LOCAL_MANUAL);
|
||||||
// ... onion requested - keep connection open
|
// ... onion requested - keep connection open
|
||||||
|
@ -508,7 +508,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro
|
||||||
} else if (methods.count("SAFECOOKIE")) {
|
} else if (methods.count("SAFECOOKIE")) {
|
||||||
// Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie
|
// Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie
|
||||||
LogPrint(BCLog::TOR, "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile);
|
LogPrint(BCLog::TOR, "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile);
|
||||||
std::pair<bool,std::string> status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE);
|
std::pair<bool,std::string> status_cookie = ReadBinaryFile(fs::PathFromString(cookiefile), TOR_COOKIE_SIZE);
|
||||||
if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) {
|
if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) {
|
||||||
// _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2));
|
// _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end());
|
cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end());
|
||||||
|
|
|
@ -201,7 +201,7 @@ std::vector<bool> DecodeAsmap(fs::path path)
|
||||||
}
|
}
|
||||||
fseek(filestr, 0, SEEK_END);
|
fseek(filestr, 0, SEEK_END);
|
||||||
int length = ftell(filestr);
|
int length = ftell(filestr);
|
||||||
LogPrintf("Opened asmap file %s (%d bytes) from disk\n", path, length);
|
LogPrintf("Opened asmap file %s (%d bytes) from disk\n", fs::quoted(fs::PathToString(path)), length);
|
||||||
fseek(filestr, 0, SEEK_SET);
|
fseek(filestr, 0, SEEK_SET);
|
||||||
uint8_t cur_byte;
|
uint8_t cur_byte;
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
|
@ -211,7 +211,7 @@ std::vector<bool> DecodeAsmap(fs::path path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!SanityCheckASMap(bits, 128)) {
|
if (!SanityCheckASMap(bits, 128)) {
|
||||||
LogPrintf("Sanity check of asmap file %s failed\n", path);
|
LogPrintf("Sanity check of asmap file %s failed\n", fs::quoted(fs::PathToString(path)));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return bits;
|
return bits;
|
||||||
|
|
|
@ -66,24 +66,24 @@ bool ReadSettings(const fs::path& path, std::map<std::string, SettingsValue>& va
|
||||||
fsbridge::ifstream file;
|
fsbridge::ifstream file;
|
||||||
file.open(path);
|
file.open(path);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
errors.emplace_back(strprintf("%s. Please check permissions.", path.string()));
|
errors.emplace_back(strprintf("%s. Please check permissions.", fs::PathToString(path)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsValue in;
|
SettingsValue in;
|
||||||
if (!in.read(std::string{std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()})) {
|
if (!in.read(std::string{std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()})) {
|
||||||
errors.emplace_back(strprintf("Unable to parse settings file %s", path.string()));
|
errors.emplace_back(strprintf("Unable to parse settings file %s", fs::PathToString(path)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.fail()) {
|
if (file.fail()) {
|
||||||
errors.emplace_back(strprintf("Failed reading settings file %s", path.string()));
|
errors.emplace_back(strprintf("Failed reading settings file %s", fs::PathToString(path)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file.close(); // Done with file descriptor. Release while copying data.
|
file.close(); // Done with file descriptor. Release while copying data.
|
||||||
|
|
||||||
if (!in.isObject()) {
|
if (!in.isObject()) {
|
||||||
errors.emplace_back(strprintf("Found non-object value %s in settings file %s", in.write(), path.string()));
|
errors.emplace_back(strprintf("Found non-object value %s in settings file %s", in.write(), fs::PathToString(path)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ bool ReadSettings(const fs::path& path, std::map<std::string, SettingsValue>& va
|
||||||
for (size_t i = 0; i < in_keys.size(); ++i) {
|
for (size_t i = 0; i < in_keys.size(); ++i) {
|
||||||
auto inserted = values.emplace(in_keys[i], in_values[i]);
|
auto inserted = values.emplace(in_keys[i], in_values[i]);
|
||||||
if (!inserted.second) {
|
if (!inserted.second) {
|
||||||
errors.emplace_back(strprintf("Found duplicate key %s in settings file %s", in_keys[i], path.string()));
|
errors.emplace_back(strprintf("Found duplicate key %s in settings file %s", in_keys[i], fs::PathToString(path)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return errors.empty();
|
return errors.empty();
|
||||||
|
@ -109,7 +109,7 @@ bool WriteSettings(const fs::path& path,
|
||||||
fsbridge::ofstream file;
|
fsbridge::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", path.string()));
|
errors.emplace_back(strprintf("Error: Unable to open settings file %s for writing", fs::PathToString(path)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file << out.write(/* prettyIndent= */ 1, /* indentLevel= */ 4) << std::endl;
|
file << out.write(/* prettyIndent= */ 1, /* indentLevel= */ 4) << std::endl;
|
||||||
|
|
|
@ -98,7 +98,7 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b
|
||||||
fs::path pathLockFile = directory / lockfile_name;
|
fs::path pathLockFile = directory / lockfile_name;
|
||||||
|
|
||||||
// If a lock for this directory already exists in the map, don't try to re-lock it
|
// If a lock for this directory already exists in the map, don't try to re-lock it
|
||||||
if (dir_locks.count(pathLockFile.string())) {
|
if (dir_locks.count(fs::PathToString(pathLockFile))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,11 +107,11 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b
|
||||||
if (file) fclose(file);
|
if (file) fclose(file);
|
||||||
auto lock = std::make_unique<fsbridge::FileLock>(pathLockFile);
|
auto lock = std::make_unique<fsbridge::FileLock>(pathLockFile);
|
||||||
if (!lock->TryLock()) {
|
if (!lock->TryLock()) {
|
||||||
return error("Error while attempting to lock directory %s: %s", directory.string(), lock->GetReason());
|
return error("Error while attempting to lock directory %s: %s", fs::PathToString(directory), lock->GetReason());
|
||||||
}
|
}
|
||||||
if (!probe_only) {
|
if (!probe_only) {
|
||||||
// Lock successful and we're not just probing, put it into the map
|
// Lock successful and we're not just probing, put it into the map
|
||||||
dir_locks.emplace(pathLockFile.string(), std::move(lock));
|
dir_locks.emplace(fs::PathToString(pathLockFile), std::move(lock));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b
|
||||||
void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name)
|
void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name)
|
||||||
{
|
{
|
||||||
LOCK(cs_dir_locks);
|
LOCK(cs_dir_locks);
|
||||||
dir_locks.erase((directory / lockfile_name).string());
|
dir_locks.erase(fs::PathToString(directory / lockfile_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseDirectoryLocks()
|
void ReleaseDirectoryLocks()
|
||||||
|
@ -242,7 +242,7 @@ namespace {
|
||||||
fs::path StripRedundantLastElementsOfPath(const fs::path& path)
|
fs::path StripRedundantLastElementsOfPath(const fs::path& path)
|
||||||
{
|
{
|
||||||
auto result = path;
|
auto result = path;
|
||||||
while (result.filename().string() == ".") {
|
while (fs::PathToString(result.filename()) == ".") {
|
||||||
result = result.parent_path();
|
result = result.parent_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +402,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(GetArg("-blocksdir", ""));
|
path = fs::system_complete(fs::PathFromString(GetArg("-blocksdir", "")));
|
||||||
if (!fs::is_directory(path)) {
|
if (!fs::is_directory(path)) {
|
||||||
path = "";
|
path = "";
|
||||||
return path;
|
return path;
|
||||||
|
@ -411,7 +411,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
|
||||||
path = GetDataDirBase();
|
path = GetDataDirBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
path /= BaseParams().DataDir();
|
path /= fs::PathFromString(BaseParams().DataDir());
|
||||||
path /= "blocks";
|
path /= "blocks";
|
||||||
fs::create_directories(path);
|
fs::create_directories(path);
|
||||||
path = StripRedundantLastElementsOfPath(path);
|
path = StripRedundantLastElementsOfPath(path);
|
||||||
|
@ -429,7 +429,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(datadir);
|
path = fs::system_complete(fs::PathFromString(datadir));
|
||||||
if (!fs::is_directory(path)) {
|
if (!fs::is_directory(path)) {
|
||||||
path = "";
|
path = "";
|
||||||
return path;
|
return path;
|
||||||
|
@ -438,7 +438,7 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
|
||||||
path = GetDefaultDataDir();
|
path = GetDefaultDataDir();
|
||||||
}
|
}
|
||||||
if (net_specific)
|
if (net_specific)
|
||||||
path /= BaseParams().DataDir();
|
path /= fs::PathFromString(BaseParams().DataDir());
|
||||||
|
|
||||||
if (fs::create_directories(path)) {
|
if (fs::create_directories(path)) {
|
||||||
// This is the first run, create wallets subdirectory too
|
// This is the first run, create wallets subdirectory too
|
||||||
|
@ -517,7 +517,7 @@ bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp) const
|
||||||
}
|
}
|
||||||
if (filepath) {
|
if (filepath) {
|
||||||
std::string settings = GetArg("-settings", BITCOIN_SETTINGS_FILENAME);
|
std::string settings = GetArg("-settings", BITCOIN_SETTINGS_FILENAME);
|
||||||
*filepath = fsbridge::AbsPathJoin(GetDataDirNet(), temp ? settings + ".tmp" : settings);
|
*filepath = fsbridge::AbsPathJoin(GetDataDirNet(), fs::PathFromString(temp ? settings + ".tmp" : settings));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -572,7 +572,7 @@ bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!RenameOver(path_tmp, path)) {
|
if (!RenameOver(path_tmp, path)) {
|
||||||
SaveErrors({strprintf("Failed renaming settings file %s to %s\n", path_tmp.string(), path.string())}, errors);
|
SaveErrors({strprintf("Failed renaming settings file %s to %s\n", fs::PathToString(path_tmp), fs::PathToString(path))}, errors);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -809,12 +809,12 @@ 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(datadir));
|
return datadir.empty() || fs::is_directory(fs::system_complete(fs::PathFromString(datadir)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path GetConfigFile(const std::string& confPath)
|
fs::path GetConfigFile(const std::string& confPath)
|
||||||
{
|
{
|
||||||
return AbsPathForConfigVal(fs::path(confPath), false);
|
return AbsPathForConfigVal(fs::PathFromString(confPath), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections)
|
static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections)
|
||||||
|
@ -1065,7 +1065,7 @@ bool RenameOver(fs::path src, fs::path dest)
|
||||||
return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
|
return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
|
||||||
MOVEFILE_REPLACE_EXISTING) != 0;
|
MOVEFILE_REPLACE_EXISTING) != 0;
|
||||||
#else
|
#else
|
||||||
int rc = std::rename(src.string().c_str(), dest.string().c_str());
|
int rc = std::rename(src.c_str(), dest.c_str());
|
||||||
return (rc == 0);
|
return (rc == 0);
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,9 +61,9 @@ bool WalletDatabaseFileId::operator==(const WalletDatabaseFileId& rhs) const
|
||||||
std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory)
|
std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory)
|
||||||
{
|
{
|
||||||
LOCK(cs_db);
|
LOCK(cs_db);
|
||||||
auto inserted = g_dbenvs.emplace(env_directory.string(), std::weak_ptr<BerkeleyEnvironment>());
|
auto inserted = g_dbenvs.emplace(fs::PathToString(env_directory), std::weak_ptr<BerkeleyEnvironment>());
|
||||||
if (inserted.second) {
|
if (inserted.second) {
|
||||||
auto env = std::make_shared<BerkeleyEnvironment>(env_directory.string());
|
auto env = std::make_shared<BerkeleyEnvironment>(env_directory);
|
||||||
inserted.first->second = env;
|
inserted.first->second = env;
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ void BerkeleyEnvironment::Close()
|
||||||
|
|
||||||
if (error_file) fclose(error_file);
|
if (error_file) fclose(error_file);
|
||||||
|
|
||||||
UnlockDirectory(strPath, ".walletlock");
|
UnlockDirectory(fs::PathFromString(strPath), ".walletlock");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BerkeleyEnvironment::Reset()
|
void BerkeleyEnvironment::Reset()
|
||||||
|
@ -111,7 +111,7 @@ void BerkeleyEnvironment::Reset()
|
||||||
fMockDb = false;
|
fMockDb = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BerkeleyEnvironment::BerkeleyEnvironment(const fs::path& dir_path) : strPath(dir_path.string())
|
BerkeleyEnvironment::BerkeleyEnvironment(const fs::path& dir_path) : strPath(fs::PathToString(dir_path))
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
@ -129,24 +129,24 @@ bool BerkeleyEnvironment::Open(bilingual_str& err)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path pathIn = strPath;
|
fs::path pathIn = fs::PathFromString(strPath);
|
||||||
TryCreateDirectories(pathIn);
|
TryCreateDirectories(pathIn);
|
||||||
if (!LockDirectory(pathIn, ".walletlock")) {
|
if (!LockDirectory(pathIn, ".walletlock")) {
|
||||||
LogPrintf("Cannot obtain a lock on wallet directory %s. Another instance of bitcoin may be using it.\n", strPath);
|
LogPrintf("Cannot obtain a lock on wallet directory %s. Another instance of bitcoin may be using it.\n", strPath);
|
||||||
err = strprintf(_("Error initializing wallet database environment %s!"), Directory());
|
err = strprintf(_("Error initializing wallet database environment %s!"), fs::quoted(fs::PathToString(Directory())));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path pathLogDir = pathIn / "database";
|
fs::path pathLogDir = pathIn / "database";
|
||||||
TryCreateDirectories(pathLogDir);
|
TryCreateDirectories(pathLogDir);
|
||||||
fs::path pathErrorFile = pathIn / "db.log";
|
fs::path pathErrorFile = pathIn / "db.log";
|
||||||
LogPrintf("BerkeleyEnvironment::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());
|
LogPrintf("BerkeleyEnvironment::Open: LogDir=%s ErrorFile=%s\n", fs::PathToString(pathLogDir), fs::PathToString(pathErrorFile));
|
||||||
|
|
||||||
unsigned int nEnvFlags = 0;
|
unsigned int nEnvFlags = 0;
|
||||||
if (gArgs.GetBoolArg("-privdb", DEFAULT_WALLET_PRIVDB))
|
if (gArgs.GetBoolArg("-privdb", DEFAULT_WALLET_PRIVDB))
|
||||||
nEnvFlags |= DB_PRIVATE;
|
nEnvFlags |= DB_PRIVATE;
|
||||||
|
|
||||||
dbenv->set_lg_dir(pathLogDir.string().c_str());
|
dbenv->set_lg_dir(fs::PathToString(pathLogDir).c_str());
|
||||||
dbenv->set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet
|
dbenv->set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet
|
||||||
dbenv->set_lg_bsize(0x10000);
|
dbenv->set_lg_bsize(0x10000);
|
||||||
dbenv->set_lg_max(1048576);
|
dbenv->set_lg_max(1048576);
|
||||||
|
@ -173,7 +173,7 @@ bool BerkeleyEnvironment::Open(bilingual_str& err)
|
||||||
LogPrintf("BerkeleyEnvironment::Open: Error %d closing failed database environment: %s\n", ret2, DbEnv::strerror(ret2));
|
LogPrintf("BerkeleyEnvironment::Open: Error %d closing failed database environment: %s\n", ret2, DbEnv::strerror(ret2));
|
||||||
}
|
}
|
||||||
Reset();
|
Reset();
|
||||||
err = strprintf(_("Error initializing wallet database environment %s!"), Directory());
|
err = strprintf(_("Error initializing wallet database environment %s!"), fs::quoted(fs::PathToString(Directory())));
|
||||||
if (ret == DB_RUNRECOVERY) {
|
if (ret == DB_RUNRECOVERY) {
|
||||||
err += Untranslated(" ") + _("This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet");
|
err += Untranslated(" ") + _("This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet");
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ bool BerkeleyDatabase::Verify(bilingual_str& errorStr)
|
||||||
fs::path file_path = walletDir / strFile;
|
fs::path file_path = walletDir / strFile;
|
||||||
|
|
||||||
LogPrintf("Using BerkeleyDB version %s\n", BerkeleyDatabaseVersion());
|
LogPrintf("Using BerkeleyDB version %s\n", BerkeleyDatabaseVersion());
|
||||||
LogPrintf("Using wallet %s\n", file_path.string());
|
LogPrintf("Using wallet %s\n", fs::PathToString(file_path));
|
||||||
|
|
||||||
if (!env->Open(errorStr)) {
|
if (!env->Open(errorStr)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -274,7 +274,7 @@ bool BerkeleyDatabase::Verify(bilingual_str& errorStr)
|
||||||
Db db(env->dbenv.get(), 0);
|
Db db(env->dbenv.get(), 0);
|
||||||
int result = db.verify(strFile.c_str(), nullptr, nullptr, 0);
|
int result = db.verify(strFile.c_str(), nullptr, nullptr, 0);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
errorStr = strprintf(_("%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup."), file_path);
|
errorStr = strprintf(_("%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup."), fs::quoted(fs::PathToString(file_path)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,7 +566,7 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
|
||||||
dbenv->log_archive(&listp, DB_ARCH_REMOVE);
|
dbenv->log_archive(&listp, DB_ARCH_REMOVE);
|
||||||
Close();
|
Close();
|
||||||
if (!fMockDb) {
|
if (!fMockDb) {
|
||||||
fs::remove_all(fs::path(strPath) / "database");
|
fs::remove_all(fs::PathFromString(strPath) / "database");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -614,21 +614,21 @@ bool BerkeleyDatabase::Backup(const std::string& strDest) const
|
||||||
|
|
||||||
// Copy wallet file
|
// Copy wallet file
|
||||||
fs::path pathSrc = env->Directory() / strFile;
|
fs::path pathSrc = env->Directory() / strFile;
|
||||||
fs::path pathDest(strDest);
|
fs::path pathDest(fs::PathFromString(strDest));
|
||||||
if (fs::is_directory(pathDest))
|
if (fs::is_directory(pathDest))
|
||||||
pathDest /= strFile;
|
pathDest /= fs::PathFromString(strFile);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (fs::equivalent(pathSrc, pathDest)) {
|
if (fs::equivalent(pathSrc, pathDest)) {
|
||||||
LogPrintf("cannot backup to wallet source file %s\n", pathDest.string());
|
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_option::overwrite_if_exists);
|
||||||
LogPrintf("copied %s to %s\n", strFile, pathDest.string());
|
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) {
|
||||||
LogPrintf("error copying %s to %s - %s\n", strFile, pathDest.string(), fsbridge::get_filesystem_error_message(e));
|
LogPrintf("error copying %s to %s - %s\n", strFile, fs::PathToString(pathDest), fsbridge::get_filesystem_error_message(e));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -828,10 +828,10 @@ std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, con
|
||||||
std::unique_ptr<BerkeleyDatabase> db;
|
std::unique_ptr<BerkeleyDatabase> db;
|
||||||
{
|
{
|
||||||
LOCK(cs_db); // Lock env.m_databases until insert in BerkeleyDatabase constructor
|
LOCK(cs_db); // Lock env.m_databases until insert in BerkeleyDatabase constructor
|
||||||
std::string data_filename = data_file.filename().string();
|
std::string data_filename = fs::PathToString(data_file.filename());
|
||||||
std::shared_ptr<BerkeleyEnvironment> env = GetBerkeleyEnv(data_file.parent_path());
|
std::shared_ptr<BerkeleyEnvironment> env = GetBerkeleyEnv(data_file.parent_path());
|
||||||
if (env->m_databases.count(data_filename)) {
|
if (env->m_databases.count(data_filename)) {
|
||||||
error = Untranslated(strprintf("Refusing to load database. Data file '%s' is already loaded.", (env->Directory() / data_filename).string()));
|
error = Untranslated(strprintf("Refusing to load database. Data file '%s' is already loaded.", fs::PathToString(env->Directory() / data_filename)));
|
||||||
status = DatabaseStatus::FAILED_ALREADY_LOADED;
|
status = DatabaseStatus::FAILED_ALREADY_LOADED;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
|
|
||||||
bool IsMock() const { return fMockDb; }
|
bool IsMock() const { return fMockDb; }
|
||||||
bool IsInitialized() const { return fDbEnvInit; }
|
bool IsInitialized() const { return fDbEnvInit; }
|
||||||
fs::path Directory() const { return strPath; }
|
fs::path Directory() const { return fs::PathFromString(strPath); }
|
||||||
|
|
||||||
bool Open(bilingual_str& error);
|
bool Open(bilingual_str& error);
|
||||||
void Close();
|
void Close();
|
||||||
|
@ -141,7 +141,7 @@ public:
|
||||||
bool Verify(bilingual_str& error);
|
bool Verify(bilingual_str& error);
|
||||||
|
|
||||||
/** Return path to main database filename */
|
/** Return path to main database filename */
|
||||||
std::string Filename() override { return (env->Directory() / strFile).string(); }
|
std::string Filename() override { return fs::PathToString(env->Directory() / strFile); }
|
||||||
|
|
||||||
std::string Format() override { return "bdb"; }
|
std::string Format() override { return "bdb"; }
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
|
std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
|
||||||
{
|
{
|
||||||
const size_t offset = wallet_dir.string().size() + (wallet_dir == wallet_dir.root_name() ? 0 : 1);
|
const size_t offset = wallet_dir.native().size() + (wallet_dir == wallet_dir.root_name() ? 0 : 1);
|
||||||
std::vector<fs::path> paths;
|
std::vector<fs::path> paths;
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
|
||||||
if (ec) {
|
if (ec) {
|
||||||
if (fs::is_directory(*it)) {
|
if (fs::is_directory(*it)) {
|
||||||
it.no_push();
|
it.no_push();
|
||||||
LogPrintf("%s: %s %s -- skipping.\n", __func__, ec.message(), it->path().string());
|
LogPrintf("%s: %s %s -- skipping.\n", __func__, ec.message(), fs::PathToString(it->path()));
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string());
|
LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(it->path()));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,8 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
|
||||||
try {
|
try {
|
||||||
// Get wallet path relative to walletdir by removing walletdir from the wallet path.
|
// Get wallet path relative to walletdir by removing walletdir from the wallet path.
|
||||||
// This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
|
// This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
|
||||||
const fs::path path = it->path().string().substr(offset);
|
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::directory_file &&
|
||||||
(IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
|
(IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
|
||||||
|
@ -50,7 +51,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__, it->path().string(), e.what());
|
LogPrintf("%s: Error scanning %s: %s\n", __func__, fs::PathToString(it->path()), e.what());
|
||||||
it.no_push();
|
it.no_push();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +86,7 @@ bool IsBDBFile(const fs::path& path)
|
||||||
// This check also prevents opening lock files.
|
// This check also prevents opening lock files.
|
||||||
boost::system::error_code ec;
|
boost::system::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(), path.string());
|
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);
|
fsbridge::ifstream file(path, std::ios::binary);
|
||||||
|
@ -109,7 +110,7 @@ bool IsSQLiteFile(const fs::path& path)
|
||||||
// A SQLite Database file is at least 512 bytes.
|
// A SQLite Database file is at least 512 bytes.
|
||||||
boost::system::error_code ec;
|
boost::system::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(), path.string());
|
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);
|
fsbridge::ifstream file(path, std::ios::binary);
|
||||||
|
|
|
@ -19,16 +19,16 @@ bool DumpWallet(CWallet& wallet, bilingual_str& error)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path path = dump_filename;
|
fs::path path = fs::PathFromString(dump_filename);
|
||||||
path = fs::absolute(path);
|
path = fs::absolute(path);
|
||||||
if (fs::exists(path)) {
|
if (fs::exists(path)) {
|
||||||
error = strprintf(_("File %s already exists. If you are sure this is what you want, move it out of the way first."), path.string());
|
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;
|
fsbridge::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"), path.string());
|
error = strprintf(_("Unable to open %s for writing"), fs::PathToString(path));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,10 +114,10 @@ bool CreateFromDump(const std::string& name, const fs::path& wallet_path, biling
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path dump_path = dump_filename;
|
fs::path dump_path = fs::PathFromString(dump_filename);
|
||||||
dump_path = fs::absolute(dump_path);
|
dump_path = fs::absolute(dump_path);
|
||||||
if (!fs::exists(dump_path)) {
|
if (!fs::exists(dump_path)) {
|
||||||
error = strprintf(_("Dump file %s does not exist."), dump_path.string());
|
error = strprintf(_("Dump file %s does not exist."), fs::PathToString(dump_path));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fsbridge::ifstream dump_file(dump_path);
|
fsbridge::ifstream dump_file(dump_path);
|
||||||
|
|
|
@ -551,13 +551,13 @@ public:
|
||||||
}
|
}
|
||||||
std::string getWalletDir() override
|
std::string getWalletDir() override
|
||||||
{
|
{
|
||||||
return GetWalletDir().string();
|
return fs::PathToString(GetWalletDir());
|
||||||
}
|
}
|
||||||
std::vector<std::string> listWalletDir() override
|
std::vector<std::string> listWalletDir() override
|
||||||
{
|
{
|
||||||
std::vector<std::string> paths;
|
std::vector<std::string> paths;
|
||||||
for (auto& path : ListDatabases(GetWalletDir())) {
|
for (auto& path : ListDatabases(GetWalletDir())) {
|
||||||
paths.push_back(path.string());
|
paths.push_back(fs::PathToString(path));
|
||||||
}
|
}
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,25 +25,25 @@ bool VerifyWallets(WalletContext& context)
|
||||||
ArgsManager& args = *Assert(context.args);
|
ArgsManager& args = *Assert(context.args);
|
||||||
|
|
||||||
if (args.IsArgSet("-walletdir")) {
|
if (args.IsArgSet("-walletdir")) {
|
||||||
fs::path wallet_dir = args.GetArg("-walletdir", "");
|
fs::path wallet_dir = fs::PathFromString(args.GetArg("-walletdir", ""));
|
||||||
boost::system::error_code error;
|
boost::system::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);
|
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"), wallet_dir.string()));
|
chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), fs::PathToString(wallet_dir)));
|
||||||
return false;
|
return false;
|
||||||
} else if (!fs::is_directory(wallet_dir)) {
|
} else if (!fs::is_directory(wallet_dir)) {
|
||||||
chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
|
chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), fs::PathToString(wallet_dir)));
|
||||||
return false;
|
return false;
|
||||||
// The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
|
// The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
|
||||||
} else if (!wallet_dir.is_absolute()) {
|
} else if (!wallet_dir.is_absolute()) {
|
||||||
chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
|
chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), fs::PathToString(wallet_dir)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
args.ForceSetArg("-walletdir", canonical_wallet_dir.string());
|
args.ForceSetArg("-walletdir", fs::PathToString(canonical_wallet_dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
|
LogPrintf("Using wallet directory %s\n", fs::PathToString(GetWalletDir()));
|
||||||
|
|
||||||
chain.initMessage(_("Verifying wallet(s)…").translated);
|
chain.initMessage(_("Verifying wallet(s)…").translated);
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ bool VerifyWallets(WalletContext& context)
|
||||||
|
|
||||||
for (const auto& wallet : chain.getSettingsList("wallet")) {
|
for (const auto& wallet : chain.getSettingsList("wallet")) {
|
||||||
const auto& wallet_file = wallet.get_str();
|
const auto& wallet_file = wallet.get_str();
|
||||||
const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), wallet_file);
|
const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(wallet_file));
|
||||||
|
|
||||||
if (!wallet_paths.insert(path).second) {
|
if (!wallet_paths.insert(path).second) {
|
||||||
chain.initWarning(strprintf(_("Ignoring duplicate -wallet %s."), wallet_file));
|
chain.initWarning(strprintf(_("Ignoring duplicate -wallet %s."), wallet_file));
|
||||||
|
@ -102,7 +102,7 @@ bool LoadWallets(WalletContext& context)
|
||||||
std::set<fs::path> wallet_paths;
|
std::set<fs::path> wallet_paths;
|
||||||
for (const auto& wallet : chain.getSettingsList("wallet")) {
|
for (const auto& wallet : chain.getSettingsList("wallet")) {
|
||||||
const auto& name = wallet.get_str();
|
const auto& name = wallet.get_str();
|
||||||
if (!wallet_paths.insert(name).second) {
|
if (!wallet_paths.insert(fs::PathFromString(name)).second) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DatabaseOptions options;
|
DatabaseOptions options;
|
||||||
|
|
|
@ -550,7 +550,7 @@ RPCHelpMan importwallet()
|
||||||
EnsureWalletIsUnlocked(*pwallet);
|
EnsureWalletIsUnlocked(*pwallet);
|
||||||
|
|
||||||
fsbridge::ifstream file;
|
fsbridge::ifstream file;
|
||||||
file.open(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");
|
||||||
}
|
}
|
||||||
|
@ -745,7 +745,7 @@ RPCHelpMan dumpwallet()
|
||||||
|
|
||||||
EnsureWalletIsUnlocked(wallet);
|
EnsureWalletIsUnlocked(wallet);
|
||||||
|
|
||||||
fs::path filepath = request.params[0].get_str();
|
fs::path filepath = fs::u8path(request.params[0].get_str());
|
||||||
filepath = fs::absolute(filepath);
|
filepath = fs::absolute(filepath);
|
||||||
|
|
||||||
/* Prevent arbitrary files from being overwritten. There have been reports
|
/* Prevent arbitrary files from being overwritten. There have been reports
|
||||||
|
@ -754,7 +754,7 @@ RPCHelpMan dumpwallet()
|
||||||
* It may also avoid other security issues.
|
* It may also avoid other security issues.
|
||||||
*/
|
*/
|
||||||
if (fs::exists(filepath)) {
|
if (fs::exists(filepath)) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " 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;
|
fsbridge::ofstream file;
|
||||||
|
@ -844,7 +844,7 @@ RPCHelpMan dumpwallet()
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
UniValue reply(UniValue::VOBJ);
|
UniValue reply(UniValue::VOBJ);
|
||||||
reply.pushKV("filename", filepath.string());
|
reply.pushKV("filename", filepath.u8string());
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
},
|
},
|
||||||
|
|
|
@ -2582,7 +2582,7 @@ static RPCHelpMan listwalletdir()
|
||||||
UniValue wallets(UniValue::VARR);
|
UniValue wallets(UniValue::VARR);
|
||||||
for (const auto& path : ListDatabases(GetWalletDir())) {
|
for (const auto& path : ListDatabases(GetWalletDir())) {
|
||||||
UniValue wallet(UniValue::VOBJ);
|
UniValue wallet(UniValue::VOBJ);
|
||||||
wallet.pushKV("name", path.string());
|
wallet.pushKV("name", path.u8string());
|
||||||
wallets.push_back(wallet);
|
wallets.push_back(wallet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2883,7 +2883,7 @@ static RPCHelpMan restorewallet()
|
||||||
|
|
||||||
WalletContext& context = EnsureWalletContext(request.context);
|
WalletContext& context = EnsureWalletContext(request.context);
|
||||||
|
|
||||||
std::string backup_file = request.params[1].get_str();
|
auto backup_file = fs::u8path(request.params[1].get_str());
|
||||||
|
|
||||||
if (!fs::exists(backup_file)) {
|
if (!fs::exists(backup_file)) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Backup file does not exist");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Backup file does not exist");
|
||||||
|
@ -2891,14 +2891,14 @@ static RPCHelpMan restorewallet()
|
||||||
|
|
||||||
std::string wallet_name = request.params[0].get_str();
|
std::string wallet_name = request.params[0].get_str();
|
||||||
|
|
||||||
const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), wallet_name);
|
const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name));
|
||||||
|
|
||||||
if (fs::exists(wallet_path)) {
|
if (fs::exists(wallet_path)) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Wallet name already exists.");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Wallet name already exists.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryCreateDirectories(wallet_path)) {
|
if (!TryCreateDirectories(wallet_path)) {
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Failed to create database path '%s'. Database already exists.", wallet_path.string()));
|
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Failed to create database path '%s'. Database already exists.", wallet_path.u8string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto wallet_file = wallet_path / "wallet.dat";
|
auto wallet_file = wallet_path / "wallet.dat";
|
||||||
|
|
|
@ -67,7 +67,7 @@ static void SetPragma(sqlite3* db, const std::string& key, const std::string& va
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, bool mock)
|
SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, bool mock)
|
||||||
: WalletDatabase(), m_mock(mock), m_dir_path(dir_path.string()), m_file_path(file_path.string())
|
: WalletDatabase(), m_mock(mock), m_dir_path(fs::PathToString(dir_path)), m_file_path(fs::PathToString(file_path))
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LOCK(g_sqlite_mutex);
|
LOCK(g_sqlite_mutex);
|
||||||
|
@ -206,7 +206,7 @@ void SQLiteDatabase::Open()
|
||||||
|
|
||||||
if (m_db == nullptr) {
|
if (m_db == nullptr) {
|
||||||
if (!m_mock) {
|
if (!m_mock) {
|
||||||
TryCreateDirectories(m_dir_path);
|
TryCreateDirectories(fs::PathFromString(m_dir_path));
|
||||||
}
|
}
|
||||||
int ret = sqlite3_open_v2(m_file_path.c_str(), &m_db, flags, nullptr);
|
int ret = sqlite3_open_v2(m_file_path.c_str(), &m_db, flags, nullptr);
|
||||||
if (ret != SQLITE_OK) {
|
if (ret != SQLITE_OK) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ BOOST_FIXTURE_TEST_SUITE(db_tests, BasicTestingSetup)
|
||||||
static std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& path, std::string& database_filename)
|
static std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& path, std::string& database_filename)
|
||||||
{
|
{
|
||||||
fs::path data_file = BDBDataFile(path);
|
fs::path data_file = BDBDataFile(path);
|
||||||
database_filename = data_file.filename().string();
|
database_filename = fs::PathToString(data_file.filename());
|
||||||
return GetBerkeleyEnv(data_file.parent_path());
|
return GetBerkeleyEnv(data_file.parent_path());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,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;
|
||||||
#if BOOST_VERSION >= 107700
|
fs::ofstream f(file_path);
|
||||||
std::ofstream f(BOOST_FILESYSTEM_C_STR(file_path));
|
|
||||||
#else
|
|
||||||
std::ofstream f(file_path.BOOST_FILESYSTEM_C_STR);
|
|
||||||
#endif // BOOST_VERSION >= 107700
|
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
|
|
@ -32,11 +32,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"]);
|
||||||
#if BOOST_VERSION >= 107700
|
fs::ofstream f(m_walletdir_path_cases["file"]);
|
||||||
std::ofstream f(BOOST_FILESYSTEM_C_STR(m_walletdir_path_cases["file"]));
|
|
||||||
#else
|
|
||||||
std::ofstream f(m_walletdir_path_cases["file"].BOOST_FILESYSTEM_C_STR);
|
|
||||||
#endif // BOOST_VERSION >= 107700
|
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,5 +46,5 @@ InitWalletDirTestingSetup::~InitWalletDirTestingSetup()
|
||||||
|
|
||||||
void InitWalletDirTestingSetup::SetWalletDir(const fs::path& walletdir_path)
|
void InitWalletDirTestingSetup::SetWalletDir(const fs::path& walletdir_path)
|
||||||
{
|
{
|
||||||
gArgs.ForceSetArg("-walletdir", walletdir_path.string());
|
gArgs.ForceSetArg("-walletdir", fs::PathToString(walletdir_path));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
|
||||||
SetWalletDir(m_walletdir_path_cases["default"]);
|
SetWalletDir(m_walletdir_path_cases["default"]);
|
||||||
bool result = m_wallet_client->verify();
|
bool result = m_wallet_client->verify();
|
||||||
BOOST_CHECK(result == true);
|
BOOST_CHECK(result == true);
|
||||||
fs::path walletdir = gArgs.GetArg("-walletdir", "");
|
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
|
||||||
SetWalletDir(m_walletdir_path_cases["custom"]);
|
SetWalletDir(m_walletdir_path_cases["custom"]);
|
||||||
bool result = m_wallet_client->verify();
|
bool result = m_wallet_client->verify();
|
||||||
BOOST_CHECK(result == true);
|
BOOST_CHECK(result == true);
|
||||||
fs::path walletdir = gArgs.GetArg("-walletdir", "");
|
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||||
fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]);
|
fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]);
|
||||||
BOOST_CHECK_EQUAL(walletdir, expected_path);
|
BOOST_CHECK_EQUAL(walletdir, expected_path);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
|
||||||
SetWalletDir(m_walletdir_path_cases["trailing"]);
|
SetWalletDir(m_walletdir_path_cases["trailing"]);
|
||||||
bool result = m_wallet_client->verify();
|
bool result = m_wallet_client->verify();
|
||||||
BOOST_CHECK(result == true);
|
BOOST_CHECK(result == true);
|
||||||
fs::path walletdir = gArgs.GetArg("-walletdir", "");
|
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
|
||||||
SetWalletDir(m_walletdir_path_cases["trailing2"]);
|
SetWalletDir(m_walletdir_path_cases["trailing2"]);
|
||||||
bool result = m_wallet_client->verify();
|
bool result = m_wallet_client->verify();
|
||||||
BOOST_CHECK(result == true);
|
BOOST_CHECK(result == true);
|
||||||
fs::path walletdir = gArgs.GetArg("-walletdir", "");
|
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,7 +258,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||||
SetMockTime(KEY_TIME);
|
SetMockTime(KEY_TIME);
|
||||||
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||||
|
|
||||||
std::string backup_file = (gArgs.GetDataDirNet() / "wallet.backup").string();
|
std::string backup_file = fs::PathToString(gArgs.GetDataDirNet() / "wallet.backup");
|
||||||
|
|
||||||
// Import key into wallet and call dumpwallet to create backup file.
|
// Import key into wallet and call dumpwallet to create backup file.
|
||||||
{
|
{
|
||||||
|
|
|
@ -2515,16 +2515,16 @@ std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, cons
|
||||||
// 2. Path to an existing directory.
|
// 2. Path to an existing directory.
|
||||||
// 3. Path to a symlink to a directory.
|
// 3. Path to a symlink to a directory.
|
||||||
// 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(), 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_not_found || path_type == fs::directory_file ||
|
||||||
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
|
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
|
||||||
(path_type == fs::regular_file && fs::path(name).filename() == name))) {
|
(path_type == fs::regular_file && 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, "
|
||||||
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
|
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
|
||||||
name, GetWalletDir()));
|
name, fs::quoted(fs::PathToString(GetWalletDir()))));
|
||||||
status = DatabaseStatus::FAILED_BAD_PATH;
|
status = DatabaseStatus::FAILED_BAD_PATH;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1106,7 +1106,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
||||||
try {
|
try {
|
||||||
exists = fs::symlink_status(path).type() != fs::file_not_found;
|
exists = fs::symlink_status(path).type() != fs::file_not_found;
|
||||||
} catch (const fs::filesystem_error& e) {
|
} catch (const fs::filesystem_error& e) {
|
||||||
error = Untranslated(strprintf("Failed to access database path '%s': %s", path.string(), 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;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1118,33 +1118,33 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
||||||
}
|
}
|
||||||
if (IsSQLiteFile(SQLiteDataFile(path))) {
|
if (IsSQLiteFile(SQLiteDataFile(path))) {
|
||||||
if (format) {
|
if (format) {
|
||||||
error = Untranslated(strprintf("Failed to load database path '%s'. Data is in ambiguous format.", path.string()));
|
error = Untranslated(strprintf("Failed to load database path '%s'. Data is in ambiguous format.", fs::PathToString(path)));
|
||||||
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
format = DatabaseFormat::SQLITE;
|
format = DatabaseFormat::SQLITE;
|
||||||
}
|
}
|
||||||
} else if (options.require_existing) {
|
} else if (options.require_existing) {
|
||||||
error = Untranslated(strprintf("Failed to load database path '%s'. Path does not exist.", path.string()));
|
error = Untranslated(strprintf("Failed to load database path '%s'. Path does not exist.", fs::PathToString(path)));
|
||||||
status = DatabaseStatus::FAILED_NOT_FOUND;
|
status = DatabaseStatus::FAILED_NOT_FOUND;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!format && options.require_existing) {
|
if (!format && options.require_existing) {
|
||||||
error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in recognized format.", path.string()));
|
error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in recognized format.", fs::PathToString(path)));
|
||||||
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format && options.require_create) {
|
if (format && options.require_create) {
|
||||||
error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", path.string()));
|
error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(path)));
|
||||||
status = DatabaseStatus::FAILED_ALREADY_EXISTS;
|
status = DatabaseStatus::FAILED_ALREADY_EXISTS;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A db already exists so format is set, but options also specifies the format, so make sure they agree
|
// A db already exists so format is set, but options also specifies the format, so make sure they agree
|
||||||
if (format && options.require_format && format != options.require_format) {
|
if (format && options.require_format && format != options.require_format) {
|
||||||
error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in required format.", path.string()));
|
error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in required format.", fs::PathToString(path)));
|
||||||
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1166,7 +1166,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
||||||
#ifdef USE_SQLITE
|
#ifdef USE_SQLITE
|
||||||
return MakeSQLiteDatabase(path, options, status, error);
|
return MakeSQLiteDatabase(path, options, status, error);
|
||||||
#endif
|
#endif
|
||||||
error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support SQLite database format.", path.string()));
|
error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support SQLite database format.", fs::PathToString(path)));
|
||||||
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1174,7 +1174,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
|
||||||
#ifdef USE_BDB
|
#ifdef USE_BDB
|
||||||
return MakeBerkeleyDatabase(path, options, status, error);
|
return MakeBerkeleyDatabase(path, options, status, error);
|
||||||
#endif
|
#endif
|
||||||
error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support Berkeley DB database format.", path.string()));
|
error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support Berkeley DB database format.", fs::PathToString(path)));
|
||||||
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
status = DatabaseStatus::FAILED_BAD_FORMAT;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const std::string name = args.GetArg("-wallet", "");
|
const std::string name = args.GetArg("-wallet", "");
|
||||||
const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), name);
|
const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name));
|
||||||
|
|
||||||
if (command == "create") {
|
if (command == "create") {
|
||||||
DatabaseOptions options;
|
DatabaseOptions options;
|
||||||
|
|
|
@ -12,7 +12,7 @@ fs::path GetWalletDir()
|
||||||
fs::path path;
|
fs::path path;
|
||||||
|
|
||||||
if (gArgs.IsArgSet("-walletdir")) {
|
if (gArgs.IsArgSet("-walletdir")) {
|
||||||
path = gArgs.GetArg("-walletdir", "");
|
path = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||||
if (!fs::is_directory(path)) {
|
if (!fs::is_directory(path)) {
|
||||||
// If the path specified doesn't exist, we return the deliberately
|
// If the path specified doesn't exist, we return the deliberately
|
||||||
// invalid empty string.
|
// invalid empty string.
|
||||||
|
|
Loading…
Add table
Reference in a new issue