Skip to content

Commit 0ab7a76

Browse files
author
Semphris
committed
Add temp files and folders
1 parent ac2edad commit 0ab7a76

File tree

13 files changed

+443
-3
lines changed

13 files changed

+443
-3
lines changed

CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,9 @@ if(ANDROID)
13041304
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
13051305
set(HAVE_SDL_FSOPS TRUE)
13061306

1307+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
1308+
set(HAVE_SDL_TMPFS TRUE)
1309+
13071310
if(SDL_HAPTIC)
13081311
set(SDL_HAPTIC_ANDROID 1)
13091312
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/android/*.c")
@@ -1480,6 +1483,9 @@ elseif(EMSCRIPTEN)
14801483
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
14811484
set(HAVE_SDL_FSOPS TRUE)
14821485

1486+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
1487+
set(HAVE_SDL_TMPFS TRUE)
1488+
14831489
if(SDL_CAMERA)
14841490
set(SDL_CAMERA_DRIVER_EMSCRIPTEN 1)
14851491
set(HAVE_CAMERA TRUE)
@@ -1827,6 +1833,9 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
18271833
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
18281834
set(HAVE_SDL_FSOPS TRUE)
18291835

1836+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
1837+
set(HAVE_SDL_TMPFS TRUE)
1838+
18301839
set(SDL_TIME_UNIX 1)
18311840
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
18321841
set(HAVE_SDL_TIME TRUE)
@@ -2025,6 +2034,7 @@ elseif(WINDOWS)
20252034
set(SDL_FILESYSTEM_WINDOWS 1)
20262035
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/windows/*.c")
20272036
set(HAVE_SDL_FILESYSTEM TRUE)
2037+
set(HAVE_SDL_TMPFS TRUE) # SDL_tmpfs is included in the windows sources
20282038

20292039
set(SDL_FSOPS_WINDOWS 1)
20302040
set(HAVE_SDL_FSOPS TRUE)
@@ -2274,6 +2284,9 @@ elseif(APPLE)
22742284
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
22752285
set(HAVE_SDL_FSOPS TRUE)
22762286

2287+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
2288+
set(HAVE_SDL_TMPFS TRUE)
2289+
22772290
if(SDL_SENSOR)
22782291
if(IOS OR VISIONOS OR WATCHOS)
22792292
set(SDL_SENSOR_COREMOTION 1)
@@ -2477,6 +2490,9 @@ elseif(HAIKU)
24772490
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
24782491
set(HAVE_SDL_FSOPS TRUE)
24792492

2493+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
2494+
set(HAVE_SDL_TMPFS TRUE)
2495+
24802496
set(SDL_TIME_UNIX 1)
24812497
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
24822498
set(HAVE_SDL_TIME TRUE)
@@ -2517,6 +2533,9 @@ elseif(RISCOS)
25172533
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
25182534
set(HAVE_SDL_FSOPS TRUE)
25192535

2536+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
2537+
set(HAVE_SDL_TMPFS TRUE)
2538+
25202539
set(SDL_TIME_UNIX 1)
25212540
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
25222541
set(HAVE_SDL_TIME TRUE)
@@ -3043,6 +3062,10 @@ if(NOT HAVE_SDL_FSOPS)
30433062
set(SDL_FSOPS_DUMMY 1)
30443063
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/SDL_sysfsops.c")
30453064
endif()
3065+
if (NOT HAVE_SDL_TMPFS)
3066+
set(SDL_TMPFS_DUMMY 1)
3067+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/SDL_dummy_tmpfs.c")
3068+
endif()
30463069
if(NOT HAVE_SDL_LOCALE)
30473070
set(SDL_LOCALE_DUMMY 1)
30483071
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/dummy/*.c")

include/SDL3/SDL_filesystem.h

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include <SDL3/SDL_stdinc.h>
3232
#include <SDL3/SDL_error.h>
33+
#include <SDL3/SDL_iostream.h>
3334

3435
#include <SDL3/SDL_begin_code.h>
3536

@@ -137,9 +138,10 @@ extern SDL_DECLSPEC char * SDLCALL SDL_GetPrefPath(const char *org, const char *
137138
/**
138139
* The type of the OS-provided default folder for a specific purpose.
139140
*
140-
* Note that the Trash folder isn't included here, because trashing files
141-
* usually involves extra OS-specific functionality to remember the file's
142-
* original location.
141+
* Note that many common folders, like the Trash, the Temp folder or
142+
* app-specific folders like AppData are not listed here; using them properly
143+
* requires more treatment than fetching the folder path and using it. To use
144+
* these folders, see their dedicated functions.
143145
*
144146
* The folders supported per platform are:
145147
*
@@ -465,6 +467,80 @@ extern SDL_DECLSPEC char ** SDLCALL SDL_GlobDirectory(const char *path, const ch
465467
*/
466468
extern SDL_DECLSPEC char * SDLCALL SDL_GetCurrentDirectory(void);
467469

470+
/**
471+
* Create a secure temporary file.
472+
*
473+
* This function is not path-based to avoid race conditions. Returning a path
474+
* and letting the caller create the file opens a time-of-check-to-time-of-use
475+
* (TOCTOU) safety issue, where an attacker can use the small delay between the
476+
* moment the name is generated and the moment the file is created to create
477+
* the file first and give it undesirable attributes, such as giving itself
478+
* full read/write access to the file, or making the file a symlink to another,
479+
* sensitive file.
480+
*
481+
* \returns an open IOStream object to the file, or NULL on error; call
482+
* SDL_GetError() for details.
483+
*
484+
* \threadsafety It is safe to call this function from any thread.
485+
*
486+
* \since This function is available since SDL 3.0.0.
487+
*
488+
* \sa SDL_CreateUnsafeTempFile
489+
* \sa SDL_CreateTempFolder
490+
*/
491+
extern SDL_DECLSPEC SDL_IOStream *SDLCALL SDL_CreateSafeTempFile(void);
492+
493+
/**
494+
* Create a temporary file, with less security considerations.
495+
*
496+
* Unlike SDL_CreateSafeTempFile(), this function provides a path, which can
497+
* then be used like any other file on the filesystem. This has security
498+
* implications; an attacker could exploit the small delay between the moment
499+
* the name is generated and the moment the file is created to create the file
500+
* first and give it undesirable attributes, such as giving itself full
501+
* read/write access to the file, or making the file a symlink to another,
502+
* sensitive file.
503+
*
504+
* The path string is owned by the caller and must be freed with SDL_free().
505+
*
506+
* \returns an absolute path to the temporary file, or NULL on error; call
507+
* SDL_GetError() for details. If a path is returned, it is encoded in
508+
* OS-specific format, and is guaranteed to finish with a path
509+
* separator.
510+
*
511+
* \threadsafety It is safe to call this function from any thread.
512+
*
513+
* \since This function is available since SDL 3.0.0.
514+
*
515+
* \sa SDL_CreateSafeTempFile
516+
* \sa SDL_CreateTempFolder
517+
*/
518+
extern SDL_DECLSPEC char *SDLCALL SDL_CreateUnsafeTempFile(void);
519+
520+
/**
521+
* Create a temporary folder.
522+
*
523+
* Keep in mind any program running as the same user as your program can access
524+
* the contents of the folders and the files in it. Do not perform sensitive
525+
* tasks using the temporary folder. If you need one or more temporary files
526+
* for sensitive purposes, use SDL_CreateSafeTempFile().
527+
*
528+
* The path string is owned by the caller and must be freed with SDL_free().
529+
*
530+
* \returns an absolute path to the temporary folder, or NULL on error; call
531+
* SDL_GetError() for details. If a path is returned, it is encoded in
532+
* OS-specific format, and is guaranteed to finish with a path
533+
* separator.
534+
*
535+
* \threadsafety It is safe to call this function from any thread.
536+
*
537+
* \since This function is available since SDL 3.0.0.
538+
*
539+
* \sa SDL_CreateSafeTempFile
540+
* \sa SDL_CreateUnsafeTempFile
541+
*/
542+
extern SDL_DECLSPEC char *SDLCALL SDL_CreateTempFolder(void);
543+
468544
/* Ends C function definitions when using C++ */
469545
#ifdef __cplusplus
470546
}

src/dynapi/SDL_dynapi.sym

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,9 @@ SDL3_0.0.0 {
12071207
SDL_SetGPUAllowedFramesInFlight;
12081208
SDL_RenderTextureAffine;
12091209
SDL_WaitAndAcquireGPUSwapchainTexture;
1210+
SDL_CreateSafeTempFile;
1211+
SDL_CreateUnsafeTempFile;
1212+
SDL_CreateTempFolder;
12101213
# extra symbols go here (don't modify this line)
12111214
local: *;
12121215
};

src/dynapi/SDL_dynapi_overrides.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,3 +1232,6 @@
12321232
#define SDL_SetGPUAllowedFramesInFlight SDL_SetGPUAllowedFramesInFlight_REAL
12331233
#define SDL_RenderTextureAffine SDL_RenderTextureAffine_REAL
12341234
#define SDL_WaitAndAcquireGPUSwapchainTexture SDL_WaitAndAcquireGPUSwapchainTexture_REAL
1235+
#define SDL_CreateSafeTempFile SDL_CreateSafeTempFile_REAL
1236+
#define SDL_CreateUnsafeTempFile SDL_CreateUnsafeTempFile_REAL
1237+
#define SDL_CreateTempFolder SDL_CreateTempFolder_REAL

src/dynapi/SDL_dynapi_procs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,3 +1238,6 @@ SDL_DYNAPI_PROC(bool,SDL_RunOnMainThread,(SDL_MainThreadCallback a,void *b,bool
12381238
SDL_DYNAPI_PROC(bool,SDL_SetGPUAllowedFramesInFlight,(SDL_GPUDevice *a,Uint32 b),(a,b),return)
12391239
SDL_DYNAPI_PROC(bool,SDL_RenderTextureAffine,(SDL_Renderer *a,SDL_Texture *b,const SDL_FRect *c,const SDL_FPoint *d,const SDL_FPoint *e,const SDL_FPoint *f),(a,b,c,d,e,f),return)
12401240
SDL_DYNAPI_PROC(bool,SDL_WaitAndAcquireGPUSwapchainTexture,(SDL_GPUCommandBuffer *a,SDL_Window *b,SDL_GPUTexture **c,Uint32 *d,Uint32 *e),(a,b,c,d,e),return)
1241+
SDL_DYNAPI_PROC(SDL_IOStream*,SDL_CreateSafeTempFile,(void),(),return)
1242+
SDL_DYNAPI_PROC(char*,SDL_CreateUnsafeTempFile,(void),(),return)
1243+
SDL_DYNAPI_PROC(char*,SDL_CreateTempFolder,(void),(),return)

src/filesystem/SDL_filesystem.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,21 @@ char *SDL_GetCurrentDirectory(void)
503503
return SDL_SYS_GetCurrentDirectory();
504504
}
505505

506+
SDL_IOStream *SDL_CreateSafeTempFile(void)
507+
{
508+
return SDL_SYS_CreateSafeTempFile();
509+
}
510+
511+
char *SDL_CreateUnsafeTempFile(void)
512+
{
513+
return SDL_SYS_CreateUnsafeTempFile();
514+
}
515+
516+
char *SDL_CreateTempFolder(void)
517+
{
518+
return SDL_SYS_CreateTempFolder();
519+
}
520+
506521
void SDL_InitFilesystem(void)
507522
{
508523
}

src/filesystem/SDL_sysfilesystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,9 @@ typedef bool (*SDL_GlobEnumeratorFunc)(const char *path, SDL_EnumerateDirectoryC
3939
typedef bool (*SDL_GlobGetPathInfoFunc)(const char *path, SDL_PathInfo *info, void *userdata);
4040
extern char **SDL_InternalGlobDirectory(const char *path, const char *pattern, SDL_GlobFlags flags, int *count, SDL_GlobEnumeratorFunc enumerator, SDL_GlobGetPathInfoFunc getpathinfo, void *userdata);
4141

42+
extern SDL_IOStream *SDL_SYS_CreateSafeTempFile(void);
43+
extern char *SDL_SYS_CreateUnsafeTempFile(void);
44+
extern char *SDL_SYS_CreateTempFolder(void);
45+
4246
#endif
4347

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Simple DirectMedia Layer
3+
Copyright (C) 1997-2024 Sam Lantinga <[email protected]>
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
2. Altered source versions must be plainly marked as such, and must not be
18+
misrepresented as being the original software.
19+
3. This notice may not be removed or altered from any source distribution.
20+
*/
21+
22+
#include "SDL_internal.h"
23+
#include "../SDL_sysfilesystem.h"
24+
25+
SDL_IOStream *SDL_SYS_CreateSafeTempFile(void)
26+
{
27+
SDL_Unsupported();
28+
return NULL;
29+
}
30+
31+
char *SDL_SYS_CreateUnsafeTempFile(void)
32+
{
33+
SDL_Unsupported();
34+
return NULL;
35+
}
36+
37+
char *SDL_SYS_CreateTempFolder(void)
38+
{
39+
SDL_Unsupported();
40+
return NULL;
41+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
Simple DirectMedia Layer
3+
Copyright (C) 1997-2024 Sam Lantinga <[email protected]>
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
2. Altered source versions must be plainly marked as such, and must not be
18+
misrepresented as being the original software.
19+
3. This notice may not be removed or altered from any source distribution.
20+
*/
21+
22+
#include "SDL_internal.h"
23+
#include "../SDL_sysfilesystem.h"
24+
#include "../../file/SDL_iostream_c.h"
25+
26+
#include <unistd.h>
27+
#include <string.h>
28+
#include <errno.h>
29+
30+
SDL_IOStream *SDL_SYS_CreateSafeTempFile(void)
31+
{
32+
FILE *file = tmpfile();
33+
34+
if (!file) {
35+
SDL_SetError("Could not tmpfile(): %s", strerror(errno));
36+
return NULL;
37+
}
38+
39+
return SDL_IOFromFP(file, true);
40+
}
41+
42+
char *SDL_SYS_CreateUnsafeTempFile(void)
43+
{
44+
/* TODO: Check for possible alternatives to /tmp, like $TMP */
45+
char template[] = "/tmp/tmp.XXXXXX";
46+
47+
char *file = SDL_strdup(template);
48+
49+
if (!file) {
50+
return NULL;
51+
}
52+
53+
int fd = mkstemp(file);
54+
55+
if (fd < 0) {
56+
SDL_free(file);
57+
SDL_SetError("Could not mkstemp(): %s", strerror(errno));
58+
return NULL;
59+
}
60+
61+
/* Normal usage of mkstemp() would use the file descriptor rather than the
62+
path, to avoid issues. In this function, security is assumed to be
63+
unimportant, so no need to worry about it. */
64+
/* See https://stackoverflow.com/questions/27680807/mkstemp-is-it-safe-to-close-descriptor-and-reopen-it-again */
65+
close(fd);
66+
67+
return file;
68+
}
69+
70+
char *SDL_SYS_CreateTempFolder(void)
71+
{
72+
/* TODO: Check for possible alternatives to /tmp, like $TMP */
73+
char template[] = "/tmp/tmp.XXXXXX";
74+
75+
char *folder = SDL_strdup(template);
76+
77+
if (!folder) {
78+
return NULL;
79+
}
80+
81+
char *res = mkdtemp(folder);
82+
83+
if (!res) {
84+
SDL_free(folder);
85+
SDL_SetError("Could not mkdtemp(): %s", strerror(errno));
86+
return NULL;
87+
}
88+
89+
return folder;
90+
}

src/filesystem/unix/SDL_sysfilesystem.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
// System dependent filesystem routines
2727

2828
#include "../SDL_sysfilesystem.h"
29+
#include "../../file/SDL_iostream_c.h"
2930

3031
#include <stdio.h>
32+
#include <stdlib.h>
3133
#include <sys/stat.h>
3234
#include <sys/types.h>
3335
#include <dirent.h>

0 commit comments

Comments
 (0)