diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h index 9cefc7555..6b72c0a87 100644 --- a/include/SDL3/SDL_filesystem.h +++ b/include/SDL3/SDL_filesystem.h @@ -224,6 +224,9 @@ typedef enum SDL_Folder * Note that the function is expensive, and should be called once at the * beginning of the execution and kept for as long as needed. * + * The returned path is guaranteed to end with a path separator ('\\' on + * Windows, '/' on most other platforms). + * * The returned value is owned by the caller and should be freed with * SDL_free(). * diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m index aef0217d2..fb261d769 100644 --- a/src/filesystem/cocoa/SDL_sysfilesystem.m +++ b/src/filesystem/cocoa/SDL_sysfilesystem.m @@ -209,11 +209,17 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } - retval = SDL_strdup(base); + retval = SDL_malloc(SDL_strlen(base) + 2); if (retval == NULL) { return NULL; } + if (SDL_snprintf(retval, SDL_strlen(base) + 2, "%s/", base) < 0) { + SDL_SetError("Couldn't snprintf folder path for Cocoa: %s", base); + SDL_free(retval); + return NULL; + } + for (ptr = retval + 1; *ptr; ptr++) { if (*ptr == '/') { *ptr = '\0'; @@ -221,7 +227,6 @@ char *SDL_GetUserFolder(SDL_Folder folder) *ptr = '/'; } } - mkdir(retval, 0700); return retval; #endif /* SDL_PLATFORM_TVOS */ diff --git a/src/filesystem/emscripten/SDL_sysfilesystem.c b/src/filesystem/emscripten/SDL_sysfilesystem.c index 69069e937..b2ae8c529 100644 --- a/src/filesystem/emscripten/SDL_sysfilesystem.c +++ b/src/filesystem/emscripten/SDL_sysfilesystem.c @@ -97,7 +97,18 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } - return SDL_strdup(home); + char *retval = SDL_malloc(SDL_strlen(home) + 2); + if (!retval) { + return NULL; + } + + if (SDL_snprintf(retval, SDL_strlen(home) + 2, "%s/", home) < 0) { + SDL_SetError("Couldn't snprintf home path for Emscripten: %s", home); + SDL_free(retval); + return NULL; + } + + return retval; } #endif /* SDL_FILESYSTEM_EMSCRIPTEN */ diff --git a/src/filesystem/haiku/SDL_sysfilesystem.cc b/src/filesystem/haiku/SDL_sysfilesystem.cc index 893e24a6d..0e91b06b0 100644 --- a/src/filesystem/haiku/SDL_sysfilesystem.cc +++ b/src/filesystem/haiku/SDL_sysfilesystem.cc @@ -107,15 +107,30 @@ char *SDL_GetUserFolder(SDL_Folder folder) switch (folder) { case SDL_FOLDER_HOME: - return SDL_strdup(home); + retval = (char *) SDL_malloc(SDL_strlen(home) + 2); + if (!retval) { + return NULL; + } + + if (SDL_snprintf(retval, SDL_strlen(home) + 2, "%s/", home) < 0) { + SDL_SetError("Couldn't snprintf home path for Haiku: %s", home); + SDL_free(retval); + return NULL; + } + + return retval; /* TODO: Is Haiku's desktop folder always ~/Desktop/ ? */ case SDL_FOLDER_DESKTOP: retval = (char *) SDL_malloc(SDL_strlen(home) + 10); + if (!retval) { + return NULL; + } - if (retval) { - SDL_strlcpy(retval, home, SDL_strlen(home) + 10); - SDL_strlcat(retval, "/Desktop/", SDL_strlen(home) + 10); + if (SDL_snprintf(retval, SDL_strlen(home) + 10, "%s/Desktop/", home) < 0) { + SDL_SetError("Couldn't snprintf desktop path for Haiku: %s/Desktop/", home); + SDL_free(retval); + return NULL; } return retval; diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c index 72e061a0d..308950edd 100644 --- a/src/filesystem/unix/SDL_sysfilesystem.c +++ b/src/filesystem/unix/SDL_sysfilesystem.c @@ -514,6 +514,7 @@ char *SDL_GetUserFolder(SDL_Folder folder) { const char *param = NULL; char *retval; + char *newretval; /* According to `man xdg-user-dir`, the possible values are: DESKTOP @@ -594,6 +595,16 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } + newretval = (char *) SDL_realloc(retval, SDL_strlen(retval) + 2); + + if (!newretval) { + SDL_free(retval); + return NULL; + } + + retval = newretval; + SDL_strlcat(retval, "/", SDL_strlen(retval) + 2); + return retval; } diff --git a/src/filesystem/windows/SDL_sysfilesystem.c b/src/filesystem/windows/SDL_sysfilesystem.c index f9e236161..e321b7dc0 100644 --- a/src/filesystem/windows/SDL_sysfilesystem.c +++ b/src/filesystem/windows/SDL_sysfilesystem.c @@ -322,6 +322,19 @@ char *SDL_GetUserFolder(SDL_Folder folder) } } + if (retval) { + char *newretval = (char *) SDL_realloc(retval, SDL_strlen(retval) + 2); + + if (!newretval) { + SDL_free(retval); + retval = NULL; /* will be returned */ + goto done; + } + + retval = newretval; + SDL_strlcat(retval, "\\", SDL_strlen(retval) + 2); + } + done: if (lib) { FreeLibrary(lib); diff --git a/src/filesystem/winrt/SDL_sysfilesystem.cpp b/src/filesystem/winrt/SDL_sysfilesystem.cpp index 0a6fcdc76..f29bc348a 100644 --- a/src/filesystem/winrt/SDL_sysfilesystem.cpp +++ b/src/filesystem/winrt/SDL_sysfilesystem.cpp @@ -250,6 +250,8 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; }; + wpath += L"\\"; + return WIN_StringToUTF8(wpath.c_str()); } diff --git a/test/testdialog.c b/test/testdialog.c index e5492eb66..378cc6d6c 100644 --- a/test/testdialog.c +++ b/test/testdialog.c @@ -54,7 +54,6 @@ int main(int argc, char *argv[]) { const SDL_FRect open_folder_rect = { 370, 50, 220, 140 }; int i; char *initial_path = NULL; - char path_with_trailing_slash[2048]; /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); @@ -94,10 +93,6 @@ int main(int argc, char *argv[]) { if (!initial_path) { SDL_Log("Will not use an initial path, couldn't get the home directory path: %s\n", SDL_GetError()); - path_with_trailing_slash[0] = '\0'; - } else { - SDL_snprintf(path_with_trailing_slash, sizeof(path_with_trailing_slash), "%s/", initial_path); - SDL_free(initial_path); } while (1) { @@ -119,11 +114,11 @@ int main(int argc, char *argv[]) { * - Nonzero if the user is allowed to choose multiple entries (not for SDL_ShowSaveFileDialog) */ if (SDL_PointInRectFloat(&p, &open_file_rect)) { - SDL_ShowOpenFileDialog(callback, NULL, w, filters, path_with_trailing_slash, 1); + SDL_ShowOpenFileDialog(callback, NULL, w, filters, initial_path, 1); } else if (SDL_PointInRectFloat(&p, &open_folder_rect)) { - SDL_ShowOpenFolderDialog(callback, NULL, w, path_with_trailing_slash, 1); + SDL_ShowOpenFolderDialog(callback, NULL, w, initial_path, 1); } else if (SDL_PointInRectFloat(&p, &save_file_rect)) { - SDL_ShowSaveFileDialog(callback, NULL, w, filters, path_with_trailing_slash); + SDL_ShowSaveFileDialog(callback, NULL, w, filters, initial_path); } } } @@ -152,6 +147,10 @@ int main(int argc, char *argv[]) { SDL_RenderPresent(r); } + if (initial_path) { + SDL_free(initial_path); + } + SDLTest_CleanupTextDrawing(); SDL_DestroyRenderer(r); SDL_DestroyWindow(w);