refactor: Block unsafe fs::path std::string conversion calls

There is no change in behavior. This just helps prepare for the
transition from boost::filesystem to std::filesystem by avoiding calls
to methods which will be unsafe after the transaction to std::filesystem
to due lack of a boost::filesystem::path::imbue equivalent and inability
to set a predictable locale.

Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>
Co-authored-by: Kiminuo <kiminuo@protonmail.com>
Co-authored-by: MarcoFalke <falke.marco@gmail.com>
This commit is contained in:
Russell Yanofsky 2021-09-10 00:17:20 -04:00
parent b39a477ec6
commit 6544ea5035
43 changed files with 244 additions and 196 deletions

View File

@ -58,7 +58,7 @@ bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data
if (fileout.IsNull()) {
fileout.fclose();
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
@ -70,7 +70,7 @@ bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data
if (!FileCommit(fileout.Get())) {
fileout.fclose();
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();
@ -122,8 +122,8 @@ void DeserializeFileDB(const fs::path& path, Data& data, int version)
} // namespace
CBanDB::CBanDB(fs::path ban_list_path)
: m_banlist_dat(ban_list_path.string() + ".dat"),
m_banlist_json(ban_list_path.string() + ".json")
: m_banlist_dat(ban_list_path + ".dat"),
m_banlist_json(ban_list_path + ".json")
{
}
@ -143,7 +143,7 @@ bool CBanDB::Write(const banmap_t& banSet)
bool CBanDB::Read(banmap_t& banSet)
{
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 (!fs::exists(m_banlist_json)) {
@ -155,7 +155,7 @@ bool CBanDB::Read(banmap_t& banSet)
if (!util::ReadSettings(m_banlist_json, settings, 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;
}
@ -163,7 +163,7 @@ bool CBanDB::Read(banmap_t& banSet)
try {
BanMapFromJson(settings[JSON_KEY], banSet);
} 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;
}
@ -194,12 +194,12 @@ std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const A
} catch (const DbNotFoundError&) {
// Addrman can be in an inconsistent state after failure, reset it
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);
} catch (const std::exception& e) {
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."),
e.what(), PACKAGE_BUGREPORT, path_addr);
e.what(), PACKAGE_BUGREPORT, fs::quoted(fs::PathToString(path_addr)));
}
return std::nullopt;
}
@ -215,7 +215,7 @@ std::vector<CAddress> ReadAnchors(const fs::path& anchors_db_path)
std::vector<CAddress> anchors;
try {
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&) {
anchors.clear();
}

View File

@ -786,7 +786,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
if (failedToGetAuthCookie) {
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)",
GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string()));
fs::PathToString(GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)))));
} else {
throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
}

View File

@ -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)
: m_name{path.stem().string()}
: m_name{fs::PathToString(path.stem())}
{
penv = nullptr;
readoptions.verify_checksums = true;
@ -129,21 +129,21 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo
options.env = penv;
} else {
if (fWipe) {
LogPrintf("Wiping LevelDB in %s\n", path.string());
leveldb::Status result = leveldb::DestroyDB(path.string(), options);
LogPrintf("Wiping LevelDB in %s\n", fs::PathToString(path));
leveldb::Status result = leveldb::DestroyDB(fs::PathToString(path), options);
dbwrapper_private::HandleError(result);
}
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);
LogPrintf("Opened LevelDB successfully\n");
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);
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.
@ -160,10 +160,10 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo
Write(OBFUSCATE_KEY_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()

View File

@ -41,11 +41,11 @@ FILE* FlatFileSeq::Open(const FlatFilePos& pos, bool read_only)
if (!file && !read_only)
file = fsbridge::fopen(path, "wb+");
if (!file) {
LogPrintf("Unable to open file %s\n", path.string());
LogPrintf("Unable to open file %s\n", fs::PathToString(path));
return nullptr;
}
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);
return nullptr;
}

View File

