mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Resolve symlinks passed to CreateDatabase()
The API checks if the given game path and game local path are directories, which isn't true if they are symlinks to directories, so if they are symlinks, resolve them before performing the directory check. Note that creating symlinks in Windows requires the SeCreateSymbolicLinkPrivilege privilege, which only admins have by default, so the test will fail unless run as admin or the privilege is given to the user running the test. Closes #645.
This commit is contained in:
+16
-5
@@ -31,7 +31,16 @@
|
||||
#include "loot/error.h"
|
||||
#include "backend/app/loot_paths.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace loot {
|
||||
std::string ResolvePath(const std::string& path) {
|
||||
if (path.empty() || !fs::is_symlink(path))
|
||||
return path;
|
||||
|
||||
return fs::read_symlink(path).string();
|
||||
}
|
||||
|
||||
LOOT_API bool IsCompatible(const unsigned int versionMajor, const unsigned int versionMinor, const unsigned int versionPatch) {
|
||||
if (versionMajor > 0)
|
||||
return versionMajor == loot::LootVersion::major;
|
||||
@@ -48,12 +57,14 @@ LOOT_API std::shared_ptr<DatabaseInterface> CreateDatabase(const GameType game,
|
||||
boost::log::core::get()->set_logging_enabled(false);
|
||||
|
||||
// Check for valid paths.
|
||||
if (!gamePath.empty() && !boost::filesystem::is_directory(gamePath))
|
||||
throw loot::Error(Error::Code::invalid_args, "Given game path \"" + std::string(gamePath) + "\" is not a valid directory.");
|
||||
const std::string resolvedGamePath = ResolvePath(gamePath);
|
||||
if (!gamePath.empty() && !fs::is_directory(resolvedGamePath))
|
||||
throw Error(Error::Code::invalid_args, "Given game path \"" + gamePath + "\" does not resolve to a valid directory.");
|
||||
|
||||
if (!gameLocalPath.empty() && !boost::filesystem::is_directory(gameLocalPath))
|
||||
throw loot::Error(Error::Code::invalid_args, "Given local data path \"" + std::string(gameLocalPath) + "\" is not a valid directory.");
|
||||
const std::string resolvedGameLocalPath = ResolvePath(gameLocalPath);
|
||||
if (!gameLocalPath.empty() && !fs::is_directory(resolvedGameLocalPath))
|
||||
throw Error(Error::Code::invalid_args, "Given local data path \"" + gameLocalPath + "\" does not resolve to a valid directory.");
|
||||
|
||||
return std::make_shared<ApiDatabase>(game, gamePath, gameLocalPath);
|
||||
return std::make_shared<ApiDatabase>(game, resolvedGamePath, resolvedGameLocalPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,17 +35,29 @@ namespace loot {
|
||||
namespace test {
|
||||
class CreateDatabaseTest : public CommonGameTestFixture {
|
||||
protected:
|
||||
CreateDatabaseTest() : db_(nullptr) {}
|
||||
CreateDatabaseTest() :
|
||||
db_(nullptr),
|
||||
gamePathSymlink(dataPath.parent_path().string() + "symlink"),
|
||||
localPathSymlink(localPath.string() + "symlink") {}
|
||||
|
||||
void SetUp() {
|
||||
CommonGameTestFixture::SetUp();
|
||||
|
||||
boost::filesystem::create_directory_symlink(dataPath.parent_path(), gamePathSymlink);
|
||||
boost::filesystem::create_directory_symlink(localPath, localPathSymlink);
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
CommonGameTestFixture::TearDown();
|
||||
|
||||
boost::filesystem::remove(gamePathSymlink);
|
||||
boost::filesystem::remove(localPathSymlink);
|
||||
}
|
||||
|
||||
std::shared_ptr<DatabaseInterface> db_;
|
||||
|
||||
const boost::filesystem::path gamePathSymlink;
|
||||
const boost::filesystem::path localPathSymlink;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
@@ -86,6 +98,11 @@ TEST_P(CreateDatabaseTest, shouldReturnOkIfPassedAnEmptyLocalPathString) {
|
||||
EXPECT_NE(nullptr, db_);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_P(CreateDatabaseTest, shouldReturnOkIfPassedGameAndLocalPathSymlinks) {
|
||||
EXPECT_NO_THROW(db_ = CreateDatabase(GetParam(), gamePathSymlink.string(), localPathSymlink.string()));
|
||||
EXPECT_NE(nullptr, db_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user