mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
Added love.filesystem.getSourceBaseDirectory and changed love.filesystem.mount to allow mounting the path returned by love.filesystem.getSourceBaseDirectory in fused mode.
This commit is contained in:
@@ -137,6 +137,11 @@ bool Filesystem::setSource(const char *source)
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *Filesystem::getSource() const
|
||||
{
|
||||
return game_source.c_str();
|
||||
}
|
||||
|
||||
bool Filesystem::setupWriteDirectory()
|
||||
{
|
||||
if (!initialized)
|
||||
@@ -160,7 +165,8 @@ bool Filesystem::setupWriteDirectory()
|
||||
|
||||
if (!success)
|
||||
{
|
||||
PHYSFS_setWriteDir(0); // Clear the write directory in case of error.
|
||||
// Clear the write directory in case of error.
|
||||
PHYSFS_setWriteDir(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -183,24 +189,39 @@ bool Filesystem::mount(const char *archive, const char *mountpoint, SearchOrder
|
||||
if (!initialized || !archive)
|
||||
return false;
|
||||
|
||||
// Not allowed for safety reasons.
|
||||
if (strlen(archive) == 0 || strstr(archive, "..") || strcmp(archive, "/") == 0)
|
||||
std::string realPath;
|
||||
std::string sourceBase = getSourceBaseDirectory();
|
||||
|
||||
if (isFused() && sourceBase.compare(archive) == 0)
|
||||
{
|
||||
// Special case: if the game is fused and the archive is the source's
|
||||
// base directory, mount it even though it's outside of the save dir.
|
||||
realPath = sourceBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not allowed for safety reasons.
|
||||
if (strlen(archive) == 0 || strstr(archive, "..") || strcmp(archive, "/") == 0)
|
||||
return false;
|
||||
|
||||
const char *realDir = PHYSFS_getRealDir(archive);
|
||||
if (!realDir)
|
||||
return false;
|
||||
|
||||
realPath = realDir;
|
||||
|
||||
// Always disallow mounting of files inside the game source, since it
|
||||
// won't work anyway if the game source is a zipped .love file.
|
||||
if (realPath.find(game_source) == 0)
|
||||
return false;
|
||||
|
||||
realPath += LOVE_PATH_SEPARATOR;
|
||||
realPath += archive;
|
||||
}
|
||||
|
||||
if (realPath.length() == 0)
|
||||
return false;
|
||||
|
||||
const char *realDir = PHYSFS_getRealDir(archive);
|
||||
if (!realDir)
|
||||
return false;
|
||||
|
||||
std::string realPath(realDir);
|
||||
|
||||
// Always disallow mounting of files inside the game source, since it won't
|
||||
// work anyway if the game source is a zipped .love file.
|
||||
if (realPath.find(game_source) == 0)
|
||||
return false;
|
||||
|
||||
realPath += LOVE_PATH_SEPARATOR;
|
||||
realPath += archive;
|
||||
|
||||
bool append = (searchorder == SEARCH_ORDER_LAST);
|
||||
|
||||
return PHYSFS_mount(realPath.c_str(), mountpoint, append);
|
||||
@@ -211,17 +232,29 @@ bool Filesystem::unmount(const char *archive)
|
||||
if (!initialized || !archive)
|
||||
return false;
|
||||
|
||||
// Not allowed for safety reasons.
|
||||
if (strlen(archive) == 0 || strstr(archive, "..") || strcmp(archive, "/") == 0)
|
||||
return false;
|
||||
std::string realPath;
|
||||
std::string sourceBase = getSourceBaseDirectory();
|
||||
|
||||
const char *realDir = PHYSFS_getRealDir(archive);
|
||||
if (!realDir)
|
||||
return false;
|
||||
if (isFused() && sourceBase.compare(archive) == 0)
|
||||
{
|
||||
// Special case: if the game is fused and the archive is the source's
|
||||
// base directory, unmount it even though it's outside of the save dir.
|
||||
realPath = sourceBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not allowed for safety reasons.
|
||||
if (strlen(archive) == 0 || strstr(archive, "..") || strcmp(archive, "/") == 0)
|
||||
return false;
|
||||
|
||||
std::string realPath(realDir);
|
||||
realPath += LOVE_PATH_SEPARATOR;
|
||||
realPath += archive;
|
||||
const char *realDir = PHYSFS_getRealDir(archive);
|
||||
if (!realDir)
|
||||
return false;
|
||||
|
||||
realPath = realDir;
|
||||
realPath += LOVE_PATH_SEPARATOR;
|
||||
realPath += archive;
|
||||
}
|
||||
|
||||
const char *mountPoint = PHYSFS_getMountPoint(realPath.c_str());
|
||||
if (!mountPoint)
|
||||
@@ -326,18 +359,40 @@ const char *Filesystem::getSaveDirectory()
|
||||
return save_path_full.c_str();
|
||||
}
|
||||
|
||||
std::string Filesystem::getSourceBaseDirectory() const
|
||||
{
|
||||
size_t source_len = game_source.length();
|
||||
|
||||
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 = game_source.find_last_of("/\\", source_len - 2);
|
||||
#else
|
||||
size_t base_end_pos = game_source.find_last_of('/', source_len - 2);
|
||||
#endif
|
||||
|
||||
if (base_end_pos == std::string::npos)
|
||||
return "";
|
||||
|
||||
// If the source is in the unix root (aka '/'), we want to keep the '/'.
|
||||
if (base_end_pos == 0)
|
||||
base_end_pos = 1;
|
||||
|
||||
return game_source.substr(0, base_end_pos);
|
||||
}
|
||||
|
||||
bool Filesystem::exists(const char *file) const
|
||||
{
|
||||
if (PHYSFS_exists(file))
|
||||
return true;
|
||||
return false;
|
||||
return PHYSFS_exists(file);
|
||||
}
|
||||
|
||||
bool Filesystem::isDirectory(const char *file) const
|
||||
{
|
||||
if (PHYSFS_isDirectory(file))
|
||||
return true;
|
||||
return false;
|
||||
return PHYSFS_isDirectory(file);
|
||||
}
|
||||
|
||||
bool Filesystem::isFile(const char *file) const
|
||||
|
||||
@@ -118,6 +118,12 @@ public:
|
||||
**/
|
||||
bool setSource(const char *source);
|
||||
|
||||
/**
|
||||
* Gets the path to the game source.
|
||||
* Returns a 0-length string if the source has not been set.
|
||||
**/
|
||||
const char *getSource() const;
|
||||
|
||||
bool mount(const char *archive, const char *mountpoint, SearchOrder searchorder = SEARCH_ORDER_FIRST);
|
||||
bool unmount(const char *archive);
|
||||
|
||||
@@ -162,6 +168,13 @@ public:
|
||||
**/
|
||||
const char *getSaveDirectory();
|
||||
|
||||
/**
|
||||
* Gets the full path to the directory containing the game source.
|
||||
* For example if the game source is C:\Games\mygame.love, this will return
|
||||
* C:\Games.
|
||||
**/
|
||||
std::string getSourceBaseDirectory() const;
|
||||
|
||||
/**
|
||||
* Checks whether a file exists in the current search path
|
||||
* or not.
|
||||
|
||||
@@ -111,6 +111,12 @@ int w_setSource(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_getSource(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, instance->getSource());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_mount(lua_State *L)
|
||||
{
|
||||
const char *archive = luaL_checkstring(L, 1);
|
||||
@@ -249,6 +255,12 @@ int w_getSaveDirectory(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getSourceBaseDirectory(lua_State *L)
|
||||
{
|
||||
luax_pushstring(L, instance->getSourceBaseDirectory());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_exists(lua_State *L)
|
||||
{
|
||||
const char *arg = luaL_checkstring(L, 1);
|
||||
@@ -580,6 +592,7 @@ static const luaL_Reg functions[] =
|
||||
{ "setIdentity", w_setIdentity },
|
||||
{ "getIdentity", w_getIdentity },
|
||||
{ "setSource", w_setSource },
|
||||
{ "getSource", w_getSource },
|
||||
{ "mount", w_mount },
|
||||
{ "unmount", w_unmount },
|
||||
{ "newFile", w_newFile },
|
||||
@@ -587,6 +600,7 @@ static const luaL_Reg functions[] =
|
||||
{ "getUserDirectory", w_getUserDirectory },
|
||||
{ "getAppdataDirectory", w_getAppdataDirectory },
|
||||
{ "getSaveDirectory", w_getSaveDirectory },
|
||||
{ "getSourceBaseDirectory", w_getSourceBaseDirectory },
|
||||
{ "exists", w_exists },
|
||||
{ "isDirectory", w_isDirectory },
|
||||
{ "isFile", w_isFile },
|
||||
|
||||
@@ -43,6 +43,7 @@ int w_isFused(lua_State *L);
|
||||
int w_setIdentity(lua_State *L);
|
||||
int w_getIdentity(lua_State *L);
|
||||
int w_setSource(lua_State *L);
|
||||
int w_getSource(lua_State *L);
|
||||
int w_mount(lua_State *L);
|
||||
int w_unmount(lua_State *L);
|
||||
int w_newFile(lua_State *L);
|
||||
@@ -51,6 +52,7 @@ int w_getWorkingDirectory(lua_State *L);
|
||||
int w_getUserDirectory(lua_State *L);
|
||||
int w_getAppdataDirectory(lua_State *L);
|
||||
int w_getSaveDirectory(lua_State *L);
|
||||
int w_getSourceBaseDirectory(lua_State *L);
|
||||
int w_exists(lua_State *L);
|
||||
int w_isDirectory(lua_State *L);
|
||||
int w_isFile(lua_State *L);
|
||||
|
||||
Reference in New Issue
Block a user