@ -24,7 +24,7 @@ namespace fsbridge {
FILE *fopen(const fs::path& p, const char *mode)
{
#ifndef WIN32
return ::fopen(p.string().c_str(), mode);
return ::fopen(p.c_str(), mode);
#else
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());
@ -46,7 +46,7 @@ static std::string GetErrorReason()
FileLock::FileLock(const fs::path& file)
{
fd = open(file.string().c_str(), O_RDWR);
fd = open(file.c_str(), O_RDWR);
if (fd == -1) {
reason = GetErrorReason();
}
@ -249,9 +249,9 @@ void ofstream::close()
#else // __GLIBCXX__
#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
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
"Warning: This build is using boost::filesystem ofstream and ifstream "
"implementations which will fail to open paths containing multibyte "

View File

@ -13,6 +13,7 @@
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <tinyformat.h>
/** Filesystem operations and types */
namespace fs {
@ -23,8 +24,8 @@ 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. In the next git commit, it also blocks calls
* to the fs::path(std::string) implicit constructor and the fs::path::string()
* 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).
@ -33,7 +34,26 @@ 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(); }
@ -45,6 +65,33 @@ 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
@ -179,4 +226,11 @@ namespace fsbridge {
#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

View File

@ -328,7 +328,7 @@ void Session::GenerateAndSavePrivateKey(const Sock& sock)
if (!WriteBinaryFile(m_private_key_file,
std::string(m_private_key.begin(), m_private_key.end()))) {
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))));
}
}

View File

@ -113,7 +113,7 @@ static const char* BITCOIN_PID_FILENAME = "bitcoind.pid";
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)
@ -127,7 +127,7 @@ static fs::path GetPidFile(const ArgsManager& args)
#endif
return true;
} 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.
fs::path datadir = gArgs.GetDataDirNet();
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)) {
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;
}
@ -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);
// 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 */
"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 "
"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();
@ -1215,20 +1215,20 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// Read asmap file if configured
std::vector<bool> 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()) {
asmap_path = DEFAULT_ASMAP_FILENAME;
asmap_path = fs::PathFromString(DEFAULT_ASMAP_FILENAME);
}
if (!asmap_path.is_absolute()) {
asmap_path = gArgs.GetDataDirNet() / 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;
}
asmap = DecodeAsmap(asmap_path);
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;
}
const uint256 asmap_version = SerializeHash(asmap);
@ -1653,11 +1653,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// ********************************************************* Step 11: import blocks
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;
}
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;
}
@ -1685,7 +1685,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
std::vector<fs::path> vImportFiles;
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] {

View File

@ -81,7 +81,7 @@ void AddLoggingArgs(ArgsManager& argsman)
void SetLoggingOptions(const ArgsManager& args)
{
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_log_timestamps = args.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
LogInstance().m_log_time_micros = args.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
@ -128,24 +128,24 @@ bool StartLogging(const ArgsManager& args)
}
if (!LogInstance().StartLogging()) {
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)
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", gArgs.GetDataDirNet().string());
LogPrintf("Default data directory %s\n", fs::PathToString(GetDefaultDataDir()));
LogPrintf("Using data directory %s\n", fs::PathToString(gArgs.GetDataDirNet()));
// Only log conf file usage message if conf file actually exists.
fs::path config_file_path = GetConfigFile(args.GetArg("-conf", BITCOIN_CONF_FILENAME));
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")) {
// 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 {
// 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

View File

@ -30,8 +30,8 @@ public:
return mp::SpawnProcess(pid, [&](int fd) {
fs::path path = argv0_path;
path.remove_filename();
path.append(new_exe_name);
return std::vector<std::string>{path.string(), "-ipcfd", strprintf("%i", fd)};
path /= fs::PathFromString(new_exe_name);
return std::vector<std::string>{fs::PathToString(path), "-ipcfd", strprintf("%i", fd)};
});
}
int waitSpawned(int pid) override { return mp::WaitProcess(pid); }

View File

