From 2621d7aab29bbdb6cbd72d4732a3e852067ed1b7 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Tue, 26 May 2026 15:23:31 -0400
Subject: [PATCH] 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.
(cherry picked from commit 7d29ce8e31dbd063ed61b2aa0ce604677923b362)
---
src/SDL_internal.h | 3 +
src/SDL_utils.c | 1 -
src/core/linux/SDL_fcitx.c | 1 +
src/core/unix/SDL_appid.c | 34 +----------
src/core/unix/SDL_appid.h | 1 -
src/core/windows/SDL_windows.c | 38 ++++++++++++
src/core/windows/SDL_windows.h | 5 +-
src/filesystem/SDL_filesystem.c | 18 ++++--
src/filesystem/SDL_sysfilesystem.h | 1 +
src/filesystem/android/SDL_sysfilesystem.c | 5 ++
src/filesystem/cocoa/SDL_sysfilesystem.m | 6 ++
src/filesystem/dummy/SDL_sysfilesystem.c | 6 ++
src/filesystem/emscripten/SDL_sysfilesystem.c | 5 ++
src/filesystem/gdk/SDL_sysfilesystem.cpp | 8 +++
src/filesystem/haiku/SDL_sysfilesystem.cc | 5 ++
src/filesystem/n3ds/SDL_sysfilesystem.c | 5 ++
src/filesystem/ngage/SDL_sysfilesystem.c | 6 ++
src/filesystem/ps2/SDL_sysfilesystem.c | 5 ++
src/filesystem/psp/SDL_sysfilesystem.c | 5 ++
src/filesystem/riscos/SDL_sysfilesystem.c | 6 ++
src/filesystem/unix/SDL_sysfilesystem.c | 47 ++++++++++-----
src/filesystem/vita/SDL_sysfilesystem.c | 5 ++
src/filesystem/windows/SDL_sysfilesystem.c | 59 +++++++------------
23 files changed, 180 insertions(+), 95 deletions(-)
diff --git a/src/SDL_internal.h b/src/SDL_internal.h
index e2debb96bc8cf..b24930984c6be 100644
--- a/src/SDL_internal.h
+++ b/src/SDL_internal.h
@@ -266,6 +266,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
diff --git a/src/SDL_utils.c b/src/SDL_utils.c
index a4a0d77614e80..146d8163414c4 100644
--- a/src/SDL_utils.c
+++ b/src/SDL_utils.c
@@ -622,4 +622,3 @@ void SDL_DebugLogBackend(const char *subsystem, const char *backend)
{
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "SDL chose %s backend '%s'", subsystem, backend);
}
-
diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c
index d47b44e86fb44..a13b640db59f5 100644
--- a/src/core/linux/SDL_fcitx.c
+++ b/src/core/linux/SDL_fcitx.c
@@ -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();
diff --git a/src/core/unix/SDL_appid.c b/src/core/unix/SDL_appid.c
index 3b85cbc876ba7..95c5dc1a6b91b 100644
--- a/src/core/unix/SDL_appid.c
+++ b/src/core/unix/SDL_appid.c
@@ -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);
@@ -73,3 +40,4 @@ const char *SDL_GetAppID(void)
return id_str;
}
+
diff --git a/src/core/unix/SDL_appid.h b/src/core/unix/SDL_appid.h
index 9ed45c31bc304..5f8eb932e6c60 100644
--- a/src/core/unix/SDL_appid.h
+++ b/src/core/unix/SDL_appid.h
@@ -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_
diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c
index d80fb61aad3fc..d011db38ead5c 100644
--- a/src/core/windows/SDL_windows.c
+++ b/src/core/windows/SDL_windows.c
@@ -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)
diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h
index 185f8862866c8..54f3f2c96c72a 100644
--- a/src/core/windows/SDL_windows.h
+++ b/src/core/windows/SDL_windows.h
@@ -213,7 +213,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
diff --git a/src/filesystem/SDL_filesystem.c b/src/filesystem/SDL_filesystem.c
index dca0da5c99aeb..81c0b41e346c4 100644
--- a/src/filesystem/SDL_filesystem.c
+++ b/src/filesystem/SDL_filesystem.c
@@ -510,6 +510,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)
{
@@ -537,10 +545,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]);
diff --git a/src/filesystem/SDL_sysfilesystem.h b/src/filesystem/SDL_sysfilesystem.h
index 660c712480482..4f1cf1d5ccfc2 100644
--- a/src/filesystem/SDL_sysfilesystem.h
+++ b/src/filesystem/SDL_sysfilesystem.h
@@ -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);
diff --git a/src/filesystem/android/SDL_sysfilesystem.c b/src/filesystem/android/SDL_sysfilesystem.c
index 7eddd28774257..3fd8afd986438 100644
--- a/src/filesystem/android/SDL_sysfilesystem.c
+++ b/src/filesystem/android/SDL_sysfilesystem.c
@@ -34,6 +34,11 @@ char *SDL_SYS_GetBasePath(void)
return SDL_strdup("./");
}
+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();
diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m
index 26ee7cc102d00..2995df4e5de03 100644
--- a/src/filesystem/cocoa/SDL_sysfilesystem.m
+++ b/src/filesystem/cocoa/SDL_sysfilesystem.m
@@ -63,6 +63,12 @@
}
}
+char *SDL_SYS_GetExeName(void)
+{
+ SDL_Unsupported(); // !!! FIXME
+ return NULL;
+}
+
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
{
@autoreleasepool {
diff --git a/src/filesystem/dummy/SDL_sysfilesystem.c b/src/filesystem/dummy/SDL_sysfilesystem.c
index 53bc50f7f91cb..2df8ec4f2c5cf 100644
--- a/src/filesystem/dummy/SDL_sysfilesystem.c
+++ b/src/filesystem/dummy/SDL_sysfilesystem.c
@@ -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();
diff --git a/src/filesystem/emscripten/SDL_sysfilesystem.c b/src/filesystem/emscripten/SDL_sysfilesystem.c
index 0d21cd2698f50..54dcf082567d6 100644
--- a/src/filesystem/emscripten/SDL_sysfilesystem.c
+++ b/src/filesystem/emscripten/SDL_sysfilesystem.c
@@ -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
diff --git a/src/filesystem/gdk/SDL_sysfilesystem.cpp b/src/filesystem/gdk/SDL_sysfilesystem.cpp
index 83abfada5465a..8554026088f9a 100644
--- a/src/filesystem/gdk/SDL_sysfilesystem.cpp
+++ b/src/filesystem/gdk/SDL_sysfilesystem.cpp
@@ -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;
diff --git a/src/filesystem/haiku/SDL_sysfilesystem.cc b/src/filesystem/haiku/SDL_sysfilesystem.cc
index 380e05ce1e1ba..747bd6ced0130 100644
--- a/src/filesystem/haiku/SDL_sysfilesystem.cc
+++ b/src/filesystem/haiku/SDL_sysfilesystem.cc
@@ -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)
{
diff --git a/src/filesystem/n3ds/SDL_sysfilesystem.c b/src/filesystem/n3ds/SDL_sysfilesystem.c
index 66dba9ddafb31..8a129c7194fc0 100644
--- a/src/filesystem/n3ds/SDL_sysfilesystem.c
+++ b/src/filesystem/n3ds/SDL_sysfilesystem.c
@@ -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;
diff --git a/src/filesystem/ngage/SDL_sysfilesystem.c b/src/filesystem/ngage/SDL_sysfilesystem.c
index a7d5ea89596e7..73b8ddc0c74bd 100644
--- a/src/filesystem/ngage/SDL_sysfilesystem.c
+++ b/src/filesystem/ngage/SDL_sysfilesystem.c
@@ -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;
diff --git a/src/filesystem/ps2/SDL_sysfilesystem.c b/src/filesystem/ps2/SDL_sysfilesystem.c
index 87b44c9bf0c49..ddc3c68399d95 100644
--- a/src/filesystem/ps2/SDL_sysfilesystem.c
+++ b/src/filesystem/ps2/SDL_sysfilesystem.c
@@ -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)
{
diff --git a/src/filesystem/psp/SDL_sysfilesystem.c b/src/filesystem/psp/SDL_sysfilesystem.c
index 18cd9d95ed43d..dd828cf52344f 100644
--- a/src/filesystem/psp/SDL_sysfilesystem.c
+++ b/src/filesystem/psp/SDL_sysfilesystem.c
@@ -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;
diff --git a/src/filesystem/riscos/SDL_sysfilesystem.c b/src/filesystem/riscos/SDL_sysfilesystem.c
index d52b22ad43717..2a5ac9263fa07 100644
--- a/src/filesystem/riscos/SDL_sysfilesystem.c
+++ b/src/filesystem/riscos/SDL_sysfilesystem.c
@@ -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;
diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c
index 9edbf6dc0bb00..a23d67b362793 100644
--- a/src/filesystem/unix/SDL_sysfilesystem.c
+++ b/src/filesystem/unix/SDL_sysfilesystem.c
@@ -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;
- }
+ return result;
+}
+
+char *SDL_SYS_GetBasePath(void)
+{
+ char *path = GetExePath();
+ if (!path) {
+ return 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.
- }
+ 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;
}
- return result;
+ 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)
{
/*
diff --git a/src/filesystem/vita/SDL_sysfilesystem.c b/src/filesystem/vita/SDL_sysfilesystem.c
index a23fcdcad609c..4910000acb1b0 100644
--- a/src/filesystem/vita/SDL_sysfilesystem.c
+++ b/src/filesystem/vita/SDL_sysfilesystem.c
@@ -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/";
diff --git a/src/filesystem/windows/SDL_sysfilesystem.c b/src/filesystem/windows/SDL_sysfilesystem.c
index f2c59f4f2f6c3..dd836e25bc593 100644
--- a/src/filesystem/windows/SDL_sysfilesystem.c
+++ b/src/filesystem/windows/SDL_sysfilesystem.c
@@ -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.
- for (i = len - 1; i > 0; i--) {
- if (path[i] == '\\') {
- break;
- }
- }
+ ptr[1] = '\0'; // chop off filename, leave '\\'.
- SDL_assert(i > 0); // Should have been an absolute path.
- path[i + 1] = '\0'; // chop off filename.
+ 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.
+}
- result = WIN_StringToUTF8W(path);
- SDL_free(path);
+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.
+ }
- 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)