mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-28 07:45:22 +00:00
filesystem: Added SDL_GetExeName().
core/unix had a more-limited copy of filesystem/unix's implementation, called SDL_GetExeName(). Replace that with a real implementation in filesystem, and allow each platform to implement it as appropriate. Implemented for Unix and Windows; most implementations are currently FIXME stubs at the moment. Reference Issue #15692.
This commit is contained in:
@@ -267,6 +267,9 @@ extern "C" {
|
||||
anything calling it without an extremely good reason. */
|
||||
extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
|
||||
|
||||
// Get just the process's binary name, no path. Calculates and caches the string on first call. String lives until SDL_Quit(). This is not a public API right now!
|
||||
extern const char *SDL_GetExeName(void);
|
||||
|
||||
#ifdef HAVE_LIBC
|
||||
#define SDL_abort() abort()
|
||||
#else
|
||||
|
||||
@@ -625,4 +625,3 @@ void SDL_DebugLogBackend(const char *subsystem, const char *backend)
|
||||
{
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "SDL chose %s backend '%s'", subsystem, backend);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ typedef struct FcitxClient
|
||||
|
||||
static FcitxClient fcitx_client;
|
||||
|
||||
// !!! FIXME: should this just be dumped for src/core/unix's SDL_GetAppID()?
|
||||
static const char *GetAppName(void)
|
||||
{
|
||||
const char *exe_name = SDL_GetExeName();
|
||||
|
||||
@@ -24,39 +24,6 @@
|
||||
#include "SDL_appid.h"
|
||||
#include <unistd.h>
|
||||
|
||||
const char *SDL_GetExeName(void)
|
||||
{
|
||||
static const char *proc_name = NULL;
|
||||
|
||||
// TODO: Use a fallback if BSD has no mounted procfs (OpenBSD has no procfs at all)
|
||||
if (!proc_name) {
|
||||
#if defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_FREEBSD) || defined (SDL_PLATFORM_NETBSD) || defined(SDL_PLATFORM_HURD)
|
||||
static char linkfile[1024];
|
||||
int linksize;
|
||||
|
||||
#if defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_HURD)
|
||||
const char *proc_path = "/proc/self/exe";
|
||||
#elif defined(SDL_PLATFORM_FREEBSD)
|
||||
const char *proc_path = "/proc/curproc/file";
|
||||
#elif defined(SDL_PLATFORM_NETBSD)
|
||||
const char *proc_path = "/proc/curproc/exe";
|
||||
#endif
|
||||
linksize = readlink(proc_path, linkfile, sizeof(linkfile) - 1);
|
||||
if (linksize > 0) {
|
||||
linkfile[linksize] = '\0';
|
||||
proc_name = SDL_strrchr(linkfile, '/');
|
||||
if (proc_name) {
|
||||
++proc_name;
|
||||
} else {
|
||||
proc_name = linkfile;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return proc_name;
|
||||
}
|
||||
|
||||
const char *SDL_GetAppID(void)
|
||||
{
|
||||
const char *id_str = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING);
|
||||
@@ -79,3 +46,4 @@ const char *SDL_GetAppID(void)
|
||||
|
||||
return id_str;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ freely, subject to the following restrictions:
|
||||
#ifndef SDL_appid_h_
|
||||
#define SDL_appid_h_
|
||||
|
||||
extern const char *SDL_GetExeName(void);
|
||||
extern const char *SDL_GetAppID(void);
|
||||
|
||||
#endif // SDL_appid_h_
|
||||
|
||||
@@ -730,4 +730,42 @@ const char *WIN_CheckDefaultArgcArgv(int *pargc, char ***pargv, void **pallocate
|
||||
return NULL; // no error string.
|
||||
}
|
||||
|
||||
char *WIN_GetModulePath(HMODULE handle)
|
||||
{
|
||||
DWORD buflen = 128;
|
||||
WCHAR *path = NULL;
|
||||
DWORD len = 0;
|
||||
|
||||
while (true) {
|
||||
void *ptr = SDL_realloc(path, buflen * sizeof(WCHAR));
|
||||
if (!ptr) {
|
||||
SDL_free(path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = (WCHAR *)ptr;
|
||||
|
||||
len = GetModuleFileNameW(handle, path, buflen);
|
||||
// if it truncated, then len >= buflen - 1
|
||||
// if there was enough room (or failure), len < buflen - 1
|
||||
if (len < (buflen - 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// buffer too small? Try again.
|
||||
buflen *= 2;
|
||||
}
|
||||
|
||||
char *retval = NULL;
|
||||
if (len == 0) {
|
||||
WIN_SetError("Couldn't locate module");
|
||||
} else {
|
||||
retval = WIN_StringToUTF8W(path);
|
||||
}
|
||||
|
||||
SDL_free(path);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif // defined(SDL_PLATFORM_WINDOWS)
|
||||
|
||||
@@ -223,7 +223,10 @@ extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat);
|
||||
extern int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar);
|
||||
|
||||
// parse out command lines from OS if argv is NULL, otherwise pass through unchanged. `*pallocated` must be HeapFree'd by caller if not NULL on successful return. Returns NULL on success, error string on problems.
|
||||
const char *WIN_CheckDefaultArgcArgv(int *pargc, char ***pargv, void **pallocated);
|
||||
extern const char *WIN_CheckDefaultArgcArgv(int *pargc, char ***pargv, void **pallocated);
|
||||
|
||||
// Does all the win32 tapdancing to make GetModuleFileName work. Returns a SDL_malloc'd UTF-8 string, or NULL on failure.
|
||||
extern char *WIN_GetModulePath(HMODULE handle);
|
||||
|
||||
// Ends C function definitions when using C++
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -518,6 +518,14 @@ const char *SDL_GetUserFolder(SDL_Folder folder)
|
||||
return CachedUserFolders[idx];
|
||||
}
|
||||
|
||||
static char *CachedExeName = NULL;
|
||||
const char *SDL_GetExeName(void)
|
||||
{
|
||||
if (!CachedExeName) {
|
||||
CachedExeName = SDL_SYS_GetExeName();
|
||||
}
|
||||
return CachedExeName;
|
||||
}
|
||||
|
||||
char *SDL_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
@@ -545,10 +553,12 @@ void SDL_InitFilesystem(void)
|
||||
|
||||
void SDL_QuitFilesystem(void)
|
||||
{
|
||||
if (CachedBasePath) {
|
||||
SDL_free(CachedBasePath);
|
||||
CachedBasePath = NULL;
|
||||
}
|
||||
SDL_free(CachedBasePath);
|
||||
CachedBasePath = NULL;
|
||||
|
||||
SDL_free(CachedExeName);
|
||||
CachedExeName = NULL;
|
||||
|
||||
for (int i = 0; i < SDL_arraysize(CachedUserFolders); i++) {
|
||||
if (CachedUserFolders[i]) {
|
||||
SDL_free(CachedUserFolders[i]);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
// return a string that we can SDL_free(). It will be cached at the higher level.
|
||||
extern char *SDL_SYS_GetBasePath(void);
|
||||
extern char *SDL_SYS_GetExeName(void);
|
||||
extern char *SDL_SYS_GetPrefPath(const char *org, const char *app);
|
||||
extern char *SDL_SYS_GetUserFolder(SDL_Folder folder);
|
||||
extern char *SDL_SYS_GetCurrentDirectory(void);
|
||||
|
||||
@@ -34,6 +34,11 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return SDL_strdup("assets://");
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
return NULL; // !!! FIXME: probably just use the Linux path?
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
const char *path = SDL_GetAndroidInternalStoragePath();
|
||||
|
||||
@@ -63,6 +63,12 @@ char *SDL_SYS_GetBasePath(void)
|
||||
}
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
@@ -104,6 +104,12 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: Move most of SDL_SYS_GetBasePath to a separate function and reuse it here.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
@@ -33,6 +33,12 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
|
||||
@@ -37,6 +37,11 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return SDL_strdup("/");
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
return NULL; // no EXE name on this system.
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
#ifdef SDL_EMSCRIPTEN_PERSISTENT_PATH_STRING
|
||||
|
||||
@@ -38,6 +38,8 @@ SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
/* NOTE: This function is a UTF8 version of the Win32 SDL_GetBasePath()!
|
||||
* The GDK actually _recommends_ the 'A' functions over the 'W' functions :o
|
||||
*
|
||||
* !!! FIXME: But can we use WIN_GetModulePath anyhow? (or change WIN_GetModulePath to use GetModuleFileNameA when built for GDK?)
|
||||
*/
|
||||
DWORD buflen = 128;
|
||||
CHAR *path = NULL;
|
||||
@@ -82,6 +84,12 @@ SDL_SYS_GetBasePath(void)
|
||||
return path;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: use WIN_GetModulePath
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
XUserHandle user = NULL;
|
||||
|
||||
@@ -64,6 +64,11 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: Move most of SDL_SYS_GetBasePath to a separate function and reuse it here.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
|
||||
@@ -40,6 +40,11 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return base_path;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
return NULL; // there isn't an "exe name" on this platform.
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *pref_path = NULL;
|
||||
|
||||
@@ -30,6 +30,12 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return base_path;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: see code in NGAGE_GetAppPath
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *pref_path = NULL;
|
||||
|
||||
@@ -46,6 +46,11 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
return NULL; // no EXE name on this system.
|
||||
}
|
||||
|
||||
// Do a recursive mkdir of parents folders
|
||||
static void recursive_mkdir(const char *dir)
|
||||
{
|
||||
|
||||
@@ -46,6 +46,11 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
return NULL; // no EXE name on this system.
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
@@ -152,6 +152,12 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: see code in SDL_SYS_GetBasePath.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *canon, *dir, *result;
|
||||
|
||||
@@ -122,7 +122,7 @@ static char *search_path_for_binary(const char *bin)
|
||||
}
|
||||
#endif
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
static char *GetExePath(void)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
@@ -235,27 +235,42 @@ char *SDL_SYS_GetBasePath(void)
|
||||
/* If we had access to argv[0] here, we could check it for a path,
|
||||
or troll through $PATH looking for it, too. */
|
||||
|
||||
if (result) { // chop off filename.
|
||||
char *ptr = SDL_strrchr(result, '/');
|
||||
if (ptr) {
|
||||
*(ptr + 1) = '\0';
|
||||
} else { // shouldn't happen, but just in case...
|
||||
SDL_free(result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
// try to shrink buffer...
|
||||
char *ptr = (char *)SDL_realloc(result, SDL_strlen(result) + 1);
|
||||
if (ptr) {
|
||||
result = ptr; // oh well if it failed.
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
char *path = GetExePath();
|
||||
if (!path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *ptr = SDL_strrchr(path, '/');
|
||||
SDL_assert(ptr != NULL); // Should have been an absolute path.
|
||||
|
||||
ptr[1] = '\0'; // chop off filename, leave '/'.
|
||||
|
||||
ptr = (char *) SDL_realloc(path, ((size_t) (ptr - path)) + 2); // try to shrink this allocation down a little.
|
||||
return ptr ? ptr : path; // return shrunk buffer if shrink worked out, unchanged original buffer if not.
|
||||
}
|
||||
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
char *path = GetExePath();
|
||||
if (!path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *ptr = SDL_strrchr(path, '/');
|
||||
SDL_assert(ptr != NULL); // Should have been an absolute path.
|
||||
const size_t slen = SDL_strlen(ptr); // counts null terminator because we're still sitting on path separator.
|
||||
SDL_memmove(path, ptr + 1, slen); // move filename string to start of SDL_realloc'd region.
|
||||
ptr = (char *) SDL_realloc(path, slen); // try to shrink this allocation down a little.
|
||||
return ptr ? ptr : path; // return shrunk buffer if shrink worked out, unchanged original buffer if not.
|
||||
}
|
||||
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -41,6 +41,11 @@ char *SDL_SYS_GetBasePath(void)
|
||||
return SDL_strdup("app0:/");
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
return NULL; // no EXE name on this system.
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
const char *envr = "ux0:/data/";
|
||||
|
||||
@@ -45,51 +45,32 @@ DEFINE_GUID(SDL_FOLDERID_Videos, 0x18989B1D, 0x99B5, 0x455B, 0x84, 0x1C, 0xAB, 0
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
DWORD buflen = 128;
|
||||
WCHAR *path = NULL;
|
||||
char *result = NULL;
|
||||
DWORD len = 0;
|
||||
int i;
|
||||
|
||||
while (true) {
|
||||
void *ptr = SDL_realloc(path, buflen * sizeof(WCHAR));
|
||||
if (!ptr) {
|
||||
SDL_free(path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = (WCHAR *)ptr;
|
||||
|
||||
len = GetModuleFileNameW(NULL, path, buflen);
|
||||
// if it truncated, then len >= buflen - 1
|
||||
// if there was enough room (or failure), len < buflen - 1
|
||||
if (len < buflen - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
// buffer too small? Try again.
|
||||
buflen *= 2;
|
||||
char *path = WIN_GetModulePath(NULL); // look up full path of the current process's EXE file.
|
||||
if (!path) {
|
||||
return NULL; // error message was already set.
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
SDL_free(path);
|
||||
WIN_SetError("Couldn't locate our .exe");
|
||||
return NULL;
|
||||
char *ptr = SDL_strrchr(path, '\\');
|
||||
SDL_assert(ptr != NULL); // Should have been an absolute path.
|
||||
|
||||
ptr[1] = '\0'; // chop off filename, leave '\\'.
|
||||
|
||||
ptr = (char *) SDL_realloc(path, ((size_t) (ptr - path)) + 2); // try to shrink this allocation down a little.
|
||||
return ptr ? ptr : path; // return shrunk buffer if shrink worked out, unchanged original buffer if not.
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
char *path = WIN_GetModulePath(NULL); // look up full path of the current process's EXE file.
|
||||
if (!path) {
|
||||
return NULL; // error message was already set.
|
||||
}
|
||||
|
||||
for (i = len - 1; i > 0; i--) {
|
||||
if (path[i] == '\\') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(i > 0); // Should have been an absolute path.
|
||||
path[i + 1] = '\0'; // chop off filename.
|
||||
|
||||
result = WIN_StringToUTF8W(path);
|
||||
SDL_free(path);
|
||||
|
||||
return result;
|
||||
char *ptr = SDL_strrchr(path, '\\');
|
||||
const size_t slen = SDL_strlen(ptr); // counts null terminator because we're still sitting on path separator.
|
||||
SDL_memmove(path, ptr + 1, slen); // move filename string to start of SDL_realloc'd region.
|
||||
ptr = (char *) SDL_realloc(path, slen); // try to shrink this allocation down a little.
|
||||
return ptr ? ptr : path; // return shrunk buffer if shrink worked out, unchanged original buffer if not.
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
|
||||
Reference in New Issue
Block a user