@ -68,13 +68,14 @@ void CleanupBlockRevFiles()
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
fs::path blocksdir = gArgs.GetBlocksDirPath();
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) &&
it->path().filename().string().length() == 12 &&
it->path().filename().string().substr(8,4) == ".dat")
path.length() == 12 &&
path.substr(8,4) == ".dat")
{
if (it->path().filename().string().substr(0, 3) == "blk") {
mapBlockFiles[it->path().filename().string().substr(3, 5)] = it->path();
} else if (it->path().filename().string().substr(0, 3) == "rev") {
if (path.substr(0, 3) == "blk") {
mapBlockFiles[path.substr(3, 5)] = it->path();
} else if (path.substr(0, 3) == "rev") {
remove(it->path());
}
}
@ -527,14 +528,14 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
for (const fs::path& path : vImportFiles) {
FILE* file = fsbridge::fopen(path, "rb");
if (file) {
LogPrintf("Importing blocks file %s...\n", path.string());
LogPrintf("Importing blocks file %s...\n", fs::PathToString(path));
chainman.ActiveChainstate().LoadExternalBlockFile(file);
if (ShutdownRequested()) {
LogPrintf("Shutdown requested. Exit %s\n", __func__);
return;
}
} else {
LogPrintf("Warning: Could not open blocks file %s\n", path.string());
LogPrintf("Warning: Could not open blocks file %s\n", fs::PathToString(path));
}
}

View File

@ -527,7 +527,7 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
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;
CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
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));
}
}

View File

@ -647,12 +647,12 @@ void setClipboard(const QString& str)
fs::path qstringToBoostPath(const QString &path)
{
return fs::path(path.toStdString());
return fs::u8path(path.toStdString());
}
QString boostPathToQString(const fs::path &path)
{
return QString::fromStdString(path.string());
return QString::fromStdString(path.u8string());
}
QString NetworkToQString(Network net)

View File

@ -263,7 +263,7 @@ bool Intro::showIfNeeded(bool& did_show_intro, int64_t& prune_MiB)
* (to be consistent with bitcoind behavior)
*/
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;
}

View File

@ -2537,15 +2537,15 @@ static RPCHelpMan dumptxoutset()
},
[&](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
// 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)) {
throw JSONRPCError(
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");
}
@ -2555,7 +2555,7 @@ static RPCHelpMan dumptxoutset()
UniValue result = CreateUTXOSnapshot(node, node.chainman->ActiveChainstate(), afile);
fs::rename(temppath, path);
result.pushKV("path", path.string());
result.pushKV("path", path.u8string());
return result;
},
};

View File

@ -70,7 +70,7 @@ static fs::path GetAuthCookieFile(bool temp=false)
if (temp) {
arg += ".tmp";
}
return AbsPathForConfigVal(fs::path(arg));
return AbsPathForConfigVal(fs::PathFromString(arg));
}
bool GenerateAuthCookie(std::string *cookie_out)
@ -87,7 +87,7 @@ bool GenerateAuthCookie(std::string *cookie_out)
fs::path filepath_tmp = GetAuthCookieFile(true);
file.open(filepath_tmp);
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;
}
file << cookie;
@ -95,10 +95,10 @@ bool GenerateAuthCookie(std::string *cookie_out)
fs::path filepath = GetAuthCookieFile(false);
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;
}
LogPrintf("Generated RPC authentication cookie %s\n", filepath.string());
LogPrintf("Generated RPC authentication cookie %s\n", fs::PathToString(filepath));
if (cookie_out)
*cookie_out = cookie;

View File

@ -239,7 +239,7 @@ static RPCHelpMan getrpcinfo()
UniValue result(UniValue::VOBJ);
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);
result.pushKV("logpath", log_path);

View File

@ -48,7 +48,7 @@ FUZZ_TARGET_INIT(banman, initialize_banman)
const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()};
bool force_read_and_write_to_err{false};
if (start_with_corrupted_banlist) {
assert(WriteBinaryFile(banlist_file.string() + ".json",
assert(WriteBinaryFile(banlist_file + ".json",
fuzzed_data_provider.ConsumeRandomLengthString()));
} else {
force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool();
@ -111,5 +111,5 @@ FUZZ_TARGET_INIT(banman, initialize_banman)
assert(banmap == banmap_read);
}
}
fs::remove(banlist_file.string() + ".json");
fs::remove(fs::PathToString(banlist_file + ".json"));
}

View File

@ -80,19 +80,19 @@ BOOST_AUTO_TEST_CASE(ReadWrite)
"dupe": "dupe"
})");
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());
// Check non-kv json files not allowed
WriteText(path, R"("non-kv")");
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());
// Check invalid json not allowed
WriteText(path, R"(invalid json)");
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());
}

