Add love.filesystem.mountFullPath.

This commit is contained in:
Alex Szpakowski
2020-10-03 19:28:57 -03:00
parent dcf0968f05
commit 0706b6243c
13 changed files with 494 additions and 208 deletions
@@ -960,6 +960,8 @@
FAAA3FDA1F64B3AD00F89E99 /* lstrlib.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAA3FD51F64B3AD00F89E99 /* lstrlib.h */; }; FAAA3FDA1F64B3AD00F89E99 /* lstrlib.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAA3FD51F64B3AD00F89E99 /* lstrlib.h */; };
FAAA3FDB1F64B3AD00F89E99 /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = FAAA3FD61F64B3AD00F89E99 /* lutf8lib.c */; }; FAAA3FDB1F64B3AD00F89E99 /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = FAAA3FD61F64B3AD00F89E99 /* lutf8lib.c */; };
FAAA3FDC1F64B3AD00F89E99 /* lutf8lib.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAA3FD71F64B3AD00F89E99 /* lutf8lib.h */; }; FAAA3FDC1F64B3AD00F89E99 /* lutf8lib.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAA3FD71F64B3AD00F89E99 /* lutf8lib.h */; };
FAAC2F79251A9D2200BCB81B /* apple.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAAC2F78251A9D2200BCB81B /* apple.mm */; };
FAAC2F7A251A9D2200BCB81B /* apple.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAAC2F78251A9D2200BCB81B /* apple.mm */; };
FAAFF04416CB11C700CCDE45 /* OpenAL-Soft.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */; }; FAAFF04416CB11C700CCDE45 /* OpenAL-Soft.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */; };
FAB17BE61ABFAA9000F9BA27 /* lz4.c in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BE41ABFAA9000F9BA27 /* lz4.c */; }; FAB17BE61ABFAA9000F9BA27 /* lz4.c in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BE41ABFAA9000F9BA27 /* lz4.c */; };
FAB17BE71ABFAA9000F9BA27 /* lz4.c in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BE41ABFAA9000F9BA27 /* lz4.c */; }; FAB17BE71ABFAA9000F9BA27 /* lz4.c in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BE41ABFAA9000F9BA27 /* lz4.c */; };
@@ -1916,6 +1918,8 @@
FAAA3FD51F64B3AD00F89E99 /* lstrlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lstrlib.h; sourceTree = "<group>"; }; FAAA3FD51F64B3AD00F89E99 /* lstrlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lstrlib.h; sourceTree = "<group>"; };
FAAA3FD61F64B3AD00F89E99 /* lutf8lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lutf8lib.c; sourceTree = "<group>"; }; FAAA3FD61F64B3AD00F89E99 /* lutf8lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lutf8lib.c; sourceTree = "<group>"; };
FAAA3FD71F64B3AD00F89E99 /* lutf8lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lutf8lib.h; sourceTree = "<group>"; }; FAAA3FD71F64B3AD00F89E99 /* lutf8lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lutf8lib.h; sourceTree = "<group>"; };
FAAC2F78251A9D2200BCB81B /* apple.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = apple.mm; sourceTree = "<group>"; };
FAAC2F7F251A9D3E00BCB81B /* apple.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = apple.h; sourceTree = "<group>"; };
FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "OpenAL-Soft.framework"; path = "/Library/Frameworks/OpenAL-Soft.framework"; sourceTree = "<absolute>"; }; FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "OpenAL-Soft.framework"; path = "/Library/Frameworks/OpenAL-Soft.framework"; sourceTree = "<absolute>"; };
FAB17BE41ABFAA9000F9BA27 /* lz4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lz4.c; sourceTree = "<group>"; }; FAB17BE41ABFAA9000F9BA27 /* lz4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lz4.c; sourceTree = "<group>"; };
FAB17BE51ABFAA9000F9BA27 /* lz4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lz4.h; sourceTree = "<group>"; }; FAB17BE51ABFAA9000F9BA27 /* lz4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lz4.h; sourceTree = "<group>"; };
@@ -2189,6 +2193,8 @@
children = ( children = (
FAA3A9AC1B7D465A00CED060 /* android.cpp */, FAA3A9AC1B7D465A00CED060 /* android.cpp */,
FAA3A9AD1B7D465A00CED060 /* android.h */, FAA3A9AD1B7D465A00CED060 /* android.h */,
FAAC2F7F251A9D3E00BCB81B /* apple.h */,
FAAC2F78251A9D2200BCB81B /* apple.mm */,
FA0B78F71A958E3B000E1D17 /* b64.cpp */, FA0B78F71A958E3B000E1D17 /* b64.cpp */,
FA0B78F81A958E3B000E1D17 /* b64.h */, FA0B78F81A958E3B000E1D17 /* b64.h */,
FA6BDE5B1F31725300786805 /* Color.h */, FA6BDE5B1F31725300786805 /* Color.h */,
@@ -4649,6 +4655,7 @@
FA0B7E1F1A95902C000E1D17 /* Physics.cpp in Sources */, FA0B7E1F1A95902C000E1D17 /* Physics.cpp in Sources */,
FA6A2B7B1F60B8250074C308 /* wrap_ByteData.cpp in Sources */, FA6A2B7B1F60B8250074C308 /* wrap_ByteData.cpp in Sources */,
FA0B7E821A95902C000E1D17 /* Shape.cpp in Sources */, FA0B7E821A95902C000E1D17 /* Shape.cpp in Sources */,
FAAC2F7A251A9D2200BCB81B /* apple.mm in Sources */,
FA0B7ACE1A958EA3000E1D17 /* packet.c in Sources */, FA0B7ACE1A958EA3000E1D17 /* packet.c in Sources */,
FAF140891E20934C00F898D2 /* PoolAlloc.cpp in Sources */, FAF140891E20934C00F898D2 /* PoolAlloc.cpp in Sources */,
FA27B3B41B498151008A9DCE /* wrap_Video.cpp in Sources */, FA27B3B41B498151008A9DCE /* wrap_Video.cpp in Sources */,
@@ -5045,6 +5052,7 @@
FAF140881E20934C00F898D2 /* PoolAlloc.cpp in Sources */, FAF140881E20934C00F898D2 /* PoolAlloc.cpp in Sources */,
FA0B7AAD1A958EA3000E1D17 /* b2WheelJoint.cpp in Sources */, FA0B7AAD1A958EA3000E1D17 /* b2WheelJoint.cpp in Sources */,
FA0B7DEE1A95902C000E1D17 /* Mouse.cpp in Sources */, FA0B7DEE1A95902C000E1D17 /* Mouse.cpp in Sources */,
FAAC2F79251A9D2200BCB81B /* apple.mm in Sources */,
FAA54ACC1F91660400A8FA7B /* TheoraVideoStream.cpp in Sources */, FAA54ACC1F91660400A8FA7B /* TheoraVideoStream.cpp in Sources */,
FA1E887E1DF363CD00E808AA /* Filter.cpp in Sources */, FA1E887E1DF363CD00E808AA /* Filter.cpp in Sources */,
FA0B7D281A95902C000E1D17 /* wrap_GlyphData.cpp in Sources */, FA0B7D281A95902C000E1D17 /* wrap_GlyphData.cpp in Sources */,
+15
View File
@@ -197,6 +197,21 @@ bool getConstant(const char *in, type &out) { return name##s.find(in, out); } \
bool getConstant(type in, const char *&out) { return name##s.find(in, out); } \ bool getConstant(type in, const char *&out) { return name##s.find(in, out); } \
std::vector<std::string> getConstants(type) { return name##s.getNames(); } std::vector<std::string> getConstants(type) { return name##s.getNames(); }
#define STRINGMAP_CLASS_DECLARE(type) \
static bool getConstant(const char *in, type &out); \
static bool getConstant(type in, const char *&out); \
static std::vector<std::string> getConstants(type); \
#define STRINGMAP_CLASS_BEGIN(classname, type, count, name) \
static StringMap<type, count>::Entry name##Entries[] =
#define STRINGMAP_CLASS_END(classname, type, count, name) \
; \
static StringMap<type, count> name##s(name##Entries, sizeof(name##Entries)); \
bool classname::getConstant(const char *in, type &out) { return name##s.find(in, out); } \
bool classname::getConstant(type in, const char *&out) { return name##s.find(in, out); } \
std::vector<std::string> classname::getConstants(type) { return name##s.getNames(); }
} // love } // love
#endif // LOVE_STRING_MAP_H #endif // LOVE_STRING_MAP_H
+50
View File
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2006-2020 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#pragma once
#include "config.h"
#if defined(LOVE_IOS) || defined(LOVE_MACOS)
#include <string>
namespace love
{
namespace apple
{
enum UserDirectory
{
USER_DIRECTORY_HOME,
USER_DIRECTORY_APPSUPPORT,
USER_DIRECTORY_DOCUMENTS,
USER_DIRECTORY_DESKTOP,
USER_DIRECTORY_CACHES,
};
std::string getUserDirectory(UserDirectory dir);
std::string getExecutablePath();
} // apple
} // love
#endif // defined(LOVE_IOS) || defined(LOVE_MACOS)
+76
View File
@@ -0,0 +1,76 @@
/**
* Copyright (c) 2006-2020 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "apple.h"
#if defined(LOVE_IOS) || defined(LOVE_MACOS)
#import <Foundation/Foundation.h>
namespace love
{
namespace apple
{
std::string getUserDirectory(UserDirectory dir)
{
std::string path;
NSSearchPathDirectory nsdir = NSTrashDirectory;
@autoreleasepool
{
switch (dir)
{
case USER_DIRECTORY_HOME:
return NSHomeDirectory().UTF8String;
case USER_DIRECTORY_APPSUPPORT:
nsdir = NSApplicationSupportDirectory;
break;
case USER_DIRECTORY_DOCUMENTS:
nsdir = NSDocumentDirectory;
break;
case USER_DIRECTORY_DESKTOP:
nsdir = NSDesktopDirectory;
break;
case USER_DIRECTORY_CACHES:
nsdir = NSCachesDirectory;
break;
}
NSArray<NSURL *> *dirs = [[NSFileManager defaultManager] URLsForDirectory:nsdir inDomains:NSUserDomainMask];
if (dirs.count > 0)
path = [dirs[0].path UTF8String];
}
return path;
}
std::string getExecutablePath()
{
@autoreleasepool
{
return std::string([NSBundle mainBundle].executablePath.UTF8String);
}
}
} // apple
} // love
#endif // defined(LOVE_IOS) || defined(LOVE_MACOS)
-15
View File
@@ -42,27 +42,12 @@ namespace ios
**/ **/
std::string getLoveInResources(bool &fused); std::string getLoveInResources(bool &fused);
/**
* Gets the directory path where files should be stored.
**/
std::string getAppdataDirectory();
/**
* Get the home directory (on iOS, this really means the app's sandbox dir.)
**/
std::string getHomeDirectory();
/** /**
* Opens the specified URL with the default program associated with the URL's * Opens the specified URL with the default program associated with the URL's
* scheme. * scheme.
**/ **/
bool openURL(const std::string &url); bool openURL(const std::string &url);
/**
* Returns the full path to the executable.
**/
std::string getExecutablePath();
/** /**
* Causes devices with vibration support to vibrate for about 0.5 seconds. * Causes devices with vibration support to vibrate for about 0.5 seconds.
**/ **/
+1 -46
View File
@@ -19,6 +19,7 @@
**/ **/
#include "ios.h" #include "ios.h"
#include "apple.h"
#ifdef LOVE_IOS #ifdef LOVE_IOS
@@ -125,12 +126,6 @@ static bool deleteFileInDocuments(NSString *filename);
@end @end
static NSString *getDocumentsDirectory()
{
NSArray *docdirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return docdirs[0];
}
static NSArray *getLovesInDocuments() static NSArray *getLovesInDocuments()
{ {
NSMutableArray *paths = [NSMutableArray new]; NSMutableArray *paths = [NSMutableArray new];
@@ -287,38 +282,6 @@ std::string getLoveInResources(bool &fused)
return path; return path;
} }
static std::string getUserDirectory(NSSearchPathDirectory dir)
{
std::string path;
@autoreleasepool
{
NSArray<NSURL *> *dirs = [[NSFileManager defaultManager] URLsForDirectory:dir inDomains:NSUserDomainMask];
if (dirs.count > 0)
path = [dirs[0].path UTF8String];
}
return path;
}
std::string getAppdataDirectory()
{
return getUserDirectory(NSApplicationSupportDirectory);
}
std::string getHomeDirectory()
{
std::string path;
@autoreleasepool
{
path = [NSHomeDirectory() UTF8String];
}
return path;
}
bool openURL(const std::string &url) bool openURL(const std::string &url)
{ {
bool success = false; bool success = false;
@@ -335,14 +298,6 @@ bool openURL(const std::string &url)
return success; return success;
} }
std::string getExecutablePath()
{
@autoreleasepool
{
return std::string([NSBundle mainBundle].executablePath.UTF8String);
}
}
void vibrate() void vibrate()
{ {
@autoreleasepool @autoreleasepool
-7
View File
@@ -31,8 +31,6 @@ namespace love
namespace macos namespace macos
{ {
std::string getAppdataDirectory();
/** /**
* Returns the filepath of the first detected love file in the Resources folder * Returns the filepath of the first detected love file in the Resources folder
* in the main bundle (love.app.) * in the main bundle (love.app.)
@@ -46,11 +44,6 @@ std::string getLoveInResources();
**/ **/
std::string checkDropEvents(); std::string checkDropEvents();
/**
* Returns the full path to the executable.
**/
std::string getExecutablePath();
/** /**
* Bounce the dock icon, if the app isn't in the foreground. * Bounce the dock icon, if the app isn't in the foreground.
**/ **/
-28
View File
@@ -36,26 +36,6 @@ namespace love
namespace macos namespace macos
{ {
static std::string getUserDirectory(NSSearchPathDirectory dir)
{
std::string path;
@autoreleasepool
{
NSArray<NSURL *> *dirs = [[NSFileManager defaultManager] URLsForDirectory:dir inDomains:NSUserDomainMask];
if (dirs.count > 0)
path = [dirs[0].path UTF8String];
}
return path;
}
std::string getAppdataDirectory()
{
return getUserDirectory(NSApplicationSupportDirectory);
}
std::string getLoveInResources() std::string getLoveInResources()
{ {
std::string path; std::string path;
@@ -94,14 +74,6 @@ std::string checkDropEvents()
return dropstr; return dropstr;
} }
std::string getExecutablePath()
{
@autoreleasepool
{
return std::string([NSBundle mainBundle].executablePath.UTF8String);
}
}
void requestAttention(bool continuous) void requestAttention(bool continuous)
{ {
@autoreleasepool @autoreleasepool
+23 -24
View File
@@ -26,10 +26,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#if defined(LOVE_MACOS) #if defined(LOVE_MACOS) || defined(LOVE_IOS)
#include "common/macos.h" #include "common/apple.h"
#elif defined(LOVE_IOS)
#include "common/ios.h"
#elif defined(LOVE_WINDOWS) #elif defined(LOVE_WINDOWS)
#include <windows.h> #include <windows.h>
#include "common/utf8.h" #include "common/utf8.h"
@@ -92,10 +90,8 @@ bool Filesystem::isRealDirectory(const std::string &path) const
std::string Filesystem::getExecutablePath() const std::string Filesystem::getExecutablePath() const
{ {
#if defined(LOVE_MACOS) #if defined(LOVE_MACOS) || defined(LOVE_IOS)
return love::macos::getExecutablePath(); return love::apple::getExecutablePath();
#elif defined(LOVE_IOS)
return love::ios::getExecutablePath();
#elif defined(LOVE_WINDOWS) #elif defined(LOVE_WINDOWS)
wchar_t buffer[MAX_PATH + 1] = {0}; wchar_t buffer[MAX_PATH + 1] = {0};
@@ -120,30 +116,33 @@ std::string Filesystem::getExecutablePath() const
#endif #endif
} }
bool Filesystem::getConstant(const char *in, FileType &out) STRINGMAP_CLASS_BEGIN(Filesystem, Filesystem::FileType, Filesystem::FILETYPE_MAX_ENUM, fileType)
{ {
return fileTypes.find(in, out); { "file", Filesystem::FILETYPE_FILE },
{ "directory", Filesystem::FILETYPE_DIRECTORY },
{ "symlink", Filesystem::FILETYPE_SYMLINK },
{ "other", Filesystem::FILETYPE_OTHER },
} }
STRINGMAP_CLASS_END(Filesystem, Filesystem::FileType, Filesystem::FILETYPE_MAX_ENUM, fileType)
bool Filesystem::getConstant(FileType in, const char *&out) STRINGMAP_CLASS_BEGIN(Filesystem, Filesystem::CommonPath, Filesystem::COMMONPATH_MAX_ENUM, commonPath)
{ {
return fileTypes.find(in, out); { "appidentity", Filesystem::COMMONPATH_APP_IDENTITY },
{ "appdocuments", Filesystem::COMMONPATH_APP_DOCUMENTS },
{ "apptemp", Filesystem::COMMONPATH_APP_TEMP },
{ "userhome", Filesystem::COMMONPATH_USER_HOME },
{ "userappdata", Filesystem::COMMONPATH_USER_APPDATA },
{ "userdesktop", Filesystem::COMMONPATH_USER_DESKTOP },
{ "userdocuments", Filesystem::COMMONPATH_USER_DOCUMENTS },
} }
STRINGMAP_CLASS_END(Filesystem, Filesystem::CommonPath, Filesystem::COMMONPATH_MAX_ENUM, commonPath)
std::vector<std::string> Filesystem::getConstants(FileType) STRINGMAP_CLASS_BEGIN(Filesystem, Filesystem::MountPermissions, Filesystem::MOUNT_PERMISSIONS_MAX_ENUM, mountPermissions)
{ {
return fileTypes.getNames(); { "read", Filesystem::MOUNT_PERMISSIONS_READ },
{ "readwrite", Filesystem::MOUNT_PERMISSIONS_READWRITE },
} }
STRINGMAP_CLASS_END(Filesystem, Filesystem::MountPermissions, Filesystem::MOUNT_PERMISSIONS_MAX_ENUM, mountPermissions)
StringMap<Filesystem::FileType, Filesystem::FILETYPE_MAX_ENUM>::Entry Filesystem::fileTypeEntries[] =
{
{ "file", FILETYPE_FILE },
{ "directory", FILETYPE_DIRECTORY },
{ "symlink", FILETYPE_SYMLINK },
{ "other", FILETYPE_OTHER },
};
StringMap<Filesystem::FileType, Filesystem::FILETYPE_MAX_ENUM> Filesystem::fileTypes(Filesystem::fileTypeEntries, sizeof(Filesystem::fileTypeEntries));
} // filesystem } // filesystem
} // love } // love
+29 -6
View File
@@ -71,6 +71,25 @@ public:
FILETYPE_MAX_ENUM FILETYPE_MAX_ENUM
}; };
enum CommonPath
{
COMMONPATH_APP_IDENTITY,
COMMONPATH_APP_DOCUMENTS,
COMMONPATH_APP_TEMP,
COMMONPATH_USER_HOME,
COMMONPATH_USER_APPDATA,
COMMONPATH_USER_DESKTOP,
COMMONPATH_USER_DOCUMENTS,
COMMONPATH_MAX_ENUM
};
enum MountPermissions
{
MOUNT_PERMISSIONS_READ,
MOUNT_PERMISSIONS_READWRITE,
MOUNT_PERMISSIONS_MAX_ENUM
};
struct Info struct Info
{ {
// Numbers will be -1 if they cannot be determined. // Numbers will be -1 if they cannot be determined.
@@ -136,8 +155,13 @@ public:
virtual bool mount(const char *archive, const char *mountpoint, bool appendToPath = false) = 0; virtual bool mount(const char *archive, const char *mountpoint, bool appendToPath = false) = 0;
virtual bool mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath = false) = 0; virtual bool mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath = false) = 0;
virtual bool mountFullPath(const char *archive, const char *mountpoint, MountPermissions permissions, bool appendToPath = false) = 0;
virtual bool mountCommonPath(CommonPath path, const char *mountpoint, MountPermissions permissions, bool appendToPath = false) = 0;
virtual bool unmount(const char *archive) = 0; virtual bool unmount(const char *archive) = 0;
virtual bool unmount(Data *data) = 0; virtual bool unmount(Data *data) = 0;
virtual bool unmount(CommonPath path) = 0;
/** /**
* Creates a new file. * Creates a new file.
@@ -152,6 +176,8 @@ public:
**/ **/
virtual FileData *newFileData(const void *data, size_t size, const char *filename) const; virtual FileData *newFileData(const void *data, size_t size, const char *filename) const;
virtual std::string getFullCommonPath(CommonPath path) = 0;
/** /**
* Gets the current working directory. * Gets the current working directory.
**/ **/
@@ -263,18 +289,15 @@ public:
**/ **/
virtual std::string getExecutablePath() const; virtual std::string getExecutablePath() const;
static bool getConstant(const char *in, FileType &out); STRINGMAP_CLASS_DECLARE(FileType);
static bool getConstant(FileType in, const char *&out); STRINGMAP_CLASS_DECLARE(CommonPath);
static std::vector<std::string> getConstants(FileType); STRINGMAP_CLASS_DECLARE(MountPermissions);
private: private:
// Should we save external or internal for Android // Should we save external or internal for Android
bool useExternal; bool useExternal;
static StringMap<FileType, FILETYPE_MAX_ENUM>::Entry fileTypeEntries[];
static StringMap<FileType, FILETYPE_MAX_ENUM> fileTypes;
}; // Filesystem }; // Filesystem
} // filesystem } // filesystem
+217 -82
View File
@@ -45,6 +45,10 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#if defined(LOVE_IOS) || defined(LOVE_MACOS)
# include "common/apple.h"
#endif
#ifdef LOVE_IOS #ifdef LOVE_IOS
# include "common/ios.h" # include "common/ios.h"
#endif #endif
@@ -60,44 +64,6 @@
#include "common/android.h" #include "common/android.h"
#endif #endif
namespace
{
size_t getDriveDelim(const std::string &input)
{
for (size_t i = 0; i < input.size(); ++i)
if (input[i] == '/' || input[i] == '\\')
return i;
// Something's horribly wrong
return 0;
}
std::string getDriveRoot(const std::string &input)
{
return input.substr(0, getDriveDelim(input)+1);
}
std::string skipDriveRoot(const std::string &input)
{
return input.substr(getDriveDelim(input)+1);
}
std::string normalize(const std::string &input)
{
std::stringstream out;
bool seenSep = false, isSep = false;
for (size_t i = 0; i < input.size(); ++i)
{
isSep = (input[i] == LOVE_PATH_SEPARATOR[0]);
if (!isSep || !seenSep)
out << input[i];
seenSep = isSep;
}
return out.str();
}
}
namespace love namespace love
{ {
namespace filesystem namespace filesystem
@@ -105,6 +71,53 @@ namespace filesystem
namespace physfs namespace physfs
{ {
static size_t getDriveDelim(const std::string &input)
{
for (size_t i = 0; i < input.size(); ++i)
if (input[i] == '/' || input[i] == '\\')
return i;
// Something's horribly wrong
return 0;
}
static std::string getDriveRoot(const std::string &input)
{
return input.substr(0, getDriveDelim(input)+1);
}
static std::string skipDriveRoot(const std::string &input)
{
return input.substr(getDriveDelim(input)+1);
}
static std::string normalize(const std::string &input)
{
std::stringstream out;
bool seenSep = false, isSep = false;
for (size_t i = 0; i < input.size(); ++i)
{
isSep = (input[i] == LOVE_PATH_SEPARATOR[0]);
if (!isSep || !seenSep)
out << input[i];
seenSep = isSep;
}
return out.str();
}
static bool isAppCommonPath(Filesystem::CommonPath path)
{
switch (path)
{
case Filesystem::COMMONPATH_APP_IDENTITY:
case Filesystem::COMMONPATH_APP_DOCUMENTS:
case Filesystem::COMMONPATH_APP_TEMP:
return true;
default:
return false;
}
}
Filesystem::Filesystem() Filesystem::Filesystem()
: fused(false) : fused(false)
, fusedSet(false) , fusedSet(false)
@@ -159,15 +172,13 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath)
save_identity = std::string(ident); save_identity = std::string(ident);
// Generate the relative path to the game save folder. // Generate the relative path to the game save folder.
save_path_relative = std::string(LOVE_APPDATA_PREFIX LOVE_APPDATA_FOLDER LOVE_PATH_SEPARATOR) + save_identity; if (fused)
save_path_relative = std::string(LOVE_APPDATA_PREFIX) + save_identity;
else
save_path_relative = std::string(LOVE_APPDATA_PREFIX LOVE_APPDATA_FOLDER LOVE_PATH_SEPARATOR) + save_identity;
// Generate the full path to the game save folder. // Generate the full path to the game save folder.
save_path_full = std::string(getAppdataDirectory()) + std::string(LOVE_PATH_SEPARATOR); save_path_full = std::string(getAppdataDirectory()) + std::string(LOVE_PATH_SEPARATOR) + save_path_relative;
if (fused)
save_path_full += std::string(LOVE_APPDATA_PREFIX) + save_identity;
else
save_path_full += save_path_relative;
save_path_full = normalize(save_path_full); save_path_full = normalize(save_path_full);
#ifdef LOVE_ANDROID #ifdef LOVE_ANDROID
@@ -370,10 +381,35 @@ bool Filesystem::mount(const char *archive, const char *mountpoint, bool appendT
realPath += archive; realPath += archive;
} }
if (realPath.length() == 0) return mountFullPath(realPath.c_str(), mountpoint, MOUNT_PERMISSIONS_READ, appendToPath);
}
bool Filesystem::mountFullPath(const char *archive, const char *mountpoint, MountPermissions permissions, bool appendToPath)
{
if (!PHYSFS_isInit() || !archive || !mountpoint)
return false; return false;
return PHYSFS_mount(realPath.c_str(), mountpoint, appendToPath) != 0; if (permissions == MOUNT_PERMISSIONS_READWRITE && strlen(mountpoint) == 0)
return false;
// TODO: readwrite mount
return PHYSFS_mount(archive, mountpoint, appendToPath) != 0;
}
bool Filesystem::mountCommonPath(CommonPath path, const char *mountpoint, MountPermissions permissions, bool appendToPath)
{
std::string fullpath = getFullCommonPath(path);
if (fullpath.empty())
return false;
bool success = mountFullPath(fullpath.c_str(), mountpoint, permissions, appendToPath);
if (!success && isAppCommonPath(path))
{
}
return success;
} }
bool Filesystem::mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath) bool Filesystem::mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath)
@@ -403,42 +439,35 @@ bool Filesystem::unmount(const char *archive)
return true; return true;
} }
std::string realPath; if (PHYSFS_getRealDir(archive) != nullptr)
std::string sourceBase = getSourceBaseDirectory(); return PHYSFS_unmount(archive) != 0;
// Check whether the given archive path is in the list of allowed full paths. if (strlen(archive) == 0 || strstr(archive, "..") || strcmp(archive, "/") == 0)
auto it = std::find(allowedMountPaths.begin(), allowedMountPaths.end(), archive); return false;
if (it != allowedMountPaths.end()) const char *realDir = PHYSFS_getRealDir(archive);
realPath = *it; if (!realDir)
else if (isFused() && sourceBase.compare(archive) == 0) return false;
{
// 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;
const char *realDir = PHYSFS_getRealDir(archive); std::string realPath = realDir;
if (!realDir) realPath += LOVE_PATH_SEPARATOR;
return false; realPath += archive;
realPath = realDir; if (PHYSFS_getMountPoint(realPath.c_str()) == nullptr)
realPath += LOVE_PATH_SEPARATOR;
realPath += archive;
}
const char *mountPoint = PHYSFS_getMountPoint(realPath.c_str());
if (!mountPoint)
return false; return false;
return PHYSFS_unmount(realPath.c_str()) != 0; return PHYSFS_unmount(realPath.c_str()) != 0;
} }
bool Filesystem::unmount(CommonPath path)
{
std::string fullpath = getFullCommonPath(path);
if (fullpath.empty())
return false;
return unmount(fullpath.c_str());
}
bool Filesystem::unmount(Data *data) bool Filesystem::unmount(Data *data)
{ {
for (const auto &datapair : mountedData) for (const auto &datapair : mountedData)
@@ -458,6 +487,115 @@ love::filesystem::File *Filesystem::newFile(const char *filename) const
return new File(filename); return new File(filename);
} }
std::string Filesystem::getFullCommonPath(CommonPath path)
{
if (!fullCommonPaths[path].empty())
return fullCommonPaths[path];
if (path == COMMONPATH_APP_IDENTITY || path == COMMONPATH_APP_DOCUMENTS || path == COMMONPATH_APP_TEMP)
{
}
#if defined(LOVE_MACOS) || defined(LOVE_IOS)
switch (path)
{
case COMMONPATH_APP_IDENTITY:
case COMMONPATH_APP_DOCUMENTS:
case COMMONPATH_APP_TEMP:
// Handled above.
break;
case COMMONPATH_USER_HOME:
fullCommonPaths[path] = apple::getUserDirectory(apple::USER_DIRECTORY_HOME);
break;
case COMMONPATH_USER_APPDATA:
fullCommonPaths[path] = apple::getUserDirectory(apple::USER_DIRECTORY_APPSUPPORT);
break;
case COMMONPATH_USER_DESKTOP:
fullCommonPaths[path] = apple::getUserDirectory(apple::USER_DIRECTORY_DESKTOP);
break;
case COMMONPATH_USER_DOCUMENTS:
fullCommonPaths[path] = apple::getUserDirectory(apple::USER_DIRECTORY_DOCUMENTS);
break;
case COMMONPATH_MAX_ENUM:
break;
}
#elif defined(LOVE_WINDOWS)
PWSTR winpath = nullptr;
HRESULT hr = E_FAIL;
switch (path)
{
case COMMONPATH_APP_IDENTITY:
case COMMONPATH_APP_DOCUMENTS:
case COMMONPATH_APP_TEMP:
// Handled above.
break;
case COMMONPATH_USER_HOME:
hr = SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, &winpath);
break;
case COMMONPATH_USER_APPDATA:
hr = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &winpath);
break;
case COMMONPATH_USER_DESKTOP:
hr = SHGetKnownFolderPath(FOLDERID_Desktop, 0, nullptr, &winpath);
break;
case COMMONPATH_USER_DOCUMENTS:
hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, nullptr, &winpath);
break;
case COMMONPATH_MAX_ENUM:
break;
}
if (SUCCEEDED(hr))
{
fullCommonPaths[path] = to_utf8(winpath);
CoTaskMemFree(winpath);
}
else
{
}
#elif defined(LOVE_ANDROID)
#elif defined(LOVE_LINUX)
const char *xdgdir = nullptr;
switch (path)
{
case COMMONPATH_APP_IDENTITY:
case COMMONPATH_APP_DOCUMENTS:
case COMMONPATH_APP_TEMP:
// Handled above.
break;
case COMMONPATH_USER_HOME:
fullCommonPaths[path] = normalize(PHYSFS_getUserDir());
break;
case COMMONPATH_USER_APPDATA:
xdgdir = getenv("XDG_DATA_HOME");
if (!xdgdir)
fullCommonPaths[path] = normalize(std::string(getUserDirectory()) + "/.local/share/");
else
fullCommonPaths[path] = xdgdir;
break;
case COMMONPATH_USER_DESKTOP:
break;
case COMMONPATH_USER_DOCUMENTS:
break;
case COMMONPATH_MAX_ENUM:
break;
}
#endif
return fullCommonPaths[path];
}
const char *Filesystem::getWorkingDirectory() const char *Filesystem::getWorkingDirectory()
{ {
if (cwd.empty()) if (cwd.empty())
@@ -474,7 +612,7 @@ const char *Filesystem::getWorkingDirectory()
if (getcwd(cwd_char, LOVE_MAX_PATH)) if (getcwd(cwd_char, LOVE_MAX_PATH))
cwd = cwd_char; // if getcwd fails, cwd_char (and thus cwd) will still be empty cwd = cwd_char; // if getcwd fails, cwd_char (and thus cwd) will still be empty
delete [] cwd_char; delete[] cwd_char;
#endif #endif
} }
@@ -483,9 +621,9 @@ const char *Filesystem::getWorkingDirectory()
std::string Filesystem::getUserDirectory() std::string Filesystem::getUserDirectory()
{ {
#ifdef LOVE_IOS #if defined(LOVE_IOS) || defined(LOVE_MACOS)
// PHYSFS_getUserDir doesn't give exactly the path we want on iOS. // PHYSFS_getUserDir doesn't give exactly the path we want on iOS.
static std::string userDir = normalize(love::ios::getHomeDirectory()); static std::string userDir = normalize(apple::getUserDirectory(apple::USER_DIRECTORY_HOME));
#else #else
static std::string userDir = normalize(PHYSFS_getUserDir()); static std::string userDir = normalize(PHYSFS_getUserDir());
#endif #endif
@@ -512,10 +650,8 @@ std::string Filesystem::getAppdataDirectory()
appdata = to_utf8(w_appdata); appdata = to_utf8(w_appdata);
} }
replace_char(appdata, '\\', '/'); replace_char(appdata, '\\', '/');
#elif defined(LOVE_MACOS) #elif defined(LOVE_MACOS) || defined(LOVE_IOS)
appdata = normalize(love::macos::getAppdataDirectory()); appdata = normalize(apple::getUserDirectory(apple::USER_DIRECTORY_APPSUPPORT));
#elif defined(LOVE_IOS)
appdata = normalize(love::ios::getAppdataDirectory());
#elif defined(LOVE_LINUX) #elif defined(LOVE_LINUX)
char *xdgdatahome = getenv("XDG_DATA_HOME"); char *xdgdatahome = getenv("XDG_DATA_HOME");
if (!xdgdatahome) if (!xdgdatahome)
@@ -529,7 +665,6 @@ std::string Filesystem::getAppdataDirectory()
return appdata; return appdata;
} }
const char *Filesystem::getSaveDirectory() const char *Filesystem::getSaveDirectory()
{ {
return save_path_full.c_str(); return save_path_full.c_str();
@@ -63,11 +63,16 @@ public:
bool mount(const char *archive, const char *mountpoint, bool appendToPath = false) override; bool mount(const char *archive, const char *mountpoint, bool appendToPath = false) override;
bool mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath = false) override; bool mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath = false) override;
bool mountFullPath(const char *archive, const char *mountpoint, MountPermissions permissions, bool appendToPath = false) override;
bool mountCommonPath(CommonPath path, const char *mountpoint, MountPermissions permissions, bool appendToPath = false) override;
bool unmount(const char *archive) override; bool unmount(const char *archive) override;
bool unmount(Data *data) override; bool unmount(Data *data) override;
bool unmount(CommonPath path) override;
love::filesystem::File *newFile(const char *filename) const override; love::filesystem::File *newFile(const char *filename) const override;
std::string getFullCommonPath(CommonPath path) override;
const char *getWorkingDirectory() override; const char *getWorkingDirectory() override;
std::string getUserDirectory() override; std::string getUserDirectory() override;
std::string getAppdataDirectory() override; std::string getAppdataDirectory() override;
@@ -129,6 +134,8 @@ private:
std::map<std::string, StrongRef<Data>> mountedData; std::map<std::string, StrongRef<Data>> mountedData;
std::string fullCommonPaths[COMMONPATH_MAX_ENUM];
}; // Filesystem }; // Filesystem
} // physfs } // physfs
@@ -148,6 +148,48 @@ int w_mount(lua_State *L)
return 1; return 1;
} }
int w_mountFullPath(lua_State *L)
{
const char *fullpath = luaL_checkstring(L, 1);
const char *mountpoint = luaL_checkstring(L, 2);
auto permissions = Filesystem::MOUNT_PERMISSIONS_READ;
if (!lua_isnoneornil(L, 3))
{
const char *permissionstr = luaL_checkstring(L, 3);
if (!Filesystem::getConstant(permissionstr, permissions))
return luax_enumerror(L, "mount permissions", Filesystem::getConstants(permissions), permissionstr);
}
bool append = luax_optboolean(L, 4, false);
luax_pushboolean(L, instance()->mountFullPath(fullpath, mountpoint, permissions, append));
return 1;
}
int w_mountCommonPath(lua_State *L)
{
const char *commonpathstr = luaL_checkstring(L, 1);
Filesystem::CommonPath commonpath;
if (!Filesystem::getConstant(commonpathstr, commonpath))
return luax_enumerror(L, "common path", Filesystem::getConstants(commonpath), commonpathstr);
const char *mountpoint = luaL_checkstring(L, 2);
auto permissions = Filesystem::MOUNT_PERMISSIONS_READ;
if (!lua_isnoneornil(L, 3))
{
const char *permissionstr = luaL_checkstring(L, 3);
if (!Filesystem::getConstant(permissionstr, permissions))
return luax_enumerror(L, "mount permissions", Filesystem::getConstants(permissions), permissionstr);
}
bool append = luax_optboolean(L, 4, false);
luax_pushboolean(L, instance()->mountCommonPath(commonpath, mountpoint, permissions, append));
return 1;
}
int w_unmount(lua_State *L) int w_unmount(lua_State *L)
{ {
if (luax_istype(L, 1, Data::type)) if (luax_istype(L, 1, Data::type))
@@ -163,6 +205,17 @@ int w_unmount(lua_State *L)
return 1; return 1;
} }
int w_unmountCommonPath(lua_State *L)
{
const char *commonpathstr = luaL_checkstring(L, 1);
Filesystem::CommonPath commonpath;
if (!Filesystem::getConstant(commonpathstr, commonpath))
return luax_enumerror(L, "common path", Filesystem::getConstants(commonpath), commonpathstr);
luax_pushboolean(L, instance()->unmount(commonpath));
return 1;
}
int w_newFile(lua_State *L) int w_newFile(lua_State *L)
{ {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
@@ -331,6 +384,17 @@ int w_newFileData(lua_State *L)
return 1; return 1;
} }
int w_getFullCommonPath(lua_State *L)
{
const char *commonpathstr = luaL_checkstring(L, 1);
Filesystem::CommonPath commonpath;
if (!Filesystem::getConstant(commonpathstr, commonpath))
return luax_enumerror(L, "common path", Filesystem::getConstants(commonpath), commonpathstr);
luax_pushstring(L, instance()->getFullCommonPath(commonpath));
return 1;
}
int w_getWorkingDirectory(lua_State *L) int w_getWorkingDirectory(lua_State *L)
{ {
lua_pushstring(L, instance()->getWorkingDirectory()); lua_pushstring(L, instance()->getWorkingDirectory());
@@ -839,8 +903,12 @@ static const luaL_Reg functions[] =
{ "setSource", w_setSource }, { "setSource", w_setSource },
{ "getSource", w_getSource }, { "getSource", w_getSource },
{ "mount", w_mount }, { "mount", w_mount },
{ "mountFullPath", w_mountFullPath },
// { "mountCommonPath", w_mountCommonPath },
{ "unmount", w_unmount }, { "unmount", w_unmount },
// { "unmountCommonPath", w_unmountCommonPath },
{ "newFile", w_newFile }, { "newFile", w_newFile },
// { "getFullCommonPath", w_getFullCommonPath },
{ "getWorkingDirectory", w_getWorkingDirectory }, { "getWorkingDirectory", w_getWorkingDirectory },
{ "getUserDirectory", w_getUserDirectory }, { "getUserDirectory", w_getUserDirectory },
{ "getAppdataDirectory", w_getAppdataDirectory }, { "getAppdataDirectory", w_getAppdataDirectory },