|
|
@@ -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,15 +283,17 @@ 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");
|
|
|
- goto steamfail;
|
|
|
- }
|
|
|
|
|
|
result = SDL_OpenStorage(&STEAM_user_iface, steam);
|
|
|
- if (result == NULL) {
|
|
|
+ if (!result) {
|
|
|
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;
|
|
|
|
|
|
steamfail:
|