View File

@ -36,7 +36,7 @@ CreateAndActivateUTXOSnapshot(NodeContext& node, const fs::path root, F malleati
UniValue result = CreateUTXOSnapshot(node, node.chainman->ActiveChainstate(), auto_outfile);
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.
//

View File

@ -91,8 +91,8 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
extra_args);
util::ThreadRename("test");
fs::create_directories(m_path_root);
m_args.ForceSetArg("-datadir", m_path_root.string());
gArgs.ForceSetArg("-datadir", m_path_root.string());
m_args.ForceSetArg("-datadir", fs::PathToString(m_path_root));
gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root));
gArgs.ClearPathCache();
{
SetupServerArgs(*m_node.args);

View File

@ -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
ArgsManager args;
args.ForceSetArg("-datadir", m_path_root.string());
args.ForceSetArg("-datadir", fs::PathToString(m_path_root));
const fs::path dd_norm = args.GetDataDirBase();
args.ForceSetArg("-datadir", dd_norm.string() + "/");
args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/");
args.ClearPathCache();
BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
args.ForceSetArg("-datadir", dd_norm.string() + "/.");
args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/.");
args.ClearPathCache();
BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
args.ForceSetArg("-datadir", dd_norm.string() + "/./");
args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/./");
args.ClearPathCache();
BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
args.ForceSetArg("-datadir", dd_norm.string() + "/.//");
args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/.//");
args.ClearPathCache();
BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
}
@ -1181,13 +1181,13 @@ BOOST_AUTO_TEST_CASE(util_ReadWriteSettings)
{
// Test writing setting.
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.WriteSettingsFile();
// Test reading setting.
TestArgsManager args2;
args2.ForceSetArg("-datadir", m_path_root.string());
args2.ForceSetArg("-datadir", fs::PathToString(m_path_root));
args2.ReadSettingsFile();
args2.LockSettings([&](util::Settings& settings) { BOOST_CHECK_EQUAL(settings.rw_settings["name"].get_str(), "value"); });

View File

@ -318,7 +318,7 @@ TorController::TorController(struct event_base* _base, const std::string& tor_co
// Read service private key if cached
std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
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;
}
}
@ -356,9 +356,9 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe
service = LookupNumeric(std::string(service_id+".onion"), Params().GetDefaultPort());
LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString());
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 {
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);
// ... onion requested - keep connection open
@ -508,7 +508,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro
} else if (methods.count("SAFECOOKIE")) {
// 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);
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) {
// _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());

View File

@ -201,7 +201,7 @@ std::vector<bool> DecodeAsmap(fs::path path)
}
fseek(filestr, 0, SEEK_END);
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);
uint8_t cur_byte;
for (int i = 0; i < length; ++i) {
@ -211,7 +211,7 @@ std::vector<bool> DecodeAsmap(fs::path path)
}
}
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 bits;

View File

