diff options
-rw-r--r-- | src/init.cpp | 2 | ||||
-rw-r--r-- | src/test/getarg_tests.cpp | 92 | ||||
-rw-r--r-- | src/util/system.cpp | 31 | ||||
-rw-r--r-- | src/util/system.h | 10 | ||||
-rw-r--r-- | src/wallet/load.cpp | 2 | ||||
-rw-r--r-- | src/wallet/test/init_tests.cpp | 8 | ||||
-rw-r--r-- | src/wallet/walletutil.cpp | 2 |
7 files changed, 121 insertions, 26 deletions
diff --git a/src/init.cpp b/src/init.cpp index 330aab5184..6aef1f8149 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1150,7 +1150,7 @@ 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::PathFromString(args.GetArg("-datadir", "")).is_absolute()) { + if (args.IsArgSet("-datadir") && !args.GetPathArg("-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 " diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index d5142c8d74..597d774673 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -159,6 +159,98 @@ BOOST_AUTO_TEST_CASE(intarg) BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 11), 0); } +BOOST_AUTO_TEST_CASE(patharg) +{ + const auto dir = std::make_pair("-dir", ArgsManager::ALLOW_ANY); + SetupArgs({dir}); + ResetArgs(""); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), fs::path{}); + + const fs::path root_path{"/"}; + ResetArgs("-dir=/"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path); + + ResetArgs("-dir=/."); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path); + + ResetArgs("-dir=/./"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path); + + ResetArgs("-dir=/.//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path); + +#ifdef WIN32 + const fs::path win_root_path{"C:\\"}; + ResetArgs("-dir=C:\\"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:/"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:\\\\"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:\\."); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:\\.\\"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:\\.\\\\"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); +#endif + + const fs::path absolute_path{"/home/user/.bitcoin"}; + ResetArgs("-dir=/home/user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/root/../home/user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/./user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin/"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin/."); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin/./"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin/.//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + const fs::path relative_path{"user/.bitcoin"}; + ResetArgs("-dir=user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=somewhere/../user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/./.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin/"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin/."); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin/./"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin/.//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); +} + BOOST_AUTO_TEST_CASE(doubledash) { const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY); diff --git a/src/util/system.cpp b/src/util/system.cpp index 4ead39dd6c..64d8ef38f0 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -245,19 +245,6 @@ static std::optional<util::SettingsValue> InterpretValue(const KeyInfo& key, con return value; } -namespace { -fs::path StripRedundantLastElementsOfPath(const fs::path& path) -{ - auto result = path; - while (result.filename().empty() || fs::PathToString(result.filename()) == ".") { - result = result.parent_path(); - } - - assert(fs::equivalent(result, path.lexically_normal())); - return result; -} -} // namespace - // Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to // #include class definitions for all members. // For example, m_settings has an internal dependency on univalue. @@ -399,6 +386,13 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co return std::nullopt; } +fs::path ArgsManager::GetPathArg(std::string pathlike_arg) const +{ + auto result = fs::PathFromString(GetArg(pathlike_arg, "")).lexically_normal(); + // Remove trailing slash, if present. + return result.has_filename() ? result : result.parent_path(); +} + const fs::path& ArgsManager::GetBlocksDirPath() const { LOCK(cs_args); @@ -409,7 +403,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const if (!path.empty()) return path; if (IsArgSet("-blocksdir")) { - path = fs::absolute(fs::PathFromString(GetArg("-blocksdir", ""))); + path = fs::absolute(GetPathArg("-blocksdir")); if (!fs::is_directory(path)) { path = ""; return path; @@ -433,9 +427,9 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const // this function if (!path.empty()) return path; - std::string datadir = GetArg("-datadir", ""); + const fs::path datadir{GetPathArg("-datadir")}; if (!datadir.empty()) { - path = fs::absolute(StripRedundantLastElementsOfPath(fs::PathFromString(datadir))); + path = fs::absolute(datadir); if (!fs::is_directory(path)) { path = ""; return path; @@ -455,7 +449,6 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const } } - path = StripRedundantLastElementsOfPath(path); return path; } @@ -816,8 +809,8 @@ fs::path GetDefaultDataDir() bool CheckDataDirOption() { - std::string datadir = gArgs.GetArg("-datadir", ""); - return datadir.empty() || fs::is_directory(fs::absolute(fs::PathFromString(datadir))); + const fs::path datadir{gArgs.GetPathArg("-datadir")}; + return datadir.empty() || fs::is_directory(fs::absolute(datadir)); } fs::path GetConfigFile(const std::string& confPath) diff --git a/src/util/system.h b/src/util/system.h index a8fd21fcaa..6b7bd38cc2 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -265,6 +265,16 @@ protected: std::optional<const Command> GetCommand() const; /** + * Get a normalized path from a specified pathlike argument + * + * It is guaranteed that the returned path has no trailing slashes. + * + * @param pathlike_arg Pathlike argument to get a path from (e.g., "-datadir", "-blocksdir" or "-walletdir") + * @return Normalized path which is get from a specified pathlike argument + */ + fs::path GetPathArg(std::string pathlike_arg) const; + + /** * Get blocks directory path * * @return Blocks path which is network specific diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp index 6a74f2eb84..633d8c5450 100644 --- a/src/wallet/load.cpp +++ b/src/wallet/load.cpp @@ -28,7 +28,7 @@ bool VerifyWallets(WalletContext& context) ArgsManager& args = *Assert(context.args); if (args.IsArgSet("-walletdir")) { - fs::path wallet_dir = fs::PathFromString(args.GetArg("-walletdir", "")); + const fs::path wallet_dir{args.GetPathArg("-walletdir")}; std::error_code error; // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory // It also lets the fs::exists and fs::is_directory checks below pass on windows, since they return false diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp index c1cae5c5f6..7fdecc5642 100644 --- a/src/wallet/test/init_tests.cpp +++ b/src/wallet/test/init_tests.cpp @@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default) SetWalletDir(m_walletdir_path_cases["default"]); bool result = m_wallet_loader->verify(); BOOST_CHECK(result == true); - fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + fs::path walletdir = gArgs.GetPathArg("-walletdir"); fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); BOOST_CHECK_EQUAL(walletdir, expected_path); } @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom) SetWalletDir(m_walletdir_path_cases["custom"]); bool result = m_wallet_loader->verify(); BOOST_CHECK(result == true); - fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + fs::path walletdir = gArgs.GetPathArg("-walletdir"); fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]); BOOST_CHECK_EQUAL(walletdir, expected_path); } @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing) SetWalletDir(m_walletdir_path_cases["trailing"]); bool result = m_wallet_loader->verify(); BOOST_CHECK(result == true); - fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + fs::path walletdir = gArgs.GetPathArg("-walletdir"); fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); BOOST_CHECK_EQUAL(walletdir, expected_path); } @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2) SetWalletDir(m_walletdir_path_cases["trailing2"]); bool result = m_wallet_loader->verify(); BOOST_CHECK(result == true); - fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + fs::path walletdir = gArgs.GetPathArg("-walletdir"); fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); BOOST_CHECK_EQUAL(walletdir, expected_path); } diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index ce276451c3..df1b10a634 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -13,7 +13,7 @@ fs::path GetWalletDir() fs::path path; if (gArgs.IsArgSet("-walletdir")) { - path = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + path = gArgs.GetPathArg("-walletdir"); if (!fs::is_directory(path)) { // If the path specified doesn't exist, we return the deliberately // invalid empty string. |