Skip to content

Commit

Permalink
Android: Fix missing directories and files with externalstorage when …
Browse files Browse the repository at this point in the history
…trying to browse it through MTP.
  • Loading branch information
MikuAuahDark committed Apr 25, 2024
1 parent 562de22 commit 4270985
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 5 deletions.
66 changes: 61 additions & 5 deletions src/common/android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#ifdef LOVE_ANDROID

#include <cerrno>
#include <set>
#include <unordered_map>

#include <SDL.h>
Expand Down Expand Up @@ -184,21 +185,76 @@ bool mkdir(const char *path)
return true;
}

inline bool tryCreateDirectory(const char *path)
{
SDL_Log("Trying to create directory '%s'", path);

if (directoryExists(path))
return true;
else if (mkdir(path))
return true;
return false;
}

bool createStorageDirectories()
{
std::string internal_storage_path = SDL_AndroidGetInternalStoragePath();
std::string internalStoragePath = SDL_AndroidGetInternalStoragePath();
std::string externalStoragePath = SDL_AndroidGetExternalStoragePath();

std::string save_directory = internal_storage_path + "/save";
if (!directoryExists(save_directory.c_str()) && !mkdir(save_directory.c_str()))
std::string saveDirectoryInternal = internalStoragePath + "/save";
if (!tryCreateDirectory(saveDirectoryInternal.c_str()))
return false;

std::string game_directory = internal_storage_path + "/game";
if (!directoryExists (game_directory.c_str()) && !mkdir(game_directory.c_str()))
std::string saveDirectoryExternal = externalStoragePath + "/save";
if (!tryCreateDirectory(saveDirectoryExternal.c_str()))
return false;

std::string game_directory = externalStoragePath + "/game";
if (!tryCreateDirectory (game_directory.c_str()))
return false;

return true;
}

void fixupPermissionSingleFile(const std::string &savedir, const std::string &path)
{
std::string fixedSavedir = savedir.back() == '/' ? savedir : (savedir + "/");
std::string target = fixedSavedir + path;
::chmod(target.c_str(), 0660);
}

void fixupExternalStoragePermission(const std::string &savedir, const std::string &path)
{
std::set<std::string> pathsToFix;
size_t start = 0;

while (true)
{
size_t pos = path.find('/', start);
if (pos == std::string::npos)
{
pathsToFix.insert(path);
break;
}

pathsToFix.insert(path.substr(0, pos));
start = pos + 1;
}

std::string fixedSavedir = savedir.back() == '/' ? savedir : (savedir + "/");
::chmod(savedir.c_str(), 0770);

for (const std::string &dir: pathsToFix)
{
const char *realPath = PHYSFS_getRealDir(dir.c_str());
if (!dir.empty() && strcmp(realPath, savedir.c_str()) == 0)
{
std::string target = fixedSavedir + dir;
::chmod(target.c_str(), 0770);
}
}
}

bool hasBackgroundMusic()
{
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
Expand Down
4 changes: 4 additions & 0 deletions src/common/android.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ bool mkdir(const char *path);

bool createStorageDirectories();

void fixupPermissionSingleFile(const std::string &savedir, const std::string &path);

void fixupExternalStoragePermission(const std::string &savedir, const std::string &path);

bool hasBackgroundMusic();

bool hasRecordingPermission();
Expand Down
19 changes: 19 additions & 0 deletions src/modules/filesystem/physfs/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#include "Filesystem.h"
#include "filesystem/FileData.h"

#ifdef LOVE_ANDROID
#include "common/android.h"
#endif

namespace love
{
namespace filesystem
Expand All @@ -50,6 +54,21 @@ File::File(const std::string &filename, Mode mode)
{
if (!open(mode))
throw love::Exception("Could not open file at path %s", filename.c_str());

#ifdef LOVE_ANDROID
// In Android with t.externalstorage = true, make sure the file opened or
// created in the save directory has permissions of ug+rw (0660) so that
// it's accessible through MTP.
auto fs = Module::getInstance<love::filesystem::Filesystem>(Module::M_FILESYSTEM);
if (fs != nullptr && fs->isAndroidSaveExternal())
{
const char *realdir = PHYSFS_getRealDir(filename.c_str());
const std::string &savedir = fs->getFullCommonPath(Filesystem::COMMONPATH_APP_SAVEDIR);

if (realdir != nullptr && strcmp(realdir, savedir.c_str()) == 0)
love::android::fixupPermissionSingleFile(savedir, filename);
#endif
}
}

File::File(const File &other)
Expand Down
10 changes: 10 additions & 0 deletions src/modules/filesystem/physfs/Filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,16 @@ bool Filesystem::createDirectory(const char *dir)
if (!PHYSFS_mkdir(dir))
return false;

#ifdef LOVE_ANDROID
// In Android with t.externalstorage = true, make sure the directory
// created in the save directory has permissions of ug+rwx (0770) so that
// it's accessible through MTP.
if (isAndroidSaveExternal())
love::android::fixupExternalStoragePermission(
getFullCommonPath(CommonPath::COMMONPATH_APP_SAVEDIR),
dir
);
#endif
return true;
}

Expand Down

0 comments on commit 4270985

Please sign in to comment.