@ -66,24 +66,24 @@ bool ReadSettings(const fs::path& path, std::map<std::string, SettingsValue>& va
fsbridge::ifstream file;
file.open(path);
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;
}
SettingsValue in;
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;
}
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;
}
file.close(); // Done with file descriptor. Release while copying data.
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;
}
@ -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) {
auto inserted = values.emplace(in_keys[i], in_values[i]);
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();
@ -109,7 +109,7 @@ bool WriteSettings(const fs::path& path,
fsbridge::ofstream file;
file.open(path);
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;
}
file << out.write(/* prettyIndent= */ 1, /* indentLevel= */ 4) << std::endl;

View File

@ -98,7 +98,7 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b
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 (dir_locks.count(pathLockFile.string())) {
if (dir_locks.count(fs::PathToString(pathLockFile))) {
return true;
}
@ -107,11 +107,11 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b
if (file) fclose(file);
auto lock = std::make_unique<fsbridge::FileLock>(pathLockFile);
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) {
// 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;
}
@ -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)
{
LOCK(cs_dir_locks);
dir_locks.erase((directory / lockfile_name).string());
dir_locks.erase(fs::PathToString(directory / lockfile_name));
}
void ReleaseDirectoryLocks()
@ -242,7 +242,7 @@ namespace {
fs::path StripRedundantLastElementsOfPath(const fs::path& path)
{
auto result = path;
while (result.filename().string() == ".") {
while (fs::PathToString(result.filename()) == ".") {
result = result.parent_path();
}
@ -402,7 +402,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
if (!path.empty()) return path;
if (IsArgSet("-blocksdir")) {
path = fs::system_complete(GetArg("-blocksdir", ""));
path = fs::system_complete(fs::PathFromString(GetArg("-blocksdir", "")));
if (!fs::is_directory(path)) {
path = "";
return path;
@ -411,7 +411,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
path = GetDataDirBase();
}
path /= BaseParams().DataDir();
path /= fs::PathFromString(BaseParams().DataDir());
path /= "blocks";
fs::create_directories(path);
path = StripRedundantLastElementsOfPath(path);
@ -429,7 +429,7 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
std::string datadir = GetArg("-datadir", "");
if (!datadir.empty()) {
path = fs::system_complete(datadir);
path = fs::system_complete(fs::PathFromString(datadir));
if (!fs::is_directory(path)) {
path = "";
return path;
@ -438,7 +438,7 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
path = GetDefaultDataDir();
}
if (net_specific)
path /= BaseParams().DataDir();
path /= fs::PathFromString(BaseParams().DataDir());
if (fs::create_directories(path)) {
// This is the first run, create wallets subdirectory too
@ -517,7 +517,7 @@ bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp) const
}
if (filepath) {
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;
}
@ -572,7 +572,7 @@ bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors) const
return false;
}
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 true;
@ -809,12 +809,12 @@ fs::path GetDefaultDataDir()
bool CheckDataDirOption()
{
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)
{
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)
@ -1065,7 +1065,7 @@ bool RenameOver(fs::path src, fs::path dest)
return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
MOVEFILE_REPLACE_EXISTING) != 0;
#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);
#endif /* WIN32 */
}

View File

@ -61,9 +61,9 @@ bool WalletDatabaseFileId::operator==(const WalletDatabaseFileId& rhs) const
std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory)
{
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) {
auto env = std::make_shared<BerkeleyEnvironment>(env_directory.string());
auto env = std::make_shared<BerkeleyEnvironment>(env_directory);
inserted.first->second = env;
return env;
}
@ -101,7 +101,7 @@ void BerkeleyEnvironment::Close()
if (error_file) fclose(error_file);
UnlockDirectory(strPath, ".walletlock");
UnlockDirectory(fs::PathFromString(strPath), ".walletlock");
}
void BerkeleyEnvironment::Reset()
@ -111,7 +111,7 @@ void BerkeleyEnvironment::Reset()
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();
}
@ -129,24 +129,24 @@ bool BerkeleyEnvironment::Open(bilingual_str& err)
return true;
}
fs::path pathIn = strPath;
fs::path pathIn = fs::PathFromString(strPath);
TryCreateDirectories(pathIn);
if (!LockDirectory(pathIn, ".walletlock")) {
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;
}
fs::path pathLogDir = pathIn / "database";
TryCreateDirectories(pathLogDir);
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;
if (gArgs.GetBoolArg("-privdb", DEFAULT_WALLET_PRIVDB))
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_lg_bsize(0x10000);
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));
}
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) {
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;
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)) {
return false;
@ -274,7 +274,7 @@ bool BerkeleyDatabase::Verify(bilingual_str& errorStr)
Db db(env->dbenv.get(), 0);
int result = db.verify(strFile.c_str(), nullptr, nullptr, 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;
}
}
@ -566,7 +566,7 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
dbenv->log_archive(&listp, DB_ARCH_REMOVE);
Close();
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
fs::path pathSrc = env->Directory() / strFile;
fs::path pathDest(strDest);
fs::path pathDest(fs::PathFromString(strDest));
if (fs::is_directory(pathDest))
pathDest /= strFile;
pathDest /= fs::PathFromString(strFile);
try {
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;
}
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;
} 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;
}
}
@ -828,10 +828,10 @@ std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, con
std::unique_ptr<BerkeleyDatabase> db;
{
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());
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;
return nullptr;
}

