From 811b2db466d7090d4444662052ae1746db3faa0b Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 4 May 2015 10:38:28 -0300 Subject: [PATCH] The full executable path, rather than argv[0], is now used when determining whether the executable is fused (resolves issue #1043.) --- src/common/OSX.h | 5 +++ src/common/OSX.mm | 8 ++++ src/common/iOS.h | 5 +++ src/common/iOS.mm | 13 ++++++- src/modules/filesystem/DroppedFile.cpp | 8 +++- src/modules/filesystem/Filesystem.cpp | 45 +++++++++++++++++++++- src/modules/filesystem/Filesystem.h | 5 +++ src/modules/filesystem/wrap_Filesystem.cpp | 7 ++++ src/modules/filesystem/wrap_Filesystem.h | 1 + src/modules/system/System.cpp | 1 - src/scripts/boot.lua | 10 ++++- src/scripts/boot.lua.h | 15 +++++++- 12 files changed, 113 insertions(+), 10 deletions(-) diff --git a/src/common/OSX.h b/src/common/OSX.h index ddd7e0c84..4d40b17bd 100644 --- a/src/common/OSX.h +++ b/src/common/OSX.h @@ -45,6 +45,11 @@ std::string getLoveInResources(); **/ std::string checkDropEvents(); +/** + * Returns the full path to the executable. + **/ +std::string getExecutablePath(); + } // osx } // love diff --git a/src/common/OSX.mm b/src/common/OSX.mm index 3d7eae65f..725bdcb2a 100644 --- a/src/common/OSX.mm +++ b/src/common/OSX.mm @@ -69,6 +69,14 @@ std::string checkDropEvents() return dropstr; } +std::string getExecutablePath() +{ + @autoreleasepool + { + return std::string([NSBundle mainBundle].executablePath.UTF8String); + } +} + } // osx } // love diff --git a/src/common/iOS.h b/src/common/iOS.h index 49bfa4162..84c1e2717 100644 --- a/src/common/iOS.h +++ b/src/common/iOS.h @@ -54,6 +54,11 @@ std::string getHomeDirectory(); **/ bool openURL(const std::string &url); +/** + * Returns the full path to the executable. + **/ +std::string getExecutablePath(); + } // ios } // love diff --git a/src/common/iOS.mm b/src/common/iOS.mm index e626be9df..c61db3526 100644 --- a/src/common/iOS.mm +++ b/src/common/iOS.mm @@ -305,15 +305,24 @@ bool openURL(const std::string &url) @autoreleasepool { + UIApplication *app = [UIApplication sharedApplication]; NSURL *nsurl = [NSURL URLWithString:@(url.c_str())]; - if ([[UIApplication sharedApplication] canOpenURL:nsurl]) - success = [[UIApplication sharedApplication] openURL:nsurl]; + if ([app canOpenURL:nsurl]) + success = [app openURL:nsurl]; } return success; } +std::string getExecutablePath() +{ + @autoreleasepool + { + return std::string([NSBundle mainBundle].executablePath.UTF8String); + } +} + } // ios } // love diff --git a/src/modules/filesystem/DroppedFile.cpp b/src/modules/filesystem/DroppedFile.cpp index 38c92f507..c3e59e4a4 100644 --- a/src/modules/filesystem/DroppedFile.cpp +++ b/src/modules/filesystem/DroppedFile.cpp @@ -64,7 +64,9 @@ bool DroppedFile::open(Mode newmode) #ifdef LOVE_WINDOWS // make sure non-ASCII filenames work. std::wstring modestr = to_widestr(getModeString(newmode)); - file = _wfopen(to_widestr(filename).c_str(), modestr.c_str()); + std::wstring wfilename = to_widestr(filename); + + file = _wfopen(wfilename.c_str(), modestr.c_str()); #else file = fopen(filename.c_str(), getModeString(newmode)); #endif @@ -105,8 +107,10 @@ int64 DroppedFile::getSize() #ifdef LOVE_WINDOWS // make sure non-ASCII filenames work. + std::wstring wfilename = to_widestr(filename); + struct _stat buf; - if (_wstat(to_widestr(filename).c_str(), &buf) != 0) + if (_wstat(wfilename.c_str(), &buf) != 0) return -1; return (int64) buf.st_size; diff --git a/src/modules/filesystem/Filesystem.cpp b/src/modules/filesystem/Filesystem.cpp index b2dc8d147..a9975b549 100644 --- a/src/modules/filesystem/Filesystem.cpp +++ b/src/modules/filesystem/Filesystem.cpp @@ -26,6 +26,17 @@ #include #include +#if defined(LOVE_MACOSX) +#include "common/OSX.h" +#elif defined(LOVE_IOS) +#include "common/iOS.h" +#elif defined(LOVE_WINDOWS) +#include +#include "common/utf8.h" +#elif defined(LOVE_LINUX) +#include +#endif + namespace love { namespace filesystem @@ -43,8 +54,10 @@ bool Filesystem::isRealDirectory(const std::string &path) const { #ifdef LOVE_WINDOWS // make sure non-ASCII paths work. + std::wstring wpath = to_widestr(path); + struct _stat buf; - if (_wstat(to_widestr(path).c_str(), &buf) != 0) + if (_wstat(wpath.c_str(), &buf) != 0) return false; return (buf.st_mode & _S_IFDIR) == _S_IFDIR; @@ -58,5 +71,35 @@ bool Filesystem::isRealDirectory(const std::string &path) const #endif } +std::string Filesystem::getExecutablePath() const +{ +#if defined(LOVE_MACOSX) + return love::osx::getExecutablePath(); +#elif defined(LOVE_IOS) + return love::ios::getExecutablePath(); +#elif defined(LOVE_WINDOWS) + + wchar_t buffer[MAX_PATH + 1] = {0}; + + if (GetModuleFileNameW(nullptr, buffer, MAX_PATH) == 0) + return ""; + + return to_utf8(buffer); + +#elif defined(LOVE_LINUX) + + char buffer[2048] = {0}; + + ssize_t len = readlink("/proc/self/exe", buffer, 2048); + if (len <= 0) + return ""; + + return std::string(buffer, len); + +#else +#error Missing implementation for Filesystem::getExecutablePath! +#endif +} + } // filesystem } // love diff --git a/src/modules/filesystem/Filesystem.h b/src/modules/filesystem/Filesystem.h index b49b549c1..257c456af 100644 --- a/src/modules/filesystem/Filesystem.h +++ b/src/modules/filesystem/Filesystem.h @@ -252,6 +252,11 @@ public: **/ virtual bool isRealDirectory(const std::string &path) const; + /** + * Gets the full platform-dependent path to the executable. + **/ + virtual std::string getExecutablePath() const; + }; // Filesystem } // filesystem diff --git a/src/modules/filesystem/wrap_Filesystem.cpp b/src/modules/filesystem/wrap_Filesystem.cpp index 6424979db..cceb6ce89 100644 --- a/src/modules/filesystem/wrap_Filesystem.cpp +++ b/src/modules/filesystem/wrap_Filesystem.cpp @@ -301,6 +301,12 @@ int w_getRealDirectory(lua_State *L) return 1; } +int w_getExecutablePath(lua_State *L) +{ + luax_pushstring(L, instance()->getExecutablePath()); + return 1; +} + int w_isDirectory(lua_State *L) { const char *arg = luaL_checkstring(L, 1); @@ -699,6 +705,7 @@ static const luaL_Reg functions[] = { "getSaveDirectory", w_getSaveDirectory }, { "getSourceBaseDirectory", w_getSourceBaseDirectory }, { "getRealDirectory", w_getRealDirectory }, + { "getExecutablePath", w_getExecutablePath }, { "isDirectory", w_isDirectory }, { "isFile", w_isFile }, { "createDirectory", w_createDirectory }, diff --git a/src/modules/filesystem/wrap_Filesystem.h b/src/modules/filesystem/wrap_Filesystem.h index d89455fb2..b1db58145 100644 --- a/src/modules/filesystem/wrap_Filesystem.h +++ b/src/modules/filesystem/wrap_Filesystem.h @@ -57,6 +57,7 @@ int w_getAppdataDirectory(lua_State *L); int w_getSaveDirectory(lua_State *L); int w_getSourceBaseDirectory(lua_State *L); int w_getRealDirectory(lua_State *L); +int w_getExecutablePath(lua_State *L); int w_isDirectory(lua_State *L); int w_isFile(lua_State *L); int w_createDirectory(lua_State *L); diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp index 3b07640aa..27f643b35 100755 --- a/src/modules/system/System.cpp +++ b/src/modules/system/System.cpp @@ -84,7 +84,6 @@ bool System::openURL(const std::string &url) const #if defined(LOVE_MACOSX) bool success = false; - // We could be lazy and use system("open " + url), but this is safer. CFURLRef cfurl = CFURLCreateWithBytes(nullptr, (const UInt8 *) url.c_str(), url.length(), diff --git a/src/scripts/boot.lua b/src/scripts/boot.lua index 812df720a..dc6a8fba7 100644 --- a/src/scripts/boot.lua +++ b/src/scripts/boot.lua @@ -271,8 +271,14 @@ function love.boot() local arg0 = love.arg.getLow(arg) love.filesystem.init(arg0) + local exepath = love.filesystem.getExecutablePath() + if #exepath == 0 then + -- This shouldn't happen, but just in case we'll fall back to arg0. + exepath = arg0 + end + -- Is this one of those fancy "fused" games? - local can_has_game = pcall(love.filesystem.setSource, arg0) + local can_has_game = pcall(love.filesystem.setSource, exepath) local is_fused_game = can_has_game if love.arg.options.fused.set then is_fused_game = true @@ -293,7 +299,7 @@ function love.boot() identity = love.path.leaf(full_source) else -- Use the name of the exe as the identity for now. - identity = love.path.leaf(arg0) + identity = love.path.leaf(exepath) end identity = identity:gsub("^([%.]+)", "") -- strip leading "."'s diff --git a/src/scripts/boot.lua.h b/src/scripts/boot.lua.h index 53fb1a068..d991d30dd 100644 --- a/src/scripts/boot.lua.h +++ b/src/scripts/boot.lua.h @@ -497,13 +497,24 @@ const unsigned char boot_lua[] = 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x67, 0x65, 0x74, 0x4c, 0x6f, 0x77, 0x28, 0x61, 0x72, 0x67, 0x29, 0x0a, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x28, 0x61, 0x72, 0x67, 0x30, 0x29, 0x0a, + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x6c, + 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x28, 0x29, 0x0a, + 0x09, 0x69, 0x66, 0x20, 0x23, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, + 0x74, 0x68, 0x65, 0x6e, 0x0a, + 0x09, 0x09, 0x2d, 0x2d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, + 0x74, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6a, 0x75, 0x73, 0x74, + 0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x77, 0x65, 0x27, 0x6c, 0x6c, 0x20, 0x66, 0x61, 0x6c, + 0x6c, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x30, 0x2e, 0x0a, + 0x09, 0x09, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x30, 0x0a, + 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x2d, 0x2d, 0x20, 0x49, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x20, 0x22, 0x66, 0x75, 0x73, 0x65, 0x64, 0x22, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x73, 0x3f, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x73, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2c, - 0x20, 0x61, 0x72, 0x67, 0x30, 0x29, 0x0a, + 0x20, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x29, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, @@ -548,7 +559,7 @@ const unsigned char boot_lua[] = 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x2e, 0x0a, 0x09, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, - 0x70, 0x61, 0x74, 0x68, 0x2e, 0x6c, 0x65, 0x61, 0x66, 0x28, 0x61, 0x72, 0x67, 0x30, 0x29, 0x0a, + 0x70, 0x61, 0x74, 0x68, 0x2e, 0x6c, 0x65, 0x61, 0x66, 0x28, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x29, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5e, 0x28, 0x5b, 0x25, 0x2e, 0x5d, 0x2b, 0x29, 0x22,