Added portable file and directory operations (thanks @icculus!)

main
Sam Lantinga 2024-03-16 08:15:13 -07:00
parent fe5c34d4bd
commit db0c1d7aeb
30 changed files with 841 additions and 2 deletions

View File

@ -50,7 +50,9 @@ LOCAL_SRC_FILES := \
$(wildcard $(LOCAL_PATH)/src/misc/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/power/*.c) \
$(wildcard $(LOCAL_PATH)/src/power/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/filesystem/*.c) \
$(wildcard $(LOCAL_PATH)/src/filesystem/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/filesystem/posix/*.c) \
$(wildcard $(LOCAL_PATH)/src/sensor/*.c) \
$(wildcard $(LOCAL_PATH)/src/sensor/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/render/*.c) \

View File

@ -482,6 +482,7 @@ sdl_glob_sources(
"${SDL3_SOURCE_DIR}/src/dynapi/*.c"
"${SDL3_SOURCE_DIR}/src/events/*.c"
"${SDL3_SOURCE_DIR}/src/file/*.c"
"${SDL3_SOURCE_DIR}/src/filesystem/*.c"
"${SDL3_SOURCE_DIR}/src/joystick/*.c"
"${SDL3_SOURCE_DIR}/src/haptic/*.c"
"${SDL3_SOURCE_DIR}/src/hidapi/*.c"
@ -1288,6 +1289,14 @@ if(ANDROID)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/android/*.c")
set(HAVE_SDL_FILESYSTEM TRUE)
set(SDL_FSOPS_POSIX 1) # !!! FIXME: this might need something else for .apk data?
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
set(SDL_FSOPS_POSIX 1) # !!! FIXME: this might need something else for .apk data?
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
if(SDL_HAPTIC)
set(SDL_HAPTIC_ANDROID 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/android/*.c")
@ -1446,6 +1455,14 @@ elseif(EMSCRIPTEN)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/emscripten/*.c")
set(HAVE_SDL_FILESYSTEM TRUE)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
if(SDL_CAMERA)
set(SDL_CAMERA_DRIVER_EMSCRIPTEN 1)
set(HAVE_CAMERA TRUE)
@ -1762,6 +1779,10 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
endif()
set(HAVE_SDL_STORAGE 1)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
set(SDL_TIMER_UNIX 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c")
set(HAVE_SDL_TIMERS TRUE)
@ -1976,11 +1997,15 @@ elseif(WINDOWS)
set(SDL_FILESYSTEM_WINDOWS 1)
if(WINDOWS_STORE)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/winrt/*.cpp")
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/windows/SDL_sysfsops.c")
else()
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/windows/*.c")
endif()
set(HAVE_SDL_FILESYSTEM TRUE)
set(SDL_FSOPS_WINDOWS 1)
set(HAVE_SDL_FSOPS TRUE)
set(SDL_STORAGE_GENERIC 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c")
if(NOT WINDOWS_STORE)
@ -2230,6 +2255,10 @@ elseif(APPLE)
endif()
set(HAVE_SDL_STORAGE 1)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
if(SDL_SENSOR)
if(IOS OR VISIONOS)
set(SDL_SENSOR_COREMOTION 1)
@ -2422,6 +2451,14 @@ elseif(HAIKU)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/haiku/*.cc")
set(HAVE_SDL_FILESYSTEM TRUE)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
set(SDL_TIMER_HAIKU 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/haiku/*.c")
set(HAVE_SDL_TIMERS TRUE)
@ -2454,6 +2491,14 @@ elseif(RISCOS)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/riscos/*.c")
set(HAVE_SDL_FILESYSTEM TRUE)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
set(SDL_TIMER_UNIX 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c")
set(HAVE_SDL_TIMERS TRUE)
@ -2491,6 +2536,10 @@ elseif(VITA)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/vita/*.c")
set(HAVE_SDL_FILESYSTEM TRUE)
# !!! FIXME: do we need a FSops implementation for this?
# !!! FIXME: do we need a FSops implementation for this?
if(SDL_JOYSTICK)
set(SDL_JOYSTICK_VITA 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/vita/*.c")
@ -2625,6 +2674,10 @@ elseif(PSP)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/psp/*.c")
set(HAVE_SDL_FILESYSTEM TRUE)
# !!! FIXME: do we need a FSops implementation for this?
# !!! FIXME: do we need a FSops implementation for this?
if(SDL_JOYSTICK)
set(SDL_JOYSTICK_PSP 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/psp/*.c")
@ -2688,6 +2741,10 @@ elseif(PS2)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/ps2/*.c")
set(HAVE_SDL_FILESYSTEM TRUE)
# !!! FIXME: do we need a FSops implementation for this?
# !!! FIXME: do we need a FSops implementation for this?
if(SDL_JOYSTICK)
set(SDL_JOYSTICK_PS2 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/ps2/*.c")
@ -2739,6 +2796,10 @@ elseif(N3DS)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/n3ds/*.c")
set(HAVE_SDL_FILESYSTEM TRUE)
# !!! FIXME: do we need a FSops implementation for this?
# !!! FIXME: do we need a FSops implementation for this?
if(SDL_JOYSTICK)
set(SDL_JOYSTICK_N3DS 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/n3ds/*.c")
@ -2763,6 +2824,10 @@ elseif(N3DS)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/n3ds/*.c")
set(HAVE_SDL_TIMERS TRUE)
set(SDL_FSOPS_POSIX 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c")
set(HAVE_SDL_FSOPS TRUE)
if(SDL_SENSOR)
set(SDL_SENSOR_N3DS 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/sensor/n3ds/*.c")
@ -2850,6 +2915,14 @@ if(NOT HAVE_SDL_STORAGE)
set(SDL_STORAGE_GENERIC 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c")
endif()
if(NOT HAVE_SDL_FSOPS)
set(SDL_FSOPS_DUMMY 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/SDL_sysfsops.c")
endif()
if(NOT HAVE_SDL_FSOPS)
set(SDL_FSOPS_DUMMY 1)
sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/SDL_sysfsops.c")
endif()
if(NOT HAVE_SDL_LOCALE)
set(SDL_LOCALE_DUMMY 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/dummy/*.c")

View File

@ -422,6 +422,7 @@
<ClInclude Include="..\..\src\events\SDL_mouse_c.h" />
<ClInclude Include="..\..\src\events\SDL_touch_c.h" />
<ClInclude Include="..\..\src\events\SDL_windowevents_c.h" />
<ClInclude Include="..\..\src\filesystem\SDL_filesystem.h" />
<ClInclude Include="..\..\src\haptic\SDL_haptic_c.h" />
<ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
<ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
@ -504,6 +505,8 @@
</ClCompile>
<ClCompile Include="..\..\src\camera\dummy\SDL_camera_dummy.c" />
<ClCompile Include="..\..\src\camera\SDL_camera.c" />
<ClCompile Include="..\..\src\filesystem\SDL_filesystem.c" />
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c" />
<ClCompile Include="..\..\src\main\generic\SDL_sysmain_callbacks.c" />
<ClCompile Include="..\..\src\main\SDL_main_callbacks.c" />
<ClCompile Include="..\..\src\SDL_guid.c" />

View File

@ -4,6 +4,12 @@
<ClCompile Include="..\..\src\core\gdk\SDL_gdk.cpp" />
<ClCompile Include="..\..\src\core\windows\pch.c" />
<ClCompile Include="..\..\src\core\windows\pch_cpp.cpp" />
<ClCompile Include="..\..\src\filesystem\SDL_filesystem.c">
<Filter>filesystem</Filter>
</ClCompile>
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c">
<Filter>filesystem\windows</Filter>
</ClCompile>
<ClCompile Include="..\..\src\render\direct3d12\SDL_render_d3d12_xbox.cpp" />
<ClCompile Include="..\..\src\render\direct3d12\SDL_shaders_d3d12_xboxone.cpp" />
<ClCompile Include="..\..\src\render\direct3d12\SDL_shaders_d3d12_xboxseries.cpp" />
@ -313,6 +319,9 @@
<ClInclude Include="..\..\src\events\SDL_mouse_c.h" />
<ClInclude Include="..\..\src\events\SDL_touch_c.h" />
<ClInclude Include="..\..\src\events\SDL_windowevents_c.h" />
<ClInclude Include="..\..\src\filesystem\SDL_filesystem.h">
<Filter>filesystem</Filter>
</ClInclude>
<ClInclude Include="..\..\src\haptic\SDL_haptic_c.h" />
<ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
<ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />

View File

@ -121,6 +121,7 @@
<ClInclude Include="..\src\events\SDL_mouse_c.h" />
<ClInclude Include="..\src\events\SDL_touch_c.h" />
<ClInclude Include="..\src\events\SDL_windowevents_c.h" />
<ClInclude Include="..\src\filesystem\SDL_filesystem.h" />
<ClInclude Include="..\src\haptic\SDL_haptic_c.h" />
<ClInclude Include="..\src\haptic\SDL_syshaptic.h" />
<ClInclude Include="..\src\haptic\windows\SDL_dinputhaptic_c.h" />
@ -334,6 +335,8 @@
<PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)$(TargetName)_cpp.pch</PrecompiledHeaderOutputFile>
</ClCompile>
<ClCompile Include="..\src\file\SDL_iostream.c" />
<ClCompile Include="..\src\filesystem\SDL_filesystem.c" />
<ClCompile Include="..\src\filesystem\windows\SDL_sysfsops.c" />
<ClCompile Include="..\src\haptic\dummy\SDL_syshaptic.c" />
<ClCompile Include="..\src\haptic\SDL_haptic.c" />
<ClCompile Include="..\src\haptic\windows\SDL_dinputhaptic.c" />

View File

@ -19,6 +19,12 @@
<Filter Include="camera\dummy">
<UniqueIdentifier>{000031d805439b865ff4550d2f620000}</UniqueIdentifier>
</Filter>
<Filter Include="filesystem">
<UniqueIdentifier>{00004389761f0ae646deb5a3d65f0000}</UniqueIdentifier>
</Filter>
<Filter Include="filesystem\windows">
<UniqueIdentifier>{0000bc587ef6c558d75ce2e620cb0000}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\SDL3\SDL_begin_code.h">
@ -180,6 +186,9 @@
<ClInclude Include="..\src\camera\SDL_syscamera.h">
<Filter>camera</Filter>
</ClInclude>
<ClInclude Include="..\src\filesystem\SDL_filesystem.h">
<Filter>filesystem</Filter>
</ClInclude>
<ClInclude Include="..\src\joystick\SDL_gamepad_c.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -579,6 +588,12 @@
<ClCompile Include="..\src\events\SDL_windowevents.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\filesystem\SDL_filesystem.c">
<Filter>filesystem</Filter>
</ClCompile>
<ClCompile Include="..\src\filesystem\windows\SDL_sysfsops.c">
<Filter>filesystem\windows</Filter>
</ClCompile>
<ClCompile Include="..\src\filesystem\winrt\SDL_sysfilesystem.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@ -344,6 +344,7 @@
<ClInclude Include="..\..\src\events\SDL_mouse_c.h" />
<ClInclude Include="..\..\src\events\SDL_touch_c.h" />
<ClInclude Include="..\..\src\events\SDL_windowevents_c.h" />
<ClInclude Include="..\..\src\filesystem\SDL_filesystem.h" />
<ClInclude Include="..\..\src\haptic\SDL_haptic_c.h" />
<ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
<ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
@ -401,6 +402,8 @@
<ClCompile Include="..\..\src\camera\dummy\SDL_camera_dummy.c" />
<ClCompile Include="..\..\src\camera\mediafoundation\SDL_camera_mediafoundation.c" />
<ClCompile Include="..\..\src\camera\SDL_camera.c" />
<ClCompile Include="..\..\src\filesystem\SDL_filesystem.c" />
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c" />
<ClCompile Include="..\..\src\main\generic\SDL_sysmain_callbacks.c" />
<ClCompile Include="..\..\src\main\SDL_main_callbacks.c" />
<ClCompile Include="..\..\src\render\vulkan\SDL_render_vulkan.c" />

View File

@ -417,6 +417,9 @@
<ClInclude Include="..\..\src\camera\SDL_syscamera.h">
<Filter>camera</Filter>
</ClInclude>
<ClInclude Include="..\..\src\filesystem\SDL_filesystem.h">
<Filter>filesystem</Filter>
</ClInclude>
<ClInclude Include="..\..\src\main\SDL_main_callbacks.h">
<Filter>main</Filter>
</ClInclude>
@ -871,6 +874,12 @@
<ClCompile Include="..\..\src\camera\SDL_camera.c">
<Filter>camera</Filter>
</ClCompile>
<ClCompile Include="..\..\src\filesystem\SDL_filesystem.c">
<Filter>filesystem</Filter>
</ClCompile>
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c">
<Filter>filesystem\windows</Filter>
</ClCompile>
<ClCompile Include="..\..\src\main\generic\SDL_sysmain_callbacks.c">
<Filter>main\generic</Filter>
</ClCompile>

View File

@ -503,6 +503,9 @@
F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1B2B59ACE000FEAD97 /* yuv_rgb_lsx.h */; };
F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1C2B59ACE000FEAD97 /* yuv_rgb_common.h */; };
FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); };
000080903BC03006F24E0000 /* SDL_filesystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 00002B010DB1A70931C20000 /* SDL_filesystem.c */; };
00000D60346481EEC8FB0000 /* SDL_filesystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 0000BE1BF5193C6D0F4F0000 /* SDL_filesystem.h */; };
0000481D255AF155B42C0000 /* SDL_sysfsops.c in Sources */ = {isa = PBXBuildFile; fileRef = 0000F4E6AA3EF99DA3C80000 /* SDL_sysfsops.c */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -1034,6 +1037,9 @@
F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = "<group>"; };
F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
00002B010DB1A70931C20000 /* SDL_filesystem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_filesystem.c; path = SDL_filesystem.c; sourceTree = "<group>"; };
0000BE1BF5193C6D0F4F0000 /* SDL_filesystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_filesystem.h; path = SDL_filesystem.h; sourceTree = "<group>"; };
0000F4E6AA3EF99DA3C80000 /* SDL_sysfsops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_sysfsops.c; path = SDL_sysfsops.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -1858,6 +1864,9 @@
children = (
A7D8A7FD23E2513F00DCD162 /* cocoa */,
A7D8A7F723E2513F00DCD162 /* dummy */,
00002B010DB1A70931C20000 /* SDL_filesystem.c */,
0000BE1BF5193C6D0F4F0000 /* SDL_filesystem.h */,
000050A2BB34616138570000 /* posix */,
);
path = filesystem;
sourceTree = "<group>";
@ -2209,6 +2218,14 @@
path = resources;
sourceTree = "<group>";
};
000050A2BB34616138570000 /* posix */ = {
isa = PBXGroup;
children = (
0000F4E6AA3EF99DA3C80000 /* SDL_sysfsops.c */,
);
path = posix;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@ -2792,6 +2809,8 @@
000098E9DAA43EF6FF7F0000 /* SDL_camera.c in Sources */,
00001B2471F503DD3C1B0000 /* SDL_camera_dummy.c in Sources */,
00002B20A48E055EB0350000 /* SDL_camera_coremedia.m in Sources */,
000080903BC03006F24E0000 /* SDL_filesystem.c in Sources */,
0000481D255AF155B42C0000 /* SDL_sysfsops.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -236,6 +236,102 @@ typedef enum
*/
extern DECLSPEC char *SDLCALL SDL_GetUserFolder(SDL_Folder folder);
/* Abstract filesystem interface */
typedef enum SDL_PathType
{
SDL_PATHTYPE_FILE, /**< a normal file */
SDL_PATHTYPE_DIRECTORY, /**< a directory */
SDL_PATHTYPE_OTHER /**< something completely different like a device node (not a symlink, those are always followed) */
} SDL_PathType;
/* SDL file timestamps are 64-bit integers representing seconds since the Unix epoch (Jan 1, 1970) */
typedef Sint64 SDL_FileTimestamp;
typedef struct SDL_PathInfo
{
SDL_PathType type; /* the path type */
Uint64 size; /* the file size in bytes */
SDL_FileTimestamp create_time; /* the time when the path was created */
SDL_FileTimestamp modify_time; /* the last time the path was modified */
SDL_FileTimestamp access_time; /* the last time the path was read */
} SDL_PathInfo;
/**
* Create a directory.
*
* \param path the path of the directory to create
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC int SDLCALL SDL_CreateDirectory(const char *path);
/* Callback for filesystem enumeration. Return 1 to keep enumerating, 0 to stop enumerating (no error), -1 to stop enumerating and report an error. "origdir" is the directory being enumerated, "fname" is the enumerated entry. */
typedef int (SDLCALL *SDL_EnumerateDirectoryCallback)(void *userdata, void *reserved, const char *origdir, const char *fname);
/**
* Enumerate a directory.
*
* \param path the path of the directory to enumerate
* \param callback a function that is called for each entry in the directory
* \param userdata a pointer that is passed to `callback`
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC int SDLCALL SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata);
/**
* Remove a file or an empty directory.
*
* \param path the path of the directory to enumerate
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC int SDLCALL SDL_RemovePath(const char *path);
/**
* Rename a file or directory.
*
* \param oldpath the old path
* \param newpath the new path
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC int SDLCALL SDL_RenamePath(const char *oldpath, const char *newpath);
/**
* Get information about a filesystem path.
*
* \param path the path to query
* \param info a pointer filled in with information about the path
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC int SDLCALL SDL_GetPathInfo(const char *path, SDL_PathInfo *info);
/* some helper functions ... */
/* Converts an SDL file timestamp into a Windows FILETIME (100-nanosecond intervals since January 1, 1601). Fills in the two 32-bit values of the FILETIME structure.
*
* \param ftime the time to convert
* \param low a pointer filled in with the low portion of the Windows FILETIME value
* \param high a pointer filled in with the high portion of the Windows FILETIME value
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC void SDLCALL SDL_FileTimeToWindows(Sint64 ftime, Uint32 *low, Uint32 *high);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}

View File

@ -469,6 +469,11 @@
#cmakedefine SDL_STORAGE_GENERIC @SDL_STORAGE_GENERIC@
#cmakedefine SDL_STORAGE_STEAM @SDL_STORAGE_STEAM@
/* Enable system FSops support */
#cmakedefine SDL_FSOPS_POSIX @SDL_FSOPS_POSIX@
#cmakedefine SDL_FSOPS_WINDOWS @SDL_FSOPS_WINDOWS@
#cmakedefine SDL_FSOPS_DUMMY @SDL_FSOPS_DUMMY@
/* Enable camera subsystem */
#cmakedefine SDL_CAMERA_DRIVER_DUMMY @SDL_CAMERA_DRIVER_DUMMY@
/* !!! FIXME: for later cmakedefine SDL_CAMERA_DRIVER_DISK @SDL_CAMERA_DRIVER_DISK@ */

View File

@ -187,6 +187,7 @@
/* Enable the filesystem driver */
#define SDL_FILESYSTEM_ANDROID 1
#define SDL_FSOPS_POSIX 1
/* Enable the camera driver */
#define SDL_CAMERA_DRIVER_ANDROID 1

View File

@ -206,6 +206,7 @@
/* Enable system filesystem support */
#define SDL_FILESYSTEM_EMSCRIPTEN 1
#define SDL_FSOPS_POSIX 1
/* Enable the camera driver */
#define SDL_CAMERA_DRIVER_EMSCRIPTEN 1

View File

@ -207,6 +207,7 @@
/* enable filesystem support */
#define SDL_FILESYSTEM_COCOA 1
#define SDL_FSOPS_POSIX 1
/* enable camera support */
#ifndef SDL_PLATFORM_TVOS

View File

@ -264,6 +264,7 @@
/* enable filesystem support */
#define SDL_FILESYSTEM_COCOA 1
#define SDL_FSOPS_POSIX 1
/* enable camera support */
#define SDL_CAMERA_DRIVER_COREMEDIA 1

View File

@ -88,6 +88,7 @@ typedef unsigned int uintptr_t;
/* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */
#define SDL_FILESYSTEM_DUMMY 1
#define SDL_FSOPS_DUMMY 1
/* Enable the camera driver (src/camera/dummy/\*.c) */
#define SDL_CAMERA_DRIVER_DUMMY 1

View File

@ -85,6 +85,7 @@ typedef unsigned long uintptr_t;
/* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */
#define SDL_FILESYSTEM_DUMMY 1
#define SDL_FSOPS_DUMMY 1
/* Enable the camera driver (src/camera/dummy/\*.c) */
#define SDL_CAMERA_DRIVER_DUMMY 1

View File

@ -312,6 +312,7 @@ typedef unsigned int uintptr_t;
/* Enable filesystem support */
#define SDL_FILESYSTEM_WINDOWS 1
#define SDL_FSOPS_WINDOWS 1
/* Enable the camera driver */
#define SDL_CAMERA_DRIVER_MEDIAFOUNDATION 1

View File

@ -244,6 +244,7 @@
/* Enable filesystem support */
#define SDL_FILESYSTEM_WINDOWS 1
#define SDL_FSOPS_WINDOWS 1
/* Enable the camera driver (src/camera/dummy/\*.c) */ /* !!! FIXME */
#define SDL_CAMERA_DRIVER_DUMMY 1

View File

@ -213,6 +213,10 @@
/* Enable system power support */
#define SDL_POWER_WINRT 1
/* Enable filesystem support */
#define SDL_FILESYSTEM_WINDOWS 1
#define SDL_FSOPS_WINDOWS 1
/* Enable the camera driver (src/camera/dummy/\*.c) */ /* !!! FIXME */
#define SDL_CAMERA_DRIVER_DUMMY 1

View File

@ -228,6 +228,8 @@
/* Enable filesystem support */
/* #define SDL_FILESYSTEM_WINDOWS 1*/
#define SDL_FILESYSTEM_XBOX 1
#define SDL_FSOPS_WINDOWS 1
/* Disable IME as not supported yet (TODO: Xbox IME?) */
#define SDL_DISABLE_WINDOWS_IME 1

View File

@ -987,6 +987,12 @@ SDL3_0.0.0 {
SDL_GetStorageFileSize;
SDL_ReadStorageFile;
SDL_GetStorageSpaceRemaining;
SDL_CreateDirectory;
SDL_EnumerateDirectory;
SDL_RemovePath;
SDL_RenamePath;
SDL_GetPathInfo;
SDL_FileTimeToWindows;
# extra symbols go here (don't modify this line)
local: *;
};

View File

@ -1012,3 +1012,9 @@
#define SDL_GetStorageFileSize SDL_GetStorageFileSize_REAL
#define SDL_ReadStorageFile SDL_ReadStorageFile_REAL
#define SDL_GetStorageSpaceRemaining SDL_GetStorageSpaceRemaining_REAL
#define SDL_CreateDirectory SDL_CreateDirectory_REAL
#define SDL_EnumerateDirectory SDL_EnumerateDirectory_REAL
#define SDL_RemovePath SDL_RemovePath_REAL
#define SDL_RenamePath SDL_RenamePath_REAL
#define SDL_GetPathInfo SDL_GetPathInfo_REAL
#define SDL_FileTimeToWindows SDL_FileTimeToWindows_REAL

View File

@ -1037,3 +1037,9 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_StorageReady,(SDL_Storage *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetStorageFileSize,(SDL_Storage *a, const char *b, Uint64 *c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_ReadStorageFile,(SDL_Storage *a, const char *b, void *c, Uint64 d),(a,b,c,d),return)
SDL_DYNAPI_PROC(Uint64,SDL_GetStorageSpaceRemaining,(SDL_Storage *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_CreateDirectory,(const char *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_EnumerateDirectory,(const char *a, SDL_EnumerateDirectoryCallback b, void *c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RemovePath,(const char *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_RenamePath,(const char *a, const char *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_GetPathInfo,(const char *a, SDL_PathInfo *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_FileTimeToWindows,(Sint64 a, Uint32 *b, Uint32 *c),(a,b,c),)

View File

@ -0,0 +1,91 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL_sysfilesystem.h"
void SDL_FileTimeToWindows(Sint64 ftime, Uint32 *low, Uint32 *high)
{
const Sint64 delta_1601_epoch_s = 11644473600ull; // [seconds] (seconds between 1/1/1601 and 1/1/1970, 11644473600 seconds)
Sint64 cvt = (ftime + delta_1601_epoch_s) * (SDL_NS_PER_SECOND / 100ull); // [100ns] (adjust to epoch and convert nanoseconds to 1/100th nanosecond units).
// Windows FILETIME is unsigned, so if we're trying to show a timestamp from before before the
// Windows epoch, (Jan 1, 1601), clamp it to zero so it doesn't go way into the future.
if (cvt < 0) {
cvt = 0;
}
if (low) {
*low = (Uint32) cvt;
}
if (high) {
*high = (Uint32) (cvt >> 32);
}
}
int SDL_RemovePath(const char *path)
{
if (!path) {
return SDL_InvalidParamError("path");
}
return SDL_SYS_FSremove(path);
}
int SDL_RenamePath(const char *oldpath, const char *newpath)
{
if (!oldpath) {
return SDL_InvalidParamError("oldpath");
} else if (!newpath) {
return SDL_InvalidParamError("newpath");
}
return SDL_SYS_FSrename(oldpath, newpath);
}
int SDL_CreateDirectory(const char *path)
{
/* TODO: Recursively create subdirectories */
if (!path) {
return SDL_InvalidParamError("path");
}
return SDL_SYS_FSmkdir(path);
}
int SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata)
{
if (!path) {
return SDL_InvalidParamError("path");
} else if (!callback) {
return SDL_InvalidParamError("callback");
}
return SDL_SYS_FSenumerate(path, path, callback, userdata);
}
int SDL_GetPathInfo(const char *path, SDL_PathInfo *stat)
{
if (!path) {
return SDL_InvalidParamError("path");
} else if (!stat) {
return SDL_InvalidParamError("stat");
}
return SDL_SYS_FSstat(path, stat);
}

View File

@ -0,0 +1,32 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SDL_sysfilesystem_h_
#define SDL_sysfilesystem_h_
int SDL_SYS_FSenumerate(const char *fullpath, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata);
int SDL_SYS_FSremove(const char *fullpath);
int SDL_SYS_FSrename(const char *oldfullpath, const char *newfullpath);
int SDL_SYS_FSmkdir(const char *fullpath);
int SDL_SYS_FSstat(const char *fullpath, SDL_PathInfo *info);
#endif

View File

@ -0,0 +1,54 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#if defined(SDL_FSOPS_DUMMY)
#include "../SDL_sysfilesystem.h"
int SDL_SYS_FSenumerate(const char *fullpath, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata)
{
return SDL_Unsupported();
}
int SDL_SYS_FSremove(const char *fullpath)
{
return SDL_Unsupported();
}
int SDL_SYS_FSrename(const char *oldfullpath, const char *newfullpath)
{
return SDL_Unsupported();
}
int SDL_SYS_FSmkdir(const char *fullpath)
{
return SDL_Unsupported();
}
int SDL_SYS_FSstat(const char *fullpath, SDL_PathInfo *st)
{
return SDL_Unsupported();
}
#endif

View File

@ -0,0 +1,138 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#if defined(SDL_FSOPS_POSIX)
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
#include "../SDL_sysfilesystem.h"
int SDL_SYS_FSenumerate(const char *fullpath, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata)
{
int retval = 1;
DIR *dir = opendir(fullpath);
if (!dir) {
return SDL_SetError("Can't open directory: %s", strerror(errno));
}
struct dirent *ent;
while ((retval == 1) && ((ent = readdir(dir)) != NULL))
{
const char *name = ent->d_name;
if ((SDL_strcmp(name, ".") == 0) || (SDL_strcmp(name, "..") == 0)) {
continue;
}
retval = cb(userdata, NULL, dirname, name);
}
closedir(dir);
return retval;
}
int SDL_SYS_FSremove(const char *fullpath)
{
int rc = remove(fullpath);
if (rc < 0) {
const int origerrno = errno;
if (origerrno == ENOENT) {
char *parent = SDL_strdup(fullpath);
if (!parent) {
return -1;
}
char *ptr = SDL_strrchr(parent, '/');
if (ptr) {
*ptr = '\0'; // chop off thing we were removing, see if parent is there.
}
struct stat statbuf;
rc = stat(ptr ? parent : ".", &statbuf);
SDL_free(parent);
if (rc == 0) {
return 0; // it's already gone, and parent exists, consider it success.
}
}
return SDL_SetError("Can't remove path: %s", strerror(origerrno));
}
return 0;
}
int SDL_SYS_FSrename(const char *oldfullpath, const char *newfullpath)
{
if (rename(oldfullpath, newfullpath) < 0) {
return SDL_SetError("Can't remove path: %s", strerror(errno));
}
return 0;
}
int SDL_SYS_FSmkdir(const char *fullpath)
{
const int rc = mkdir(fullpath, 0770);
if (rc < 0) {
const int origerrno = errno;
if (origerrno == EEXIST) {
struct stat statbuf;
if ((stat(fullpath, &statbuf) == 0) && (S_ISDIR(statbuf.st_mode))) {
return 0; // it already exists and it's a directory, consider it success.
}
}
return SDL_SetError("Can't create directory: %s", strerror(origerrno));
}
return 0;
}
int SDL_SYS_FSstat(const char *fullpath, SDL_PathInfo *info)
{
struct stat statbuf;
const int rc = stat(fullpath, &statbuf);
if (rc < 0) {
return SDL_SetError("Can't stat: %s", strerror(errno));
} else if (S_ISREG(statbuf.st_mode)) {
info->type = SDL_PATHTYPE_FILE;
info->size = (Uint64) statbuf.st_size;
} else if (S_ISDIR(statbuf.st_mode)) {
info->type = SDL_PATHTYPE_DIRECTORY;
info->size = 0;
} else {
info->type = SDL_PATHTYPE_OTHER;
info->size = (Uint64) statbuf.st_size;
}
// SDL file time is seconds since the Unix epoch, so we're already good here.
// Note that this will fail on machines with 32-bit time_t in 2038, but that's not
// an SDL bug; those machines need to be fixed or everything will fail in the same way.
info->create_time = (Sint64) statbuf.st_ctime;
info->modify_time = (Sint64) statbuf.st_mtime;
info->access_time = (Sint64) statbuf.st_atime;
return 0;
}
#endif

View File

@ -0,0 +1,188 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#if defined(SDL_FSOPS_WINDOWS)
#include "../../core/windows/SDL_windows.h"
#include "../SDL_sysfilesystem.h"
int SDL_SYS_FSenumerate(const char *fullpath, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata)
{
int retval = 1;
if (*fullpath == '\0') { // if empty (completely at the root), we need to enumerate drive letters.
const DWORD drives = GetLogicalDrives();
char name[3] = { 0, ':', '\0' };
for (int i = 'A'; (retval == 1) && (i <= 'Z'); i++) {
if (drives & (1 << (i - 'A'))) {
name[0] = (char) i;
retval = cb(userdata, NULL, dirname, name);
}
}
} else {
const size_t patternlen = SDL_strlen(fullpath) + 3;
char *pattern = (char *) SDL_malloc(patternlen);
if (!pattern) {
return -1;
}
// you need a wildcard to enumerate through FindFirstFileEx(), but the wildcard is only checked in the
// filename element at the end of the path string, so always tack on a "\\*" to get everything, and
// also prevent any wildcards inserted by the app from being respected.
SDL_snprintf(pattern, patternlen, "%s\\*", fullpath);
WCHAR *wpattern = WIN_UTF8ToString(pattern);
SDL_free(pattern);
if (!wpattern) {
return -1;
}
WIN32_FIND_DATAW entw;
HANDLE dir = FindFirstFileExW(wpattern, FindExInfoStandard, &entw, FindExSearchNameMatch, NULL, 0);
SDL_free(wpattern);
if (dir == INVALID_HANDLE_VALUE) {
return WIN_SetError("Failed to enumerate directory");
}
do {
const WCHAR *fn = entw.cFileName;
if (fn[0] == '.') { // ignore "." and ".."
if ((fn[1] == '\0') || ((fn[1] == '.') && (fn[2] == '\0'))) {
continue;
}
}
char *utf8fn = WIN_StringToUTF8(fn);
if (!utf8fn) {
retval = -1;
} else {
retval = cb(userdata, NULL, dirname, utf8fn);
SDL_free(utf8fn);
}
} while ((retval == 1) && (FindNextFileW(dir, &entw) != 0));
FindClose(dir);
}
return retval;
}
int SDL_SYS_FSremove(const char *fullpath)
{
WCHAR *wpath = WIN_UTF8ToString(fullpath);
if (!wpath) {
return -1;
}
WIN32_FILE_ATTRIBUTE_DATA info;
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &info)) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
// Note that ERROR_PATH_NOT_FOUND means a parent dir is missing, and we consider that an error.
return 0; // thing is already gone, call it a success.
}
return WIN_SetError("Couldn't get path's attributes");
}
const int isdir = (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
const BOOL rc = isdir ? RemoveDirectoryW(wpath) : DeleteFileW(wpath);
SDL_free(wpath);
return !rc ? WIN_SetError("Couldn't remove path") : 0;
}
int SDL_SYS_FSrename(const char *oldfullpath, const char *newfullpath)
{
WCHAR *woldpath = WIN_UTF8ToString(oldfullpath);
if (!woldpath) {
return -1;
}
WCHAR *wnewpath = WIN_UTF8ToString(newfullpath);
if (!wnewpath) {
SDL_free(woldpath);
return -1;
}
const BOOL rc = MoveFileExW(woldpath, wnewpath, MOVEFILE_REPLACE_EXISTING);
SDL_free(wnewpath);
SDL_free(woldpath);
return !rc ? WIN_SetError("Couldn't rename path") : 0;
}
int SDL_SYS_FSmkdir(const char *fullpath)
{
WCHAR *wpath = WIN_UTF8ToString(fullpath);
if (!wpath) {
return -1;
}
const DWORD rc = CreateDirectoryW(wpath, NULL);
SDL_free(wpath);
return !rc ? WIN_SetError("Couldn't create directory") : 0;
}
static Sint64 FileTimeToSDLTime(const FILETIME *ft)
{
const Uint64 delta_1601_epoch_100ns = 11644473600ull * 10000000ull; // [100ns] (100-ns chunks between 1/1/1601 and 1/1/1970, 11644473600 seconds * 10000000)
ULARGE_INTEGER large;
large.LowPart = ft->dwLowDateTime;
large.HighPart = ft->dwHighDateTime;
if (large.QuadPart == 0) {
return 0; // unsupported on this filesystem...0 is fine, I guess.
}
return (Sint64) ((((Uint64)large.QuadPart) - delta_1601_epoch_100ns) / (SDL_NS_PER_SECOND / 100ull)); // [secs] (adjust to epoch and convert 1/100th nanosecond units to seconds).
}
int SDL_SYS_FSstat(const char *fullpath, SDL_PathInfo *info)
{
WCHAR *wpath = WIN_UTF8ToString(fullpath);
if (!wpath) {
return -1;
}
WIN32_FILE_ATTRIBUTE_DATA winstat;
const BOOL rc = GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat);
SDL_free(wpath);
if (!rc) {
return WIN_SetError("Can't stat");
}
if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
info->type = SDL_PATHTYPE_DIRECTORY;
info->size = 0;
} else if (winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE)) {
info->type = SDL_PATHTYPE_OTHER;
info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow);
} else {
info->type = SDL_PATHTYPE_FILE;
info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow);
}
info->create_time = FileTimeToSDLTime(&winstat.ftCreationTime);
info->modify_time = FileTimeToSDLTime(&winstat.ftLastWriteTime);
info->access_time = FileTimeToSDLTime(&winstat.ftLastAccessTime);
return 1;
}
#endif

View File

@ -15,11 +15,54 @@
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_test.h>
static int SDLCALL enum_callback(void *userdata, void *reserved, const char *origdir, const char *fname)
{
SDL_PathInfo info;
char *fullpath = NULL;
/* you can use '/' for a path separator on Windows, but to make the log output look correct, we'll #ifdef this... */
#ifdef SDL_PLATFORM_WINDOWS
const char *pathsep = "\\";
#else
const char *pathsep = "/";
#endif
if (SDL_asprintf(&fullpath, "%s%s%s", origdir, *origdir ? pathsep : "", fname) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
return -1;
}
if (SDL_GetPathInfo(fullpath, &info) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't stat '%s': %s", fullpath, SDL_GetError());
} else {
const char *type;
if (info.type == SDL_PATHTYPE_FILE) {
type = "FILE";
} else if (info.type == SDL_PATHTYPE_DIRECTORY) {
type = "DIRECTORY";
} else {
type = "OTHER";
}
SDL_Log("%s (type=%s, size=%" SDL_PRIu64 ", create=%" SDL_PRIu64 ", mod=%" SDL_PRIu64 ", access=%" SDL_PRIu64 ")",
fullpath, type, info.size, info.modify_time, info.create_time, info.access_time);
if (info.type == SDL_PATHTYPE_DIRECTORY) {
if (SDL_EnumerateDirectory(fullpath, enum_callback, userdata) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Enumeration failed!");
}
}
}
SDL_free(fullpath);
return 1; /* keep going */
}
int main(int argc, char *argv[])
{
SDLTest_CommonState *state;
char *base_path;
char *pref_path;
char *base_path;
/* Initialize test framework */
state = SDLTest_CommonCreateState(argv, 0);
@ -46,7 +89,6 @@ int main(int argc, char *argv[])
SDL_GetError());
} else {
SDL_Log("base path: '%s'\n", base_path);
SDL_free(base_path);
}
pref_path = SDL_GetPrefPath("libsdl", "test_filesystem");
@ -67,6 +109,31 @@ int main(int argc, char *argv[])
SDL_free(pref_path);
}
if (base_path) {
if (SDL_EnumerateDirectory(base_path, enum_callback, NULL) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Base path enumeration failed!");
}
/* !!! FIXME: put this in a subroutine and make it test more thoroughly (and put it in testautomation). */
if (SDL_CreateDirectory("testfilesystem-test") == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateDirectory('testfilesystem-test') failed: %s", SDL_GetError());
} else if (SDL_CreateDirectory("testfilesystem-test/1") == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateDirectory('testfilesystem-test/1') failed: %s", SDL_GetError());
} else if (SDL_CreateDirectory("testfilesystem-test/1") == -1) { /* THIS SHOULD NOT FAIL! Making a directory that already exists should succeed here. */
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateDirectory('testfilesystem-test/1') failed: %s", SDL_GetError());
} else if (SDL_RenamePath("testfilesystem-test/1", "testfilesystem-test/2") == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_RenamePath('testfilesystem-test/1', 'testfilesystem-test/2') failed: %s", SDL_GetError());
} else if (SDL_RemovePath("testfilesystem-test/2") == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_RemovePath('testfilesystem-test/2') failed: %s", SDL_GetError());
} else if (SDL_RemovePath("testfilesystem-test") == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_RemovePath('testfilesystem-test') failed: %s", SDL_GetError());
} else if (SDL_RemovePath("testfilesystem-test") == -1) { /* THIS SHOULD NOT FAIL! Removing a directory that is already gone should succeed here. */
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_RemovePath('testfilesystem-test') failed: %s", SDL_GetError());
}
}
SDL_free(base_path);
SDL_Quit();
SDLTest_CommonDestroyState(state);
return 0;