View File

@ -63,7 +63,7 @@ public:
bool IsMock() const { return fMockDb; }
bool IsInitialized() const { return fDbEnvInit; }
fs::path Directory() const { return strPath; }
fs::path Directory() const { return fs::PathFromString(strPath); }
bool Open(bilingual_str& error);
void Close();
@ -141,7 +141,7 @@ public:
bool Verify(bilingual_str& error);
/** 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"; }
/**

View File

@ -12,7 +12,7 @@
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;
boost::system::error_code ec;
@ -20,9 +20,9 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
if (ec) {
if (fs::is_directory(*it)) {
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 {
LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string());
LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(it->path()));
}
continue;
}
@ -30,7 +30,8 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
try {
// 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.
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 &&
(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) {
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();
}
}
@ -85,7 +86,7 @@ bool IsBDBFile(const fs::path& path)
// This check also prevents opening lock files.
boost::system::error_code 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;
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.
boost::system::error_code 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;
fsbridge::ifstream file(path, std::ios::binary);

View File

@ -19,16 +19,16 @@ bool DumpWallet(CWallet& wallet, bilingual_str& error)
return false;
}
fs::path path = dump_filename;
fs::path path = fs::PathFromString(dump_filename);
path = fs::absolute(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;
}
fsbridge::ofstream dump_file;
dump_file.open(path);
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;
}
@ -114,10 +114,10 @@ bool CreateFromDump(const std::string& name, const fs::path& wallet_path, biling
return false;
}
fs::path dump_path = dump_filename;
fs::path dump_path = fs::PathFromString(dump_filename);
dump_path = fs::absolute(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;
}
fsbridge::ifstream dump_file(dump_path);

View File

@ -551,13 +551,13 @@ public:
}
std::string getWalletDir() override
{
return GetWalletDir().string();
return fs::PathToString(GetWalletDir());
}
std::vector<std::string> listWalletDir() override
{
std::vector<std::string> paths;
for (auto& path : ListDatabases(GetWalletDir())) {
paths.push_back(path.string());
paths.push_back(fs::PathToString(path));
}
return paths;
}

View File

@ -25,25 +25,25 @@ bool VerifyWallets(WalletContext& context)
ArgsManager& args = *Assert(context.args);
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;
// 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);
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;
} 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;
// The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
} 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;
}
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);
@ -70,7 +70,7 @@ bool VerifyWallets(WalletContext& context)
for (const auto& wallet : chain.getSettingsList("wallet")) {
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) {
chain.initWarning(strprintf(_("Ignoring duplicate -wallet %s."), wallet_file));
@ -102,7 +102,7 @@ bool LoadWallets(WalletContext& context)
std::set<fs::path> wallet_paths;
for (const auto& wallet : chain.getSettingsList("wallet")) {
const auto& name = wallet.get_str();
if (!wallet_paths.insert(name).second) {
if (!wallet_paths.insert(fs::PathFromString(name)).second) {
continue;
}
DatabaseOptions options;

View File

@ -550,7 +550,7 @@ RPCHelpMan importwallet()
EnsureWalletIsUnlocked(*pwallet);
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()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
}
@ -745,7 +745,7 @@ RPCHelpMan dumpwallet()
EnsureWalletIsUnlocked(wallet);
fs::path filepath = request.params[0].get_str();
fs::path filepath = fs::u8path(request.params[0].get_str());
filepath = fs::absolute(filepath);
/* Prevent arbitrary files from being overwritten. There have been reports
@ -754,7 +754,7 @@ RPCHelpMan dumpwallet()
* It may also avoid other security issues.
*/
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;
@ -844,7 +844,7 @@ RPCHelpMan dumpwallet()
file.close();
UniValue reply(UniValue::VOBJ);
reply.pushKV("filename", filepath.string());
reply.pushKV("filename", filepath.u8string());
return reply;
},

View File

@ -2555,7 +2555,7 @@ static RPCHelpMan listwalletdir()
UniValue wallets(UniValue::VARR);
for (const auto& path : ListDatabases(GetWalletDir())) {
UniValue wallet(UniValue::VOBJ);
wallet.pushKV("name", path.string());
wallet.pushKV("name", path.u8string());
wallets.push_back(wallet);
}
@ -2856,7 +2856,7 @@ static RPCHelpMan restorewallet()
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)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Backup file does not exist");
@ -2864,14 +2864,14 @@ static RPCHelpMan restorewallet()
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)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Wallet name already exists.");
}
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";

View File

@ -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)
: 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);
@ -206,7 +206,7 @@ void SQLiteDatabase::Open()
if (m_db == nullptr) {
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);
if (ret != SQLITE_OK) {

View File

@ -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)
{
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());
}
@ -25,11 +25,7 @@ BOOST_AUTO_TEST_CASE(getwalletenv_file)
std::string test_name = "test_name.dat";
const fs::path datadir = gArgs.GetDataDirNet();
fs::path file_path = datadir / test_name;
#if BOOST_VERSION >= 107700
std::ofstream f(BOOST_FILESYSTEM_C_STR(file_path));
#else
std::ofstream f(file_path.BOOST_FILESYSTEM_C_STR);
#endif // BOOST_VERSION >= 107700
fs::ofstream f(file_path);
f.close();
std::string filename;

View File

@ -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["custom"]);
fs::create_directories(m_walletdir_path_cases["relative"]);
#if BOOST_VERSION >= 107700
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
fs::ofstream f(m_walletdir_path_cases["file"]);
f.close();
}
@ -50,5 +46,5 @@ InitWalletDirTestingSetup::~InitWalletDirTestingSetup()
void InitWalletDirTestingSetup::SetWalletDir(const fs::path& walletdir_path)
{
gArgs.ForceSetArg("-walletdir", walletdir_path.string());
gArgs.ForceSetArg("-walletdir", fs::PathToString(walletdir_path));
}

View File

@ -17,7 +17,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
SetWalletDir(m_walletdir_path_cases["default"]);
bool result = m_wallet_client->verify();
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"]);
BOOST_CHECK_EQUAL(walletdir, expected_path);
}
@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
SetWalletDir(m_walletdir_path_cases["custom"]);
bool result = m_wallet_client->verify();
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"]);
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"]);
bool result = m_wallet_client->verify();
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"]);
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"]);
bool result = m_wallet_client->verify();
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"]);
BOOST_CHECK_EQUAL(walletdir, expected_path);
}

View File

@ -258,7 +258,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(KEY_TIME);
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.
{

View File

@ -2515,16 +2515,16 @@ std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, cons
// 2. Path to an existing directory.
// 3. Path to a symlink to a directory.
// 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();
if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
(path_type == fs::regular_file && fs::path(name).filename() == name))) {
(path_type == fs::regular_file && fs::PathFromString(name).filename() == fs::PathFromString(name)))) {
error_string = Untranslated(strprintf(
"Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
"database/log.?????????? files can be stored, a location where such a directory could be created, "
"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;
return nullptr;
}

View File

@ -1106,7 +1106,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
try {
exists = fs::symlink_status(path).type() != fs::file_not_found;
} 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;
return nullptr;
}
@ -1118,33 +1118,33 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
}
if (IsSQLiteFile(SQLiteDataFile(path))) {
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;
return nullptr;
}
format = DatabaseFormat::SQLITE;
}
} 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;
return nullptr;
}
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;
return nullptr;
}
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;
return nullptr;
}
// 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) {
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;
return nullptr;
}
@ -1166,7 +1166,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
#ifdef USE_SQLITE
return MakeSQLiteDatabase(path, options, status, error);
#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;
return nullptr;
}
@ -1174,7 +1174,7 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
#ifdef USE_BDB
return MakeBerkeleyDatabase(path, options, status, error);
#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;
return nullptr;
}

View File

@ -125,7 +125,7 @@ bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
return false;
}
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") {
DatabaseOptions options;

View File

@ -12,7 +12,7 @@ fs::path GetWalletDir()
fs::path path;
if (gArgs.IsArgSet("-walletdir")) {
path = gArgs.GetArg("-walletdir", "");
path = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
if (!fs::is_directory(path)) {
// If the path specified doesn't exist, we return the deliberately
// invalid empty string.