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:
Alex Szpakowski
2013-08-10 20:11:50 -03:00
parent 7e4e5e9c0b
commit daf50698b8
4 changed files with 116 additions and 32 deletions
+87 -32
View File
@@ -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);