mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +02:00
Android: Fix missing directories and files with externalstorage when trying to browse it through MTP.
This commit is contained in:
+61
-5
@@ -24,6 +24,7 @@
|
|||||||
#ifdef LOVE_ANDROID
|
#ifdef LOVE_ANDROID
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
@@ -184,21 +185,76 @@ bool mkdir(const char *path)
|
|||||||
return true;
|
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()
|
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";
|
std::string saveDirectoryInternal = internalStoragePath + "/save";
|
||||||
if (!directoryExists(save_directory.c_str()) && !mkdir(save_directory.c_str()))
|
if (!tryCreateDirectory(saveDirectoryInternal.c_str()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string game_directory = internal_storage_path + "/game";
|
std::string saveDirectoryExternal = externalStoragePath + "/save";
|
||||||
if (!directoryExists (game_directory.c_str()) && !mkdir(game_directory.c_str()))
|
if (!tryCreateDirectory(saveDirectoryExternal.c_str()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string game_directory = externalStoragePath + "/game";
|
||||||
|
if (!tryCreateDirectory (game_directory.c_str()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
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()
|
bool hasBackgroundMusic()
|
||||||
{
|
{
|
||||||
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
|
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ bool mkdir(const char *path);
|
|||||||
|
|
||||||
bool createStorageDirectories();
|
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 hasBackgroundMusic();
|
||||||
|
|
||||||
bool hasRecordingPermission();
|
bool hasRecordingPermission();
|
||||||
|
|||||||
@@ -27,6 +27,10 @@
|
|||||||
#include "Filesystem.h"
|
#include "Filesystem.h"
|
||||||
#include "filesystem/FileData.h"
|
#include "filesystem/FileData.h"
|
||||||
|
|
||||||
|
#ifdef LOVE_ANDROID
|
||||||
|
#include "common/android.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
namespace filesystem
|
namespace filesystem
|
||||||
@@ -50,6 +54,21 @@ File::File(const std::string &filename, Mode mode)
|
|||||||
{
|
{
|
||||||
if (!open(mode))
|
if (!open(mode))
|
||||||
throw love::Exception("Could not open file at path %s", filename.c_str());
|
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)
|
File::File(const File &other)
|
||||||
|
|||||||
@@ -796,6 +796,16 @@ bool Filesystem::createDirectory(const char *dir)
|
|||||||
if (!PHYSFS_mkdir(dir))
|
if (!PHYSFS_mkdir(dir))
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user