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:
Ryan C. Gordon
2026-05-26 15:23:31 -04:00
parent 199d509820
commit 7d29ce8e31
24 changed files with 191 additions and 100 deletions

View File

@@ -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]);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)
{
/*

View File

@@ -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/";

View File

@@ -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)