Steam storage improvements

* Implemented EnumerateStorageDirectory()
* Implemented RemoveStoragePath()
* Fixed init failure if the application previously crashed with a write batch in progress
* Allow creation of multiple Steam storage objects, the write batch is complete when the last storage is closed
* Check to see if a file exists in GetStoragePathInfo()
This commit is contained in:
Sam Lantinga
2025-12-06 12:45:05 -08:00
parent 96b5c92780
commit eea8090f84
2 changed files with 102 additions and 9 deletions

View File

@@ -55,15 +55,20 @@ typedef struct STEAM_RemoteStorage
#include "SDL_steamstorage_proc.h"
} STEAM_RemoteStorage;
static SDL_AtomicInt SDL_steam_storage_refcount;
static bool STEAM_CloseStorage(void *userdata)
{
bool result = true;
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage *)userdata;
void *steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
bool end_batch = SDL_AtomicDecRef(&SDL_steam_storage_refcount);
if (steamremotestorage == NULL) {
result = SDL_SetError("SteamRemoteStorage unavailable");
} else if (!steam->SteamAPI_ISteamRemoteStorage_EndFileWriteBatch(steamremotestorage)) {
result = SDL_SetError("SteamRemoteStorage()->EndFileWriteBatch() failed");
} else if (end_batch) {
if (!steam->SteamAPI_ISteamRemoteStorage_EndFileWriteBatch(steamremotestorage)) {
result = SDL_SetError("SteamRemoteStorage()->EndFileWriteBatch() failed");
}
}
SDL_UnloadObject(steam->libsteam_api);
SDL_free(steam);
@@ -75,6 +80,67 @@ static bool STEAM_StorageReady(void *userdata)
return true;
}
static bool STEAM_EnumerateStorageDirectory(void *userdata, const char *path, SDL_EnumerateDirectoryCallback callback, void *callback_userdata)
{
bool result = true;
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage *)userdata;
void *steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
if (steamremotestorage == NULL) {
return SDL_SetError("SteamRemoteStorage unavailable");
}
const char *prefix;
if (SDL_strcmp(path, ".") == 0) {
prefix = "";
} else {
prefix = path;
while (*prefix == '/') {
++prefix;
}
}
size_t prefixlen = SDL_strlen(prefix);
while (prefixlen > 0 && prefix[prefixlen - 1] == '/') {
--prefixlen;
}
bool done = false;
Sint32 count = steam->SteamAPI_ISteamRemoteStorage_GetFileCount(steamremotestorage);
for (Sint32 i = 0; i < count && !done; ++i) {
const char *file = steam->SteamAPI_ISteamRemoteStorage_GetFileNameAndSize(steamremotestorage, i, NULL);
if (!file) {
continue;
}
const char *fname;
if (prefixlen > 0) {
// Make sure the prefix matches
if (SDL_strncmp(prefix, file, prefixlen) != 0 || *(file + prefixlen) != '/') {
continue;
}
fname = file + prefixlen + 1;
} else {
// Make sure this is a top-level file
if (SDL_strchr(file, '/') != NULL) {
continue;
}
fname = file;
}
switch (callback(callback_userdata, path, fname)) {
case SDL_ENUM_SUCCESS:
done = true;
break;
case SDL_ENUM_FAILURE:
result = false;
done = true;
break;
default:
break;
}
}
return result;
}
static bool STEAM_GetStoragePathInfo(void *userdata, const char *path, SDL_PathInfo *info)
{
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage *)userdata;
@@ -83,10 +149,16 @@ static bool STEAM_GetStoragePathInfo(void *userdata, const char *path, SDL_PathI
return SDL_SetError("SteamRemoteStorage unavailable");
}
if (!steam->SteamAPI_ISteamRemoteStorage_FileExists(steamremotestorage, path)) {
return SDL_SetError("Can't stat");
}
if (info) {
SDL_zerop(info);
info->type = SDL_PATHTYPE_FILE;
info->size = steam->SteamAPI_ISteamRemoteStorage_GetFileSize(steamremotestorage, path);
Sint64 mtime = steam->SteamAPI_ISteamRemoteStorage_GetFileTimestamp(steamremotestorage, path);
info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(mtime);
}
return true;
}
@@ -129,6 +201,19 @@ static bool STEAM_WriteStorageFile(void *userdata, const char *path, const void
return result;
}
static bool STEAM_RemoveStoragePath(void *userdata, const char *path)
{
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage *)userdata;
void *steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
if (steamremotestorage == NULL) {
return SDL_SetError("SteamRemoteStorage unavailable");
}
if (!steam->SteamAPI_ISteamRemoteStorage_FileDelete(steamremotestorage, path)) {
return SDL_SetError("SteamRemoteStorage()->FileDelete() failed");
}
return true;
}
static Uint64 STEAM_GetStorageSpaceRemaining(void *userdata)
{
Uint64 total, remaining;
@@ -149,12 +234,12 @@ static const SDL_StorageInterface STEAM_user_iface = {
sizeof(SDL_StorageInterface),
STEAM_CloseStorage,
STEAM_StorageReady,
NULL, // enumerate
STEAM_EnumerateStorageDirectory,
STEAM_GetStoragePathInfo,
STEAM_ReadStorageFile,
STEAM_WriteStorageFile,
NULL, // mkdir
NULL, // remove
STEAM_RemoveStoragePath,
NULL, // rename
NULL, // copy
STEAM_GetStorageSpaceRemaining
@@ -198,14 +283,16 @@ static SDL_Storage *STEAM_User_Create(const char *org, const char *app, SDL_Prop
SDL_SetError("Steam cloud is disabled for this application");
goto steamfail;
}
if (!steam->SteamAPI_ISteamRemoteStorage_BeginFileWriteBatch(steamremotestorage)) {
SDL_SetError("SteamRemoteStorage()->BeginFileWriteBatch() failed");
result = SDL_OpenStorage(&STEAM_user_iface, steam);
if (!result) {
goto steamfail;
}
result = SDL_OpenStorage(&STEAM_user_iface, steam);
if (result == NULL) {
goto steamfail;
if (SDL_AtomicIncRef(&SDL_steam_storage_refcount) == 0) {
if (!steam->SteamAPI_ISteamRemoteStorage_BeginFileWriteBatch(steamremotestorage)) {
// We probably already have a batch in progress (maybe we crashed earlier?)
}
}
return result;

View File

@@ -6,9 +6,15 @@ STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_IsCloudEnabledForApp, (void*))
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_BeginFileWriteBatch, (void*))
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_EndFileWriteBatch, (void*))
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_FileExists, (void*, const char*))
STEAM_PROC(Sint32, SteamAPI_ISteamRemoteStorage_GetFileSize, (void*, const char*))
STEAM_PROC(Sint64, SteamAPI_ISteamRemoteStorage_GetFileTimestamp, (void*, const char *))
STEAM_PROC(Sint32, SteamAPI_ISteamRemoteStorage_FileRead, (void*, const char*, void*, Sint32))
STEAM_PROC(Sint32, SteamAPI_ISteamRemoteStorage_FileWrite, (void*, const char*, const void*, Sint32))
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_FileDelete, (void*, const char*))
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_GetQuota, (void*, Uint64*, Uint64*))
STEAM_PROC(Sint32, SteamAPI_ISteamRemoteStorage_GetFileCount, (void*))
STEAM_PROC(const char *, SteamAPI_ISteamRemoteStorage_GetFileNameAndSize, (void*, int, Sint32*))
#undef STEAM_PROC