Skip to content

Commit 6174f53

Browse files
author
Semphris
committed
Add temp files and folders
1 parent f3d4e6f commit 6174f53

File tree

13 files changed

+436
-3
lines changed

13 files changed

+436
-3
lines changed

CMakeLists.txt

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

1334+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
1335+
set(HAVE_SDL_TMPFS TRUE)
1336+
13341337
if(SDL_HAPTIC)
13351338
set(SDL_HAPTIC_ANDROID 1)
13361339
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/android/*.c")
@@ -1507,6 +1510,9 @@ elseif(EMSCRIPTEN)
15071510
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
15081511
set(HAVE_SDL_FSOPS TRUE)
15091512

1513+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
1514+
set(HAVE_SDL_TMPFS TRUE)
1515+
15101516
if(SDL_CAMERA)
15111517
set(SDL_CAMERA_DRIVER_EMSCRIPTEN 1)
15121518
set(HAVE_CAMERA TRUE)
@@ -1857,6 +1863,9 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
18571863
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
18581864
set(HAVE_SDL_FSOPS TRUE)
18591865

1866+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
1867+
set(HAVE_SDL_TMPFS TRUE)
1868+
18601869
set(SDL_TIME_UNIX 1)
18611870
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
18621871
set(HAVE_SDL_TIME TRUE)
@@ -2059,6 +2068,7 @@ elseif(WINDOWS)
20592068
set(SDL_FILESYSTEM_WINDOWS 1)
20602069
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/windows/*.c")
20612070
set(HAVE_SDL_FILESYSTEM TRUE)
2071+
set(HAVE_SDL_TMPFS TRUE) # SDL_tmpfs is included in the windows sources
20622072

20632073
set(SDL_FSOPS_WINDOWS 1)
20642074
set(HAVE_SDL_FSOPS TRUE)
@@ -2311,6 +2321,9 @@ elseif(APPLE)
23112321
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
23122322
set(HAVE_SDL_FSOPS TRUE)
23132323

2324+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
2325+
set(HAVE_SDL_TMPFS TRUE)
2326+
23142327
if(SDL_SENSOR)
23152328
if(IOS OR VISIONOS OR WATCHOS)
23162329
set(SDL_SENSOR_COREMOTION 1)
@@ -2514,6 +2527,9 @@ elseif(HAIKU)
25142527
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
25152528
set(HAVE_SDL_FSOPS TRUE)
25162529

2530+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
2531+
set(HAVE_SDL_TMPFS TRUE)
2532+
25172533
set(SDL_TIME_UNIX 1)
25182534
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
25192535
set(HAVE_SDL_TIME TRUE)
@@ -2554,6 +2570,9 @@ elseif(RISCOS)
25542570
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
25552571
set(HAVE_SDL_FSOPS TRUE)
25562572

2573+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_posix_tmpfs.c")
2574+
set(HAVE_SDL_TMPFS TRUE)
2575+
25572576
set(SDL_TIME_UNIX 1)
25582577
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
25592578
set(HAVE_SDL_TIME TRUE)
@@ -3078,6 +3097,10 @@ if(NOT HAVE_SDL_FSOPS)
30783097
set(SDL_FSOPS_DUMMY 1)
30793098
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/SDL_sysfsops.c")
30803099
endif()
3100+
if (NOT HAVE_SDL_TMPFS)
3101+
set(SDL_TMPFS_DUMMY 1)
3102+
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/SDL_dummy_tmpfs.c")
3103+
endif()
30813104
if(NOT HAVE_SDL_LOCALE)
30823105
set(SDL_LOCALE_DUMMY 1)
30833106
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/dummy/*.c")

include/SDL3/SDL_filesystem.h

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
#include <SDL3/SDL_stdinc.h>
4848
#include <SDL3/SDL_error.h>
49+
#include <SDL3/SDL_iostream.h>
4950

5051
#include <SDL3/SDL_begin_code.h>
5152

@@ -153,9 +154,10 @@ extern SDL_DECLSPEC char * SDLCALL SDL_GetPrefPath(const char *org, const char *
153154
/**
154155
* The type of the OS-provided default folder for a specific purpose.
155156
*
156-
* Note that the Trash folder isn't included here, because trashing files
157-
* usually involves extra OS-specific functionality to remember the file's
158-
* original location.
157+
* Note that many common folders, like the Trash, the Temp folder or
158+
* app-specific folders like AppData are not listed here; using them properly
159+
* requires more treatment than fetching the folder path and using it. To use
160+
* these folders, see their dedicated functions.
159161
*
160162
* The folders supported per platform are:
161163
*
@@ -494,6 +496,79 @@ extern SDL_DECLSPEC char ** SDLCALL SDL_GlobDirectory(const char *path, const ch
494496
*/
495497
extern SDL_DECLSPEC char * SDLCALL SDL_GetCurrentDirectory(void);
496498

499+
/**
500+
* Create a secure temporary file.
501+
*
502+
* This function is not path-based to avoid race conditions. Returning a path
503+
* and letting the caller create the file opens a time-of-check-to-time-of-use
504+
* (TOCTOU) safety issue, where an attacker can use the small delay between the
505+
* moment the name is generated and the moment the file is created to create
506+
* the file first and give it undesirable attributes, such as giving itself
507+
* full read/write access to the file, or making the file a symlink to another,
508+
* sensitive file.
509+
*
510+
* \returns an open IOStream object to the file, or NULL on error; call
511+
* SDL_GetError() for details.
512+
*
513+
* \threadsafety It is safe to call this function from any thread.
514+
*
515+
* \since This function is available since SDL 3.0.0.
516+
*
517+
* \sa SDL_CreateUnsafeTempFile
518+
* \sa SDL_CreateTempFolder
519+
*/
520+
extern SDL_DECLSPEC SDL_IOStream *SDLCALL SDL_CreateSafeTempFile(void);
521+
522+
/**
523+
* Create a temporary file, with less security considerations.
524+
*
525+
* Unlike SDL_CreateSafeTempFile(), this function provides a path, which can
526+
* then be used like any other file on the filesystem. This has security
527+
* implications; an attacker could exploit the small delay between the moment
528+
* the name is generated and the moment the file is created to create the file
529+
* first and give it undesirable attributes, such as giving itself full
530+
* read/write access to the file, or making the file a symlink to another,
531+
* sensitive file.
532+
*
533+
* The path string is owned by the caller and must be freed with SDL_free().
534+
*
535+
* \returns an absolute path to the temporary file, or NULL on error; call
536+
* SDL_GetError() for details. If a path is returned, it is encoded in
537+
* OS-specific format.
538+
*
539+
* \threadsafety It is safe to call this function from any thread.
540+
*
541+
* \since This function is available since SDL 3.0.0.
542+
*
543+
* \sa SDL_CreateSafeTempFile
544+
* \sa SDL_CreateTempFolder
545+
*/
546+
extern SDL_DECLSPEC char *SDLCALL SDL_CreateUnsafeTempFile(void);
547+
548+
/**
549+
* Create a temporary folder.
550+
*
551+
* Keep in mind any program running as the same user as your program can access
552+
* the contents of the folders and the files in it. Do not perform sensitive
553+
* tasks using the temporary folder. If you need one or more temporary files
554+
* for sensitive purposes, use SDL_CreateSafeTempFile().
555+
*
556+
* The path string is owned by the caller and must be freed with SDL_free().
557+
*
558+
* \returns an absolute path to the temporary folder, or NULL on error; call
559+
* SDL_GetError() for details. If a path is returned, it is encoded in
560+
* OS-specific format, and is guaranteed to finish with a path
561+
* separator.
562+
*
563+
* \threadsafety It is safe to call this function from any thread.
564+
*
565+
* \since This function is available since SDL 3.0.0.
566+
*
567+
* \sa SDL_CreateSafeTempFile
568+
* \sa SDL_CreateUnsafeTempFile
569+
*/
570+
extern SDL_DECLSPEC char *SDLCALL SDL_CreateTempFolder(void);
571+
497572
/* Ends C function definitions when using C++ */
498573
#ifdef __cplusplus
499574
}

src/dynapi/SDL_dynapi.sym

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,9 @@ SDL3_0.0.0 {
12461246
SDL_SetWindowProgressValue;
12471247
SDL_GetWindowProgressState;
12481248
SDL_GetWindowProgressValue;
1249+
SDL_CreateSafeTempFile;
1250+
SDL_CreateUnsafeTempFile;
1251+
SDL_CreateTempFolder;
12491252
# extra symbols go here (don't modify this line)
12501253
local: *;
12511254
};

src/dynapi/SDL_dynapi_overrides.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,3 +1271,6 @@
12711271
#define SDL_SetWindowProgressValue SDL_SetWindowProgressValue_REAL
12721272
#define SDL_GetWindowProgressState SDL_GetWindowProgressState_REAL
12731273
#define SDL_GetWindowProgressValue SDL_GetWindowProgressValue_REAL
1274+
#define SDL_CreateSafeTempFile SDL_CreateSafeTempFile_REAL
1275+
#define SDL_CreateUnsafeTempFile SDL_CreateUnsafeTempFile_REAL
1276+
#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
@@ -1279,3 +1279,6 @@ SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressState,(SDL_Window *a,SDL_ProgressState
12791279
SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressValue,(SDL_Window *a,float b),(a,b),return)
12801280
SDL_DYNAPI_PROC(SDL_ProgressState,SDL_GetWindowProgressState,(SDL_Window *a),(a),return)
12811281
SDL_DYNAPI_PROC(float,SDL_GetWindowProgressValue,(SDL_Window *a),(a),return)
1282+
SDL_DYNAPI_PROC(SDL_IOStream*,SDL_CreateSafeTempFile,(void),(),return)
1283+
SDL_DYNAPI_PROC(char*,SDL_CreateUnsafeTempFile,(void),(),return)
1284+
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
@@ -510,6 +510,21 @@ char *SDL_GetCurrentDirectory(void)
510510
return SDL_SYS_GetCurrentDirectory();
511511
}
512512

513+
SDL_IOStream *SDL_CreateSafeTempFile(void)
514+
{
515+
return SDL_SYS_CreateSafeTempFile();
516+
}
517+
518+
char *SDL_CreateUnsafeTempFile(void)
519+
{
520+
return SDL_SYS_CreateUnsafeTempFile();
521+
}
522+
523+
char *SDL_CreateTempFolder(void)
524+
{
525+
return SDL_SYS_CreateTempFolder();
526+
}
527+
513528
void SDL_InitFilesystem(void)
514529
{
515530
}

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: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
char *file = SDL_strdup("/tmp/tmp.XXXXXX");
45+
46+
if (!file) {
47+
return NULL;
48+
}
49+
50+
int fd = mkstemp(file);
51+
52+
if (fd < 0) {
53+
SDL_free(file);
54+
SDL_SetError("Could not mkstemp(): %s", strerror(errno));
55+
return NULL;
56+
}
57+
58+
/* Normal usage of mkstemp() would use the file descriptor rather than the
59+
path, to avoid issues. In this function, security is assumed to be
60+
unimportant, so no need to worry about it. */
61+
/* See https://stackoverflow.com/questions/27680807/mkstemp-is-it-safe-to-close-descriptor-and-reopen-it-again */
62+
close(fd);
63+
64+
return file;
65+
}
66+
67+
char *SDL_SYS_CreateTempFolder(void)
68+
{
69+
char *folder = SDL_strdup("/tmp/tmp.XXXXXX");
70+
71+
if (!folder) {
72+
return NULL;
73+
}
74+
75+
char *res = mkdtemp(folder);
76+
77+
if (!res) {
78+
SDL_free(folder);
79+
SDL_SetError("Could not mkdtemp(): %s", strerror(errno));
80+
return NULL;
81+
}
82+
83+
return folder;
84+
}

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)