mirror of
https://github.com/love2d/love.git
synced 2026-08-17 02:58:31 +02:00
love.filesystem canonicalizes internal full paths where possible.
resolves #1693. resolves #1100.
This commit is contained in:
@@ -38,6 +38,9 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// C++17 std::filesystem
|
||||
#include <filesystem>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace filesystem
|
||||
@@ -182,6 +185,18 @@ bool Filesystem::createRealDirectory(const std::string &path)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Filesystem::canonicalizeRealPath(const std::string &p) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return std::filesystem::weakly_canonical(p).string();
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Filesystem::getExecutablePath() const
|
||||
{
|
||||
#if defined(LOVE_MACOS) || defined(LOVE_IOS)
|
||||
|
||||
@@ -303,6 +303,12 @@ public:
|
||||
**/
|
||||
virtual bool createRealDirectory(const std::string &path);
|
||||
|
||||
/**
|
||||
* Converts the given real path to its canonical version (e.g. resolving
|
||||
* '..', '.', relative paths, etc).
|
||||
**/
|
||||
virtual std::string canonicalizeRealPath(const std::string &path) const;
|
||||
|
||||
/**
|
||||
* Gets the full platform-dependent path to the executable.
|
||||
**/
|
||||
|
||||
@@ -172,9 +172,14 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath)
|
||||
continue;
|
||||
|
||||
// If a file is still open, unmount will fail.
|
||||
std::string fullPath = getFullCommonPath(p);
|
||||
if (!fullPath.empty() && !PHYSFS_canUnmount(fullPath.c_str()))
|
||||
return false;
|
||||
std::string fullpath = getFullCommonPath(p);
|
||||
|
||||
if (!fullpath.empty())
|
||||
{
|
||||
std::string canonpath = canonicalizeRealPath(fullpath);
|
||||
if (!PHYSFS_canUnmount(canonpath.c_str()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool oldMountedCommonPaths[COMMONPATH_MAX_ENUM] = {false};
|
||||
@@ -237,7 +242,7 @@ bool Filesystem::setSource(const char *source)
|
||||
if (!gameSource.empty())
|
||||
return false;
|
||||
|
||||
std::string new_search_path = source;
|
||||
std::string new_search_path = canonicalizeRealPath(source);
|
||||
|
||||
#ifdef LOVE_ANDROID
|
||||
if (!love::android::createStorageDirectories())
|
||||
@@ -395,10 +400,12 @@ bool Filesystem::mountFullPath(const char *archive, const char *mountpoint, Moun
|
||||
if (!PHYSFS_isInit() || !archive)
|
||||
return false;
|
||||
|
||||
if (permissions == MOUNT_PERMISSIONS_READWRITE)
|
||||
return PHYSFS_mountRW(archive, mountpoint, appendToPath) != 0;
|
||||
std::string canonarchive = canonicalizeRealPath(archive);
|
||||
|
||||
return PHYSFS_mount(archive, mountpoint, appendToPath) != 0;
|
||||
if (permissions == MOUNT_PERMISSIONS_READWRITE)
|
||||
return PHYSFS_mountRW(canonarchive.c_str(), mountpoint, appendToPath) != 0;
|
||||
|
||||
return PHYSFS_mount(canonarchive.c_str(), mountpoint, appendToPath) != 0;
|
||||
}
|
||||
|
||||
bool Filesystem::mountCommonPathInternal(CommonPath path, const char *mountpoint, MountPermissions permissions, bool appendToPath, bool createDir)
|
||||
@@ -474,10 +481,12 @@ bool Filesystem::unmount(const char *archive)
|
||||
realPath += LOVE_PATH_SEPARATOR;
|
||||
realPath += archive;
|
||||
|
||||
if (PHYSFS_getMountPoint(realPath.c_str()) == nullptr)
|
||||
std::string canonpath = canonicalizeRealPath(realPath.c_str());
|
||||
|
||||
if (PHYSFS_getMountPoint(canonpath.c_str()) == nullptr)
|
||||
return false;
|
||||
|
||||
return PHYSFS_unmount(realPath.c_str()) != 0;
|
||||
return PHYSFS_unmount(canonpath.c_str()) != 0;
|
||||
}
|
||||
|
||||
bool Filesystem::unmountFullPath(const char *fullpath)
|
||||
@@ -485,7 +494,9 @@ bool Filesystem::unmountFullPath(const char *fullpath)
|
||||
if (!PHYSFS_isInit() || !fullpath)
|
||||
return false;
|
||||
|
||||
return PHYSFS_unmount(fullpath) != 0;
|
||||
std::string canonpath = canonicalizeRealPath(fullpath);
|
||||
|
||||
return PHYSFS_unmount(canonpath.c_str()) != 0;
|
||||
}
|
||||
|
||||
bool Filesystem::unmount(CommonPath path)
|
||||
@@ -725,8 +736,6 @@ std::string Filesystem::getSourceBaseDirectory() const
|
||||
if (source_len == 0)
|
||||
return "";
|
||||
|
||||
// FIXME: This doesn't take into account parent and current directory
|
||||
// symbols (i.e. '..' and '.')
|
||||
#ifdef LOVE_WINDOWS
|
||||
// In windows, delimiters can be either '/' or '\'.
|
||||
size_t base_end_pos = gameSource.find_last_of("/\\", source_len - 2);
|
||||
|
||||
@@ -498,6 +498,13 @@ int w_getRealDirectory(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_canonicalizeRealPath(lua_State *L)
|
||||
{
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
luax_pushstring(L, instance()->canonicalizeRealPath(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getExecutablePath(lua_State *L)
|
||||
{
|
||||
luax_pushstring(L, instance()->getExecutablePath());
|
||||
@@ -1033,6 +1040,7 @@ static const luaL_Reg functions[] =
|
||||
{ "getSaveDirectory", w_getSaveDirectory },
|
||||
{ "getSourceBaseDirectory", w_getSourceBaseDirectory },
|
||||
{ "getRealDirectory", w_getRealDirectory },
|
||||
{ "canonicalizeRealPath", w_canonicalizeRealPath },
|
||||
{ "getExecutablePath", w_getExecutablePath },
|
||||
{ "createDirectory", w_createDirectory },
|
||||
{ "remove", w_remove },
|
||||
|
||||
@@ -66,20 +66,9 @@ end
|
||||
|
||||
-- Converts any path into a full path.
|
||||
function love.path.getFull(p)
|
||||
|
||||
if love.path.abs(p) then
|
||||
return love.path.normalslashes(p)
|
||||
end
|
||||
|
||||
local cwd = love.filesystem.getWorkingDirectory()
|
||||
cwd = love.path.normalslashes(cwd)
|
||||
cwd = love.path.endslash(cwd)
|
||||
|
||||
-- Construct a full path.
|
||||
local full = cwd .. love.path.normalslashes(p)
|
||||
|
||||
-- Remove trailing /., if applicable
|
||||
return full:match("(.-)/%.$") or full
|
||||
p = love.filesystem.canonicalizeRealPath(p)
|
||||
p = love.path.normalslashes(p)
|
||||
return p
|
||||
end
|
||||
|
||||
-- Returns the leaf of a full path.
|
||||
|
||||
Reference in New Issue
Block a user