mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +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>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// C++17 std::filesystem
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
namespace filesystem
|
namespace filesystem
|
||||||
@@ -182,6 +185,18 @@ bool Filesystem::createRealDirectory(const std::string &path)
|
|||||||
return true;
|
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
|
std::string Filesystem::getExecutablePath() const
|
||||||
{
|
{
|
||||||
#if defined(LOVE_MACOS) || defined(LOVE_IOS)
|
#if defined(LOVE_MACOS) || defined(LOVE_IOS)
|
||||||
|
|||||||
@@ -303,6 +303,12 @@ public:
|
|||||||
**/
|
**/
|
||||||
virtual bool createRealDirectory(const std::string &path);
|
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.
|
* Gets the full platform-dependent path to the executable.
|
||||||
**/
|
**/
|
||||||
|
|||||||
@@ -172,9 +172,14 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If a file is still open, unmount will fail.
|
// If a file is still open, unmount will fail.
|
||||||
std::string fullPath = getFullCommonPath(p);
|
std::string fullpath = getFullCommonPath(p);
|
||||||
if (!fullPath.empty() && !PHYSFS_canUnmount(fullPath.c_str()))
|
|
||||||
return false;
|
if (!fullpath.empty())
|
||||||
|
{
|
||||||
|
std::string canonpath = canonicalizeRealPath(fullpath);
|
||||||
|
if (!PHYSFS_canUnmount(canonpath.c_str()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool oldMountedCommonPaths[COMMONPATH_MAX_ENUM] = {false};
|
bool oldMountedCommonPaths[COMMONPATH_MAX_ENUM] = {false};
|
||||||
@@ -237,7 +242,7 @@ bool Filesystem::setSource(const char *source)
|
|||||||
if (!gameSource.empty())
|
if (!gameSource.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string new_search_path = source;
|
std::string new_search_path = canonicalizeRealPath(source);
|
||||||
|
|
||||||
#ifdef LOVE_ANDROID
|
#ifdef LOVE_ANDROID
|
||||||
if (!love::android::createStorageDirectories())
|
if (!love::android::createStorageDirectories())
|
||||||
@@ -395,10 +400,12 @@ bool Filesystem::mountFullPath(const char *archive, const char *mountpoint, Moun
|
|||||||
if (!PHYSFS_isInit() || !archive)
|
if (!PHYSFS_isInit() || !archive)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (permissions == MOUNT_PERMISSIONS_READWRITE)
|
std::string canonarchive = canonicalizeRealPath(archive);
|
||||||
return PHYSFS_mountRW(archive, mountpoint, appendToPath) != 0;
|
|
||||||
|
|
||||||
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)
|
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 += LOVE_PATH_SEPARATOR;
|
||||||
realPath += archive;
|
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 false;
|
||||||
|
|
||||||
return PHYSFS_unmount(realPath.c_str()) != 0;
|
return PHYSFS_unmount(canonpath.c_str()) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Filesystem::unmountFullPath(const char *fullpath)
|
bool Filesystem::unmountFullPath(const char *fullpath)
|
||||||
@@ -485,7 +494,9 @@ bool Filesystem::unmountFullPath(const char *fullpath)
|
|||||||
if (!PHYSFS_isInit() || !fullpath)
|
if (!PHYSFS_isInit() || !fullpath)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return PHYSFS_unmount(fullpath) != 0;
|
std::string canonpath = canonicalizeRealPath(fullpath);
|
||||||
|
|
||||||
|
return PHYSFS_unmount(canonpath.c_str()) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Filesystem::unmount(CommonPath path)
|
bool Filesystem::unmount(CommonPath path)
|
||||||
@@ -725,8 +736,6 @@ std::string Filesystem::getSourceBaseDirectory() const
|
|||||||
if (source_len == 0)
|
if (source_len == 0)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
// FIXME: This doesn't take into account parent and current directory
|
|
||||||
// symbols (i.e. '..' and '.')
|
|
||||||
#ifdef LOVE_WINDOWS
|
#ifdef LOVE_WINDOWS
|
||||||
// In windows, delimiters can be either '/' or '\'.
|
// In windows, delimiters can be either '/' or '\'.
|
||||||
size_t base_end_pos = gameSource.find_last_of("/\\", source_len - 2);
|
size_t base_end_pos = gameSource.find_last_of("/\\", source_len - 2);
|
||||||
|
|||||||
@@ -498,6 +498,13 @@ int w_getRealDirectory(lua_State *L)
|
|||||||
return 1;
|
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)
|
int w_getExecutablePath(lua_State *L)
|
||||||
{
|
{
|
||||||
luax_pushstring(L, instance()->getExecutablePath());
|
luax_pushstring(L, instance()->getExecutablePath());
|
||||||
@@ -1033,6 +1040,7 @@ static const luaL_Reg functions[] =
|
|||||||
{ "getSaveDirectory", w_getSaveDirectory },
|
{ "getSaveDirectory", w_getSaveDirectory },
|
||||||
{ "getSourceBaseDirectory", w_getSourceBaseDirectory },
|
{ "getSourceBaseDirectory", w_getSourceBaseDirectory },
|
||||||
{ "getRealDirectory", w_getRealDirectory },
|
{ "getRealDirectory", w_getRealDirectory },
|
||||||
|
{ "canonicalizeRealPath", w_canonicalizeRealPath },
|
||||||
{ "getExecutablePath", w_getExecutablePath },
|
{ "getExecutablePath", w_getExecutablePath },
|
||||||
{ "createDirectory", w_createDirectory },
|
{ "createDirectory", w_createDirectory },
|
||||||
{ "remove", w_remove },
|
{ "remove", w_remove },
|
||||||
|
|||||||
@@ -66,20 +66,9 @@ end
|
|||||||
|
|
||||||
-- Converts any path into a full path.
|
-- Converts any path into a full path.
|
||||||
function love.path.getFull(p)
|
function love.path.getFull(p)
|
||||||
|
p = love.filesystem.canonicalizeRealPath(p)
|
||||||
if love.path.abs(p) then
|
p = love.path.normalslashes(p)
|
||||||
return love.path.normalslashes(p)
|
return 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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Returns the leaf of a full path.
|
-- Returns the leaf of a full path.
|
||||||
|
|||||||
Reference in New Issue
Block a user