diff --git a/src/LibHac/Fs/AccessLog.cs b/src/LibHac/Fs/AccessLog.cs
index 693766dc..bfed8313 100644
--- a/src/LibHac/Fs/AccessLog.cs
+++ b/src/LibHac/Fs/AccessLog.cs
@@ -1135,5 +1135,33 @@ namespace LibHac.Fs.Impl
(byte)',', (byte)' ', (byte)'f', (byte)'u', (byte)'n', (byte)'c', (byte)'t', (byte)'i',
(byte)'o', (byte)'n', (byte)':', (byte)' ', (byte)'"'
};
+
+ /// ", cachestoragelist_handle: 0x"
+ public static ReadOnlySpan LogCacheStorageListHandle =>
+ new[]
+ {
+ (byte)',', (byte)' ', (byte)'c', (byte)'a', (byte)'c', (byte)'h', (byte)'e', (byte)'s',
+ (byte)'t', (byte)'o', (byte)'r', (byte)'a', (byte)'g', (byte)'e', (byte)'l', (byte)'i',
+ (byte)'s', (byte)'t', (byte)'_', (byte)'h', (byte)'a', (byte)'n', (byte)'d', (byte)'l',
+ (byte)'e', (byte)':', (byte)' ', (byte)'0', (byte)'x'
+ };
+
+ /// ", infobuffercount: 0x"
+ public static ReadOnlySpan LogInfoBufferCount =>
+ new[]
+ {
+ (byte)',', (byte)' ', (byte)'i', (byte)'n', (byte)'f', (byte)'o', (byte)'b', (byte)'u',
+ (byte)'f', (byte)'f', (byte)'e', (byte)'r', (byte)'c', (byte)'o', (byte)'u', (byte)'n',
+ (byte)'t', (byte)':', (byte)' ', (byte)'0', (byte)'x'
+ };
+
+ /// ", cache_storage_count: "
+ public static ReadOnlySpan LogCacheStorageCount =>
+ new[]
+ {
+ (byte)',', (byte)' ', (byte)'c', (byte)'a', (byte)'c', (byte)'h', (byte)'e', (byte)'_',
+ (byte)'s', (byte)'t', (byte)'o', (byte)'r', (byte)'a', (byte)'g', (byte)'e', (byte)'_',
+ (byte)'c', (byte)'o', (byte)'u', (byte)'n', (byte)'t', (byte)':', (byte)' '
+ };
}
}
\ No newline at end of file
diff --git a/src/LibHac/Fs/ApplicationSaveDataManagement.cs b/src/LibHac/Fs/ApplicationSaveDataManagement.cs
index 2e13c0d0..61e64ca4 100644
--- a/src/LibHac/Fs/ApplicationSaveDataManagement.cs
+++ b/src/LibHac/Fs/ApplicationSaveDataManagement.cs
@@ -29,7 +29,7 @@ public static class ApplicationSaveDataManagement
Result CreateAccountSaveFunc()
{
- UserId userId = ConvertAccountUidToFsUserId(uidLocal);
+ UserId userId = Utility.ConvertAccountUidToFsUserId(uidLocal);
return fs.CreateSaveData(applicationId, userId, saveDataOwnerId, accountSaveDataSize,
accountSaveJournalSize, SaveDataFlags.None);
}
@@ -465,9 +465,4 @@ public static class ApplicationSaveDataManagement
return rc;
}
-
- public static UserId ConvertAccountUidToFsUserId(Uid uid)
- {
- return new UserId(uid.Id.High, uid.Id.Low);
- }
}
\ No newline at end of file
diff --git a/src/LibHac/Fs/CacheStorageTypes.cs b/src/LibHac/Fs/CacheStorageTypes.cs
new file mode 100644
index 00000000..d9b5eaa9
--- /dev/null
+++ b/src/LibHac/Fs/CacheStorageTypes.cs
@@ -0,0 +1,19 @@
+using LibHac.Common.FixedArrays;
+
+namespace LibHac.Fs;
+
+public readonly struct CacheStorageListHandle
+{
+ internal readonly object Cache;
+
+ internal CacheStorageListHandle(object cache)
+ {
+ Cache = cache;
+ }
+}
+
+public struct CacheStorageInfo
+{
+ public int Index;
+ public Array28 Reserved;
+}
\ No newline at end of file
diff --git a/src/LibHac/Fs/Shim/SaveDataManagement.cs b/src/LibHac/Fs/Shim/SaveDataManagement.cs
index c785a48e..6c9444ba 100644
--- a/src/LibHac/Fs/Shim/SaveDataManagement.cs
+++ b/src/LibHac/Fs/Shim/SaveDataManagement.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using LibHac.Common;
using LibHac.Diag;
using LibHac.Fs.Fsa;
@@ -12,682 +14,290 @@ using LibHac.Sf;
using LibHac.Time;
using static LibHac.Fs.Impl.AccessLogStrings;
-namespace LibHac.Fs.Shim;
-
-public class SaveDataIterator : IDisposable
+namespace LibHac.Fs
{
- private readonly FileSystemClient _fsClient;
- private SharedRef _reader;
-
- internal SaveDataIterator(FileSystemClient fsClient, ref SharedRef reader)
+ ///
+ /// Allows iterating through the of a list of save data.
+ ///
+ /// Based on nnSdk 13.4.0
+ public class SaveDataIterator : IDisposable
{
- _reader = SharedRef.CreateMove(ref reader);
- _fsClient = fsClient;
- }
+ private readonly FileSystemClient _fsClient;
+ private SharedRef _reader;
- public void Dispose()
- {
- _reader.Destroy();
- }
-
- private Result ReadSaveDataInfoImpl(out long readCount, Span buffer)
- {
- Result rc = _reader.Get.Read(out readCount, OutBuffer.FromSpan(buffer));
- if (rc.IsFailure()) return rc.Miss();
-
- return Result.Success;
- }
-
- public Result ReadSaveDataInfo(out long readCount, Span buffer)
- {
- Result rc;
- FileSystemClient fs = _fsClient;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ internal SaveDataIterator(FileSystemClient fsClient, ref SharedRef reader)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = ReadSaveDataInfoImpl(out readCount, buffer);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSize).AppendFormat(buffer.Length, 'd');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = ReadSaveDataInfoImpl(out readCount, buffer);
+ _reader = SharedRef.CreateMove(ref reader);
+ _fsClient = fsClient;
}
- fs.Impl.AbortIfNeeded(rc);
- if (rc.IsFailure()) return rc.Miss();
+ public void Dispose()
+ {
+ _reader.Destroy();
+ }
- return Result.Success;
+ private Result ReadSaveDataInfoImpl(out long readCount, Span buffer)
+ {
+ Result rc = _reader.Get.Read(out readCount, OutBuffer.FromSpan(buffer));
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public Result ReadSaveDataInfo(out long readCount, Span buffer)
+ {
+ Result rc;
+ FileSystemClient fs = _fsClient;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = ReadSaveDataInfoImpl(out readCount, buffer);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSize).AppendFormat(buffer.Length, 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = ReadSaveDataInfoImpl(out readCount, buffer);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
}
}
-[SkipLocalsInit]
-public static class SaveDataManagement
+namespace LibHac.Fs.Shim
{
- public static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
- out SaveDataExtraData extraData, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out extraData);
-
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraData(OutBuffer.FromStruct(ref extraData), saveDataId);
- if (rc.IsFailure()) return rc;
-
- return Result.Success;
- }
-
- public static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
- out SaveDataExtraData extraData, SaveDataSpaceId spaceId, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out extraData);
-
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataBySaveDataSpaceId(
- OutBuffer.FromStruct(ref extraData), spaceId, saveDataId);
- if (rc.IsFailure()) return rc;
-
- return Result.Success;
- }
-
- public static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
- out SaveDataExtraData extraData, SaveDataSpaceId spaceId, in SaveDataAttribute attribute)
- {
- UnsafeHelpers.SkipParamInit(out extraData);
-
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataBySaveDataAttribute(
- OutBuffer.FromStruct(ref extraData), spaceId, in attribute);
- if (rc.IsFailure()) return rc;
-
- return Result.Success;
- }
-
- public static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
- out SaveDataExtraData extraData, SaveDataSpaceId spaceId, in SaveDataAttribute attribute,
- in SaveDataExtraData extraDataMask)
- {
- UnsafeHelpers.SkipParamInit(out extraData);
-
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(
- OutBuffer.FromStruct(ref extraData), spaceId, in attribute, InBuffer.FromStruct(in extraDataMask));
- if (rc.IsFailure()) return rc;
-
- return Result.Success;
- }
-
///
- /// Writes the of the provided
- /// to the save data in the specified with the provided save data ID.
+ /// Contains functions for creating, deleting, and otherwise managing save data.
///
- /// The to use.
- /// The containing the save data to be written to.
- /// The save data ID of the save data to be written to.
- /// The containing the data to write.
- /// : The operation was successful.
- /// : The save data was not found.
- /// : Insufficient permissions.
- public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
- ulong saveDataId, in SaveDataExtraData extraData)
+ /// Based on nnSdk 13.4.0
+ [SkipLocalsInit]
+ public static class SaveDataManagement
{
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraData(saveDataId, spaceId,
- InBuffer.FromStruct(in extraData));
- fs.AbortIfNeeded(rc);
- if (rc.IsFailure()) return rc.Miss();
-
- return Result.Success;
- }
-
- ///
- /// Writes the provided to the save data in the specified
- /// with the provided save data ID.
- ///
- /// The to use.
- /// The containing the save data to be written to.
- /// The save data ID of the save data to be written to.
- /// The to write to the save data.
- /// A mask specifying which bits of
- /// to write to the save's extra data. 0 = don't write, 1 = write.
- /// : The operation was successful.
- /// : The save data was not found.
- /// : Insufficient permissions.
- ///
- /// Calling programs may have permission to write to all, some or none of the save data's extra data.
- /// If any bits are set in that the caller does not have the permissions
- /// to write to, nothing will be written and will be returned.
- ///
- public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
- ulong saveDataId, in SaveDataExtraData extraData, in SaveDataExtraData extraDataMask)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraDataWithMask(saveDataId, spaceId,
- InBuffer.FromStruct(in extraData), InBuffer.FromStruct(in extraDataMask));
- fs.AbortIfNeeded(rc);
- if (rc.IsFailure()) return rc.Miss();
-
- return Result.Success;
- }
-
- ///
- /// Writes the provided to the save data in the specified
- /// that matches the provided key.
- /// The mask specifies which parts of the extra data will be written to the save data.
- ///
- /// The to use.
- /// The containing the save data to be written to.
- /// The key for the save data.
- /// The to write to the save data.
- /// A mask specifying which bits of
- /// to write to the save's extra data. 0 = don't write, 1 = write.
- /// : The operation was successful.
- /// : The save data was not found.
- /// : Insufficient permissions.
- ///
- /// If is set to ,
- /// the program ID of will be resolved to the default save data program ID of the calling program.
- /// Calling programs may have permission to write to all, some or none of the save data's extra data.
- /// If any bits are set in that the caller does not have the permissions
- /// to write to, nothing will be written and will be returned.
- ///
- public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
- in SaveDataAttribute attribute, in SaveDataExtraData extraData, in SaveDataExtraData extraDataMask)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(in attribute,
- spaceId, InBuffer.FromStruct(in extraData), InBuffer.FromStruct(in extraDataMask));
- fs.AbortIfNeeded(rc);
- if (rc.IsFailure()) return rc.Miss();
-
- return Result.Success;
- }
-
- public static Result FindSaveDataWithFilter(this FileSystemClientImpl fs, out SaveDataInfo saveInfo,
- SaveDataSpaceId spaceId, in SaveDataFilter filter)
- {
- UnsafeHelpers.SkipParamInit(out saveInfo);
-
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Unsafe.SkipInit(out SaveDataInfo tempInfo);
- OutBuffer saveInfoBuffer = OutBuffer.FromStruct(ref tempInfo);
-
- Result rc = fileSystemProxy.Get.FindSaveDataWithFilter(out long count, saveInfoBuffer, spaceId, in filter);
- if (rc.IsFailure()) return rc;
-
- if (count == 0)
- return ResultFs.TargetNotFound.Log();
-
- saveInfo = tempInfo;
- return Result.Success;
- }
-
- public static Result CreateSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
- UserId userId, ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account,
- userId, 0);
- if (rc.IsFailure()) return rc;
-
- rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
- SaveDataSpaceId.User);
- if (rc.IsFailure()) return rc;
-
- var metaPolicy = new SaveDataMetaPolicy(SaveDataType.Account);
- metaPolicy.GenerateMetaInfo(out SaveDataMetaInfo metaInfo);
-
- rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
- if (rc.IsFailure()) return rc.Miss();
-
- return Result.Success;
- }
-
- public static Result CreateBcatSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
- long size)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Bcat,
- Fs.SaveData.InvalidUserId, 0);
- if (rc.IsFailure()) return rc;
-
- rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size,
- SaveDataProperties.BcatSaveDataJournalSize, SystemProgramId.Bcat.Value, SaveDataFlags.None,
- SaveDataSpaceId.User);
- if (rc.IsFailure()) return rc;
-
- var metaInfo = new SaveDataMetaInfo
+ private class CacheStorageListCache : IDisposable
{
- Type = SaveDataMetaType.None,
- Size = 0
- };
+ public readonly struct CacheEntry
+ {
+ private readonly int _index;
- rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
- if (rc.IsFailure()) return rc.Miss();
+ public CacheEntry(int index) => _index = index;
+ public int GetCacheStorageIndex() => _index;
+ }
- return Result.Success;
- }
+ private int _position;
+ private List _entryList;
- public static Result CreateDeviceSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
- ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+ public CacheStorageListCache()
+ {
+ _position = 0;
+ _entryList = new List();
+ }
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Device,
- Fs.SaveData.InvalidUserId, 0);
- if (rc.IsFailure()) return rc;
+ public void Dispose() { }
- rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
- SaveDataSpaceId.User);
- if (rc.IsFailure()) return rc;
+ public Result PushBack(in CacheEntry entry)
+ {
+ _entryList.Add(entry);
- var metaPolicy = new SaveDataMetaPolicy(SaveDataType.Device);
- metaPolicy.GenerateMetaInfo(out SaveDataMetaInfo metaInfo);
+ // The original code can have allocation failures here
+ return Result.Success;
+ }
- rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
- if (rc.IsFailure()) return rc.Miss();
+ public ref readonly CacheEntry PopFront()
+ {
+ if (_position >= _entryList.Count)
+ return ref Unsafe.NullRef();
- return Result.Success;
- }
+ return ref CollectionsMarshal.AsSpan(_entryList)[_position++];
+ }
- public static Result CreateCacheStorage(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
- SaveDataSpaceId spaceId, ulong ownerId, ushort index, long size, long journalSize, SaveDataFlags flags)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Cache,
- Fs.SaveData.InvalidUserId, 0, index);
- if (rc.IsFailure()) return rc;
-
- rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
- spaceId);
- if (rc.IsFailure()) return rc;
-
- var metaInfo = new SaveDataMetaInfo
- {
- Type = SaveDataMetaType.None,
- Size = 0
- };
-
- rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
- if (rc.IsFailure()) return rc.Miss();
-
- return Result.Success;
- }
-
- public static Result CreateSaveData(this FileSystemClientImpl fs, in SaveDataAttribute attribute,
- in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo, in HashSalt hashSalt)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- return fileSystemProxy.Get.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo,
- in metaInfo, in hashSalt);
- }
-
- public static Result DeleteSaveData(this FileSystemClientImpl fs, ulong saveDataId)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- return fileSystemProxy.Get.DeleteSaveDataFileSystem(saveDataId);
- }
-
- public static Result DeleteSaveData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId, ulong saveDataId)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
- }
-
- public static Result DeleteSaveData(this FileSystemClient fs, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x30];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.DeleteSaveData(saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.DeleteSaveData(saveDataId);
+ public static CacheStorageListCache GetCacheStorageListCache(CacheStorageListHandle handle)
+ {
+ return (CacheStorageListCache)handle.Cache;
+ }
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result DeleteSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
+ out SaveDataExtraData extraData, ulong saveDataId)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.DeleteSaveData(spaceId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
+ UnsafeHelpers.SkipParamInit(out extraData);
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.DeleteSaveData(spaceId, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result DeleteSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
- UserId userId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x80];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = Delete(fs, spaceId, saveDataId, userId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16);
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = Delete(fs, spaceId, saveDataId, userId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result Delete(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId)
- {
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
- SaveDataType.System, userId, saveDataId);
+ Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraData(OutBuffer.FromStruct(ref extraData), saveDataId);
if (rc.IsFailure()) return rc;
- return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataAttribute(spaceId, in attribute);
- }
- }
-
- public static Result DeleteDeviceSaveData(this FileSystemClient fs, ApplicationId applicationId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x30];
-
- if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = Delete(fs, applicationId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = Delete(fs, applicationId);
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result Delete(FileSystemClient fs, ApplicationId applicationId)
+ public static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
+ out SaveDataExtraData extraData, SaveDataSpaceId spaceId, ulong saveDataId)
{
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ UnsafeHelpers.SkipParamInit(out extraData);
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value),
- SaveDataType.Device, Fs.SaveData.InvalidUserId, 0);
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataBySaveDataSpaceId(
+ OutBuffer.FromStruct(ref extraData), spaceId, saveDataId);
if (rc.IsFailure()) return rc;
- return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId.User, in attribute);
- }
- }
-
- public static Result RegisterSaveDataAtomicDeletion(this FileSystemClient fs,
- ReadOnlySpan saveDataIdList)
- {
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.RegisterSaveDataFileSystemAtomicDeletion(InBuffer.FromSpan(saveDataIdList));
- fs.Impl.AbortIfNeeded(rc);
- if (rc.IsFailure()) return rc.Miss();
-
- return Result.Success;
- }
-
- public static Result OpenSaveDataIterator(this FileSystemClientImpl fs,
- ref UniqueRef outIterator, SaveDataSpaceId spaceId)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- using var reader = new SharedRef();
-
- Result rc = fileSystemProxy.Get.OpenSaveDataInfoReaderBySaveDataSpaceId(ref reader.Ref(), spaceId);
- if (rc.IsFailure()) return rc;
-
- using var iterator = new UniqueRef(new SaveDataIterator(fs.Fs, ref reader.Ref()));
-
- if (!iterator.HasValue)
- return ResultFs.AllocationMemoryFailedInSaveDataManagementA.Log();
-
- outIterator.Set(ref iterator.Ref());
-
- return Result.Success;
- }
-
- public static Result OpenSaveDataIterator(this FileSystemClientImpl fs,
- ref UniqueRef outIterator, SaveDataSpaceId spaceId, in SaveDataFilter filter)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- using var reader = new SharedRef();
-
- Result rc = fileSystemProxy.Get.OpenSaveDataInfoReaderWithFilter(ref reader.Ref(), spaceId, in filter);
- if (rc.IsFailure()) return rc;
-
- using var iterator = new UniqueRef(new SaveDataIterator(fs.Fs, ref reader.Ref()));
-
- if (!iterator.HasValue)
- return ResultFs.AllocationMemoryFailedInSaveDataManagementA.Log();
-
- outIterator.Set(ref iterator.Ref());
-
- return Result.Success;
- }
-
- public static Result ReadSaveDataIteratorSaveDataInfo(out long readCount, Span buffer,
- in SaveDataIterator iterator)
- {
- Result rc = iterator.ReadSaveDataInfo(out readCount, buffer);
- if (rc.IsFailure()) return rc.Miss();
-
- return Result.Success;
- }
-
- public static Result OpenSaveDataIterator(this FileSystemClient fs, ref UniqueRef outIterator,
- SaveDataSpaceId spaceId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId));
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId);
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result OpenSaveDataIterator(this FileSystemClient fs, ref UniqueRef outIterator,
- SaveDataSpaceId spaceId, in SaveDataFilter filter)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
+ out SaveDataExtraData extraData, SaveDataSpaceId spaceId, in SaveDataAttribute attribute)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId, in filter);
- Tick end = fs.Hos.Os.GetSystemTick();
+ UnsafeHelpers.SkipParamInit(out extraData);
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId));
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId, in filter);
+ Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataBySaveDataAttribute(
+ OutBuffer.FromStruct(ref extraData), spaceId, in attribute);
+ if (rc.IsFailure()) return rc;
+
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result FindSaveDataWithFilter(this FileSystemClient fs, out SaveDataInfo info,
- SaveDataSpaceId spaceId, in SaveDataFilter filter)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
+ out SaveDataExtraData extraData, SaveDataSpaceId spaceId, in SaveDataAttribute attribute,
+ in SaveDataExtraData extraDataMask)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.FindSaveDataWithFilter(out info, spaceId, in filter);
- Tick end = fs.Hos.Os.GetSystemTick();
+ UnsafeHelpers.SkipParamInit(out extraData);
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId));
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.FindSaveDataWithFilter(out info, spaceId, in filter);
+ Result rc = fileSystemProxy.Get.ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(
+ OutBuffer.FromStruct(ref extraData), spaceId, in attribute, InBuffer.FromStruct(in extraDataMask));
+ if (rc.IsFailure()) return rc;
+
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result CreateSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
- ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x100];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ ///
+ /// Writes the of the provided
+ /// to the save data in the specified with the provided save data ID.
+ ///
+ /// The to use.
+ /// The containing the save data to be written to.
+ /// The save data ID of the save data to be written to.
+ /// The containing the data to write.
+ /// : The operation was successful.
+ /// : The save data was not found.
+ /// : Insufficient permissions.
+ public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
+ ulong saveDataId, in SaveDataExtraData extraData)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.CreateSaveData(applicationId, userId, ownerId, size, journalSize, flags);
- Tick end = fs.Hos.Os.GetSystemTick();
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
- .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
- .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
- .Append(LogSaveDataSize).AppendFormat(size, 'd')
- .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
- .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+ Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraData(saveDataId, spaceId,
+ InBuffer.FromStruct(in extraData));
+ fs.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.CreateSaveData(applicationId, userId, ownerId, size, journalSize, flags);
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result CreateSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
- ulong ownerId, long size, long journalSize, in HashSalt hashSalt, SaveDataFlags flags)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x100];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ ///
+ /// Writes the provided to the save data in the specified
+ /// with the provided save data ID.
+ ///
+ /// The to use.
+ /// The containing the save data to be written to.
+ /// The save data ID of the save data to be written to.
+ /// The to write to the save data.
+ /// A mask specifying which bits of
+ /// to write to the save's extra data. 0 = don't write, 1 = write.
+ /// : The operation was successful.
+ /// : The save data was not found.
+ /// : Insufficient permissions.
+ ///
+ /// Calling programs may have permission to write to all, some or none of the save data's extra data.
+ /// If any bits are set in that the caller does not have the permissions
+ /// to write to, nothing will be written and will be returned.
+ ///
+ public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
+ ulong saveDataId, in SaveDataExtraData extraData, in SaveDataExtraData extraDataMask)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = CreateSave(fs, applicationId, userId, ownerId, size, journalSize, in hashSalt, flags);
- Tick end = fs.Hos.Os.GetSystemTick();
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
- .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
- .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
- .Append(LogSaveDataSize).AppendFormat(size, 'd')
- .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
- .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+ Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraDataWithMask(saveDataId, spaceId,
+ InBuffer.FromStruct(in extraData), InBuffer.FromStruct(in extraDataMask));
+ fs.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = CreateSave(fs, applicationId, userId, ownerId, size, journalSize, in hashSalt, flags);
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result CreateSave(FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
- ulong ownerId, long size, long journalSize, in HashSalt hashSalt, SaveDataFlags flags)
+ ///
+ /// Writes the provided to the save data in the specified
+ /// that matches the provided key.
+ /// The mask specifies which parts of the extra data will be written to the save data.
+ ///
+ /// The to use.
+ /// The containing the save data to be written to.
+ /// The key for the save data.
+ /// The to write to the save data.
+ /// A mask specifying which bits of
+ /// to write to the save's extra data. 0 = don't write, 1 = write.
+ /// : The operation was successful.
+ /// : The save data was not found.
+ /// : Insufficient permissions.
+ ///
+ /// If is set to ,
+ /// the program ID of will be resolved to the default save data program ID of the calling program.
+ /// Calling programs may have permission to write to all, some or none of the save data's extra data.
+ /// If any bits are set in that the caller does not have the permissions
+ /// to write to, nothing will be written and will be returned.
+ ///
+ public static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
+ in SaveDataAttribute attribute, in SaveDataExtraData extraData, in SaveDataExtraData extraDataMask)
{
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(in attribute,
+ spaceId, InBuffer.FromStruct(in extraData), InBuffer.FromStruct(in extraDataMask));
+ fs.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result FindSaveDataWithFilter(this FileSystemClientImpl fs, out SaveDataInfo saveInfo,
+ SaveDataSpaceId spaceId, in SaveDataFilter filter)
+ {
+ UnsafeHelpers.SkipParamInit(out saveInfo);
+
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+
+ Unsafe.SkipInit(out SaveDataInfo tempInfo);
+ OutBuffer saveInfoBuffer = OutBuffer.FromStruct(ref tempInfo);
+
+ Result rc = fileSystemProxy.Get.FindSaveDataWithFilter(out long count, saveInfoBuffer, spaceId, in filter);
+ if (rc.IsFailure()) return rc;
+
+ if (count == 0)
+ return ResultFs.TargetNotFound.Log();
+
+ saveInfo = tempInfo;
+ return Result.Success;
+ }
+
+ public static Result CreateSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
+ UserId userId, ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account,
- userId, 0);
+ userId, staticSaveDataId: 0);
if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
@@ -697,1349 +307,1950 @@ public static class SaveDataManagement
var metaPolicy = new SaveDataMetaPolicy(SaveDataType.Account);
metaPolicy.GenerateMetaInfo(out SaveDataMetaInfo metaInfo);
- return fileSystemProxy.Get.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo, in metaInfo,
- in hashSalt);
- }
- }
+ rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
+ if (rc.IsFailure()) return rc.Miss();
- public static Result CreateBcatSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, long size)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.CreateBcatSaveData(applicationId, size);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
- .Append(LogSaveDataSize).AppendFormat(size, 'd');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.CreateBcatSaveData(applicationId, size);
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result CreateDeviceSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId,
- ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x100];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result CreateBcatSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
+ long size)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.CreateDeviceSaveData(applicationId, ownerId, size, journalSize, flags);
- Tick end = fs.Hos.Os.GetSystemTick();
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
- .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
- .Append(LogSaveDataSize).AppendFormat(size, 'd')
- .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
- .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Bcat,
+ Fs.SaveData.InvalidUserId, staticSaveDataId: 0);
+ if (rc.IsFailure()) return rc;
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.CreateDeviceSaveData(applicationId, ownerId, size, journalSize, flags);
+ rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size,
+ SaveDataProperties.BcatSaveDataJournalSize, SystemProgramId.Bcat.Value, SaveDataFlags.None,
+ SaveDataSpaceId.User);
+ if (rc.IsFailure()) return rc;
+
+ var metaInfo = new SaveDataMetaInfo
+ {
+ Type = SaveDataMetaType.None,
+ Size = 0
+ };
+
+ rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result CreateTemporaryStorage(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
- ulong ownerId, long size, SaveDataFlags flags)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Temporary,
- Fs.SaveData.InvalidUserId, 0);
- if (rc.IsFailure()) return rc;
-
- rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, 0, ownerId, flags,
- SaveDataSpaceId.Temporary);
- if (rc.IsFailure()) return rc;
-
- var metaInfo = new SaveDataMetaInfo
- {
- Type = SaveDataMetaType.None,
- Size = 0
- };
-
- return fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
- }
-
- public static Result CreateTemporaryStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
- ulong ownerId, long size, SaveDataFlags flags)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x100];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.CreateTemporaryStorage(applicationId, ownerId, size, flags);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
- .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
- .Append(LogSaveDataSize).AppendFormat(size, 'd')
- .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.CreateTemporaryStorage(applicationId, ownerId, size, flags);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result CreateCacheStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
- SaveDataSpaceId spaceId, ulong ownerId, ushort index, long size, long journalSize, SaveDataFlags flags)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x100];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.CreateCacheStorage(applicationId, spaceId, ownerId, index, size, journalSize, flags);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
- .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
- .Append(LogSaveDataSize).AppendFormat(size, 'd')
- .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
- .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.CreateCacheStorage(applicationId, spaceId, ownerId, index, size, journalSize, flags);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result CreateCacheStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
- SaveDataSpaceId spaceId, ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- return CreateCacheStorage(fs, applicationId, spaceId, ownerId, 0, size, journalSize, flags);
- }
-
- public static Result CreateCacheStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
- ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- return CreateCacheStorage(fs, applicationId, SaveDataSpaceId.User, ownerId, size, journalSize, flags);
- }
-
- public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId,
- ulong saveDataId, UserId userId, ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x100];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = CreateSave(fs, spaceId, saveDataId, userId, ownerId, size, journalSize, flags);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
- .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
- .Append(LogSaveDataSize).AppendFormat(size, 'd')
- .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
- .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = CreateSave(fs, spaceId, saveDataId, userId, ownerId, size, journalSize, flags);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result CreateSave(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId,
+ public static Result CreateDeviceSaveData(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
ulong ownerId, long size, long journalSize, SaveDataFlags flags)
{
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
- SaveDataType.System, userId, saveDataId);
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Device,
+ Fs.SaveData.InvalidUserId, staticSaveDataId: 0);
+ if (rc.IsFailure()) return rc;
+
+ rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
+ SaveDataSpaceId.User);
+ if (rc.IsFailure()) return rc;
+
+ var metaPolicy = new SaveDataMetaPolicy(SaveDataType.Device);
+ metaPolicy.GenerateMetaInfo(out SaveDataMetaInfo metaInfo);
+
+ rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result CreateCacheStorage(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
+ SaveDataSpaceId spaceId, ulong ownerId, ushort index, long size, long journalSize, SaveDataFlags flags)
+ {
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Cache,
+ Fs.SaveData.InvalidUserId, staticSaveDataId: 0, index);
if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
spaceId);
if (rc.IsFailure()) return rc;
- return fileSystemProxy.Get.CreateSaveDataFileSystemBySystemSaveDataId(in attribute, in creationInfo);
- }
- }
+ var metaInfo = new SaveDataMetaInfo
+ {
+ Type = SaveDataMetaType.None,
+ Size = 0
+ };
- public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId,
- ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- return CreateSystemSaveData(fs, SaveDataSpaceId.System, saveDataId, userId, ownerId, size, journalSize,
- flags);
- }
+ rc = fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
+ if (rc.IsFailure()) return rc.Miss();
- public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId, long size,
- long journalSize, SaveDataFlags flags)
- {
- return CreateSystemSaveData(fs, saveDataId, userId, 0, size, journalSize, flags);
- }
-
- public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, ulong ownerId, long size,
- long journalSize, SaveDataFlags flags)
- {
- return CreateSystemSaveData(fs, saveDataId, Fs.SaveData.InvalidUserId, ownerId, size, journalSize, flags);
- }
-
- public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, long size,
- long journalSize, SaveDataFlags flags)
- {
- return CreateSystemSaveData(fs, saveDataId, Fs.SaveData.InvalidUserId, 0, size, journalSize, flags);
- }
-
- public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
- ulong ownerId, long size, long journalSize, SaveDataFlags flags)
- {
- return CreateSystemSaveData(fs, spaceId, saveDataId, Fs.SaveData.InvalidUserId, ownerId, size, journalSize,
- flags);
- }
-
- public static Result ExtendSaveData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId, ulong saveDataId,
- long saveDataSize, long journalSize)
- {
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- return fileSystemProxy.Get.ExtendSaveDataFileSystem(spaceId, saveDataId, saveDataSize, journalSize);
- }
-
- public static Result ExtendSaveData(this FileSystemClient fs, ulong saveDataId, long saveDataSize,
- long journalSize)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x90];
-
- var spaceId = SaveDataSpaceId.System;
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.ExtendSaveData(spaceId, saveDataId, saveDataSize, journalSize);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogSaveDataSize).AppendFormat(saveDataSize, 'd')
- .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.ExtendSaveData(spaceId, saveDataId, saveDataSize, journalSize);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result ExtendSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
- long saveDataSize, long journalSize)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x90];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.ExtendSaveData(spaceId, saveDataId, saveDataSize, journalSize);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogSaveDataSize).AppendFormat(saveDataSize, 'd')
- .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.ExtendSaveData(spaceId, saveDataId, saveDataSize, journalSize);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result QuerySaveDataTotalSize(this FileSystemClientImpl fs, out long totalSize, long size,
- long journalSize)
- {
- UnsafeHelpers.SkipParamInit(out totalSize);
-
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.QuerySaveDataTotalSize(out long tempTotalSize, size, journalSize);
- if (rc.IsFailure()) return rc.Miss();
-
- totalSize = tempTotalSize;
- return Result.Success;
- }
-
- public static Result QuerySaveDataTotalSize(this FileSystemClient fs, out long totalSize, long size,
- long journalSize)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.QuerySaveDataTotalSize(out totalSize, size, journalSize);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataSize).AppendFormat(size, 'd')
- .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.QuerySaveDataTotalSize(out totalSize, size, journalSize);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result GetSaveDataOwnerId(this FileSystemClient fs, out ulong ownerId, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x40];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetOwnerId(fs, out ownerId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- // Note: Nintendo accidentally uses ", save_data_size: %ld" instead of ", savedataid: 0x%lX"
- // for the format string.
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetOwnerId(fs, out ownerId, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetOwnerId(FileSystemClient fs, out ulong ownerId, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out ownerId);
-
- Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
- if (rc.IsFailure()) return rc;
-
- ownerId = extraData.OwnerId;
return Result.Success;
}
- }
- public static Result GetSaveDataOwnerId(this FileSystemClient fs, out ulong ownerId, SaveDataSpaceId spaceId,
- ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result CreateSaveData(this FileSystemClientImpl fs, in SaveDataAttribute attribute,
+ in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo, in HashSalt hashSalt)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetOwnerId(fs, out ownerId, spaceId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetOwnerId(fs, out ownerId, spaceId, saveDataId);
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+ return fileSystemProxy.Get.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo,
+ in metaInfo, in hashSalt);
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetOwnerId(FileSystemClient fs, out ulong ownerId, SaveDataSpaceId spaceId, ulong saveDataId)
+ public static Result DeleteSaveData(this FileSystemClientImpl fs, ulong saveDataId)
{
- UnsafeHelpers.SkipParamInit(out ownerId);
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+ return fileSystemProxy.Get.DeleteSaveDataFileSystem(saveDataId);
+ }
- Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId,
- saveDataId);
- if (rc.IsFailure()) return rc;
+ public static Result DeleteSaveData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId, ulong saveDataId)
+ {
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+ return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
+ }
+
+ public static Result DeleteSaveData(this FileSystemClient fs, ulong saveDataId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x30];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.DeleteSaveData(saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.DeleteSaveData(saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result DeleteSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.DeleteSaveData(spaceId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.DeleteSaveData(spaceId, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result DeleteSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
+ UserId userId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x80];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = Delete(fs, spaceId, saveDataId, userId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = Delete(fs, spaceId, saveDataId, userId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result Delete(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
+ SaveDataType.System, userId, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataAttribute(spaceId, in attribute);
+ }
+ }
+
+ public static Result DeleteDeviceSaveData(this FileSystemClient fs, ApplicationId applicationId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x30];
+
+ if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = Delete(fs, applicationId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = Delete(fs, applicationId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result Delete(FileSystemClient fs, ApplicationId applicationId)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value),
+ SaveDataType.Device, Fs.SaveData.InvalidUserId, staticSaveDataId: 0);
+ if (rc.IsFailure()) return rc;
+
+ return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId.User, in attribute);
+ }
+ }
+
+ public static Result RegisterSaveDataAtomicDeletion(this FileSystemClient fs,
+ ReadOnlySpan saveDataIdList)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.RegisterSaveDataFileSystemAtomicDeletion(InBuffer.FromSpan(saveDataIdList));
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
- ownerId = extraData.OwnerId;
return Result.Success;
}
- }
- public static Result GetSaveDataFlags(this FileSystemClient fs, out SaveDataFlags flags, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x40];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result OpenSaveDataIterator(this FileSystemClientImpl fs,
+ ref UniqueRef outIterator, SaveDataSpaceId spaceId)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetFlags(fs, out flags, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+ using var reader = new SharedRef();
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetFlags(fs, out flags, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetFlags(FileSystemClient fs, out SaveDataFlags flags, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out flags);
-
- Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
+ Result rc = fileSystemProxy.Get.OpenSaveDataInfoReaderBySaveDataSpaceId(ref reader.Ref(), spaceId);
if (rc.IsFailure()) return rc;
- flags = extraData.Flags;
+ using var iterator = new UniqueRef(new SaveDataIterator(fs.Fs, ref reader.Ref()));
+
+ if (!iterator.HasValue)
+ return ResultFs.AllocationMemoryFailedInSaveDataManagementA.Log();
+
+ outIterator.Set(ref iterator.Ref());
+
return Result.Success;
}
- }
- public static Result GetSaveDataFlags(this FileSystemClient fs, out SaveDataFlags flags,
- SaveDataSpaceId spaceId, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result OpenSaveDataIterator(this FileSystemClientImpl fs,
+ ref UniqueRef outIterator, SaveDataSpaceId spaceId, in SaveDataFilter filter)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetFlags(fs, out flags, spaceId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+ using var reader = new SharedRef();
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
+ Result rc = fileSystemProxy.Get.OpenSaveDataInfoReaderWithFilter(ref reader.Ref(), spaceId, in filter);
+ if (rc.IsFailure()) return rc;
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+ using var iterator = new UniqueRef(new SaveDataIterator(fs.Fs, ref reader.Ref()));
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetFlags(fs, out flags, spaceId, saveDataId);
+ if (!iterator.HasValue)
+ return ResultFs.AllocationMemoryFailedInSaveDataManagementA.Log();
+
+ outIterator.Set(ref iterator.Ref());
+
+ return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
+ public static Result ReadSaveDataIteratorSaveDataInfo(this FileSystemClientImpl fs, out long readCount,
+ Span buffer, in SaveDataIterator iterator)
+ {
+ Result rc = iterator.ReadSaveDataInfo(out readCount, buffer);
+ if (rc.IsFailure()) return rc.Miss();
- static Result GetFlags(FileSystemClient fs, out SaveDataFlags flags, SaveDataSpaceId spaceId,
+ return Result.Success;
+ }
+
+ public static Result OpenSaveDataIterator(this FileSystemClient fs, ref UniqueRef outIterator,
+ SaveDataSpaceId spaceId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId));
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result OpenSaveDataIterator(this FileSystemClient fs, ref UniqueRef outIterator,
+ SaveDataSpaceId spaceId, in SaveDataFilter filter)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId, in filter);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId));
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.OpenSaveDataIterator(ref outIterator, spaceId, in filter);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result FindSaveDataWithFilter(this FileSystemClient fs, out SaveDataInfo info,
+ SaveDataSpaceId spaceId, in SaveDataFilter filter)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.FindSaveDataWithFilter(out info, spaceId, in filter);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId));
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.FindSaveDataWithFilter(out info, spaceId, in filter);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result CreateSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
+ ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x100];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.CreateSaveData(applicationId, userId, ownerId, size, journalSize, flags);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
+ .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
+ .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
+ .Append(LogSaveDataSize).AppendFormat(size, 'd')
+ .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
+ .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.CreateSaveData(applicationId, userId, ownerId, size, journalSize, flags);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result CreateSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
+ ulong ownerId, long size, long journalSize, in HashSalt hashSalt, SaveDataFlags flags)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x100];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = CreateSave(fs, applicationId, userId, ownerId, size, journalSize, in hashSalt, flags);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
+ .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
+ .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
+ .Append(LogSaveDataSize).AppendFormat(size, 'd')
+ .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
+ .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = CreateSave(fs, applicationId, userId, ownerId, size, journalSize, in hashSalt, flags);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result CreateSave(FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
+ ulong ownerId, long size, long journalSize, in HashSalt hashSalt, SaveDataFlags flags)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account,
+ userId, staticSaveDataId: 0);
+ if (rc.IsFailure()) return rc;
+
+ rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
+ SaveDataSpaceId.User);
+ if (rc.IsFailure()) return rc;
+
+ var metaPolicy = new SaveDataMetaPolicy(SaveDataType.Account);
+ metaPolicy.GenerateMetaInfo(out SaveDataMetaInfo metaInfo);
+
+ return fileSystemProxy.Get.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo, in metaInfo,
+ in hashSalt);
+ }
+ }
+
+ public static Result CreateBcatSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, long size)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.CreateBcatSaveData(applicationId, size);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
+ .Append(LogSaveDataSize).AppendFormat(size, 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.CreateBcatSaveData(applicationId, size);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result CreateDeviceSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId,
+ ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x100];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.CreateDeviceSaveData(applicationId, ownerId, size, journalSize, flags);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
+ .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
+ .Append(LogSaveDataSize).AppendFormat(size, 'd')
+ .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
+ .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.CreateDeviceSaveData(applicationId, ownerId, size, journalSize, flags);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result CreateTemporaryStorage(this FileSystemClientImpl fs, Ncm.ApplicationId applicationId,
+ ulong ownerId, long size, SaveDataFlags flags)
+ {
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Temporary,
+ Fs.SaveData.InvalidUserId, staticSaveDataId: 0);
+ if (rc.IsFailure()) return rc;
+
+ rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize: 0, ownerId, flags,
+ SaveDataSpaceId.Temporary);
+ if (rc.IsFailure()) return rc;
+
+ var metaInfo = new SaveDataMetaInfo
+ {
+ Type = SaveDataMetaType.None,
+ Size = 0
+ };
+
+ return fileSystemProxy.Get.CreateSaveDataFileSystem(in attribute, in creationInfo, in metaInfo);
+ }
+
+ public static Result CreateTemporaryStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
+ ulong ownerId, long size, SaveDataFlags flags)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x100];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.CreateTemporaryStorage(applicationId, ownerId, size, flags);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
+ .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
+ .Append(LogSaveDataSize).AppendFormat(size, 'd')
+ .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.CreateTemporaryStorage(applicationId, ownerId, size, flags);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result CreateCacheStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
+ SaveDataSpaceId spaceId, ulong ownerId, ushort index, long size, long journalSize, SaveDataFlags flags)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x100];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.CreateCacheStorage(applicationId, spaceId, ownerId, index, size, journalSize, flags);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
+ .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
+ .Append(LogSaveDataSize).AppendFormat(size, 'd')
+ .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
+ .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.CreateCacheStorage(applicationId, spaceId, ownerId, index, size, journalSize, flags);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result CreateCacheStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
+ SaveDataSpaceId spaceId, ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ return CreateCacheStorage(fs, applicationId, spaceId, ownerId, index: 0, size, journalSize, flags);
+ }
+
+ public static Result CreateCacheStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId,
+ ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ return CreateCacheStorage(fs, applicationId, SaveDataSpaceId.User, ownerId, size, journalSize, flags);
+ }
+
+ public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId,
+ ulong saveDataId, UserId userId, ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x100];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = CreateSave(fs, spaceId, saveDataId, userId, ownerId, size, journalSize, flags);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
+ .Append(LogSaveDataOwnerId).AppendFormat(ownerId, 'X')
+ .Append(LogSaveDataSize).AppendFormat(size, 'd')
+ .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd')
+ .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = CreateSave(fs, spaceId, saveDataId, userId, ownerId, size, journalSize, flags);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result CreateSave(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId,
+ ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
+ SaveDataType.System, userId, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
+ spaceId);
+ if (rc.IsFailure()) return rc;
+
+ return fileSystemProxy.Get.CreateSaveDataFileSystemBySystemSaveDataId(in attribute, in creationInfo);
+ }
+ }
+
+ public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId,
+ ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ return CreateSystemSaveData(fs, SaveDataSpaceId.System, saveDataId, userId, ownerId, size, journalSize,
+ flags);
+ }
+
+ public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId, long size,
+ long journalSize, SaveDataFlags flags)
+ {
+ return CreateSystemSaveData(fs, saveDataId, userId, ownerId: 0, size, journalSize, flags);
+ }
+
+ public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, ulong ownerId, long size,
+ long journalSize, SaveDataFlags flags)
+ {
+ return CreateSystemSaveData(fs, saveDataId, Fs.SaveData.InvalidUserId, ownerId, size, journalSize, flags);
+ }
+
+ public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, long size,
+ long journalSize, SaveDataFlags flags)
+ {
+ return CreateSystemSaveData(fs, saveDataId, Fs.SaveData.InvalidUserId, ownerId: 0, size, journalSize, flags);
+ }
+
+ public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
+ ulong ownerId, long size, long journalSize, SaveDataFlags flags)
+ {
+ return CreateSystemSaveData(fs, spaceId, saveDataId, Fs.SaveData.InvalidUserId, ownerId, size, journalSize,
+ flags);
+ }
+
+ public static Result ExtendSaveData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId, ulong saveDataId,
+ long saveDataSize, long journalSize)
+ {
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+
+ return fileSystemProxy.Get.ExtendSaveDataFileSystem(spaceId, saveDataId, saveDataSize, journalSize);
+ }
+
+ public static Result ExtendSaveData(this FileSystemClient fs, ulong saveDataId, long saveDataSize,
+ long journalSize)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x90];
+
+ var spaceId = SaveDataSpaceId.System;
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.ExtendSaveData(spaceId, saveDataId, saveDataSize, journalSize);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogSaveDataSize).AppendFormat(saveDataSize, 'd')
+ .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.ExtendSaveData(spaceId, saveDataId, saveDataSize, journalSize);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result ExtendSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
+ long saveDataSize, long journalSize)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x90];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.ExtendSaveData(spaceId, saveDataId, saveDataSize, journalSize);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogSaveDataSize).AppendFormat(saveDataSize, 'd')
+ .Append(LogSaveDataJournalSize).AppendFormat(journalSize, 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.ExtendSaveData(spaceId, saveDataId, saveDataSize, journalSize);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result QuerySaveDataTotalSize(this FileSystemClientImpl fs, out long totalSize, long saveDataSize,
+ long saveDataJournalSize)
+ {
+ UnsafeHelpers.SkipParamInit(out totalSize);
+
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.QuerySaveDataTotalSize(out long tempTotalSize, saveDataSize,
+ saveDataJournalSize);
+ if (rc.IsFailure()) return rc.Miss();
+
+ totalSize = tempTotalSize;
+ return Result.Success;
+ }
+
+ public static Result QuerySaveDataTotalSize(this FileSystemClient fs, out long totalSize, long saveDataSize,
+ long saveDataJournalSize)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.QuerySaveDataTotalSize(out totalSize, saveDataSize, saveDataJournalSize);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataSize).AppendFormat(saveDataSize, 'd')
+ .Append(LogSaveDataJournalSize).AppendFormat(saveDataJournalSize, 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.QuerySaveDataTotalSize(out totalSize, saveDataSize, saveDataJournalSize);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result GetSaveDataOwnerId(this FileSystemClient fs, out ulong ownerId, ulong saveDataId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x40];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetOwnerId(fs, out ownerId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ // Note: Nintendo accidentally uses ", save_data_size: %ld" instead of ", savedataid: 0x%lX"
+ // for the format string.
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetOwnerId(fs, out ownerId, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetOwnerId(FileSystemClient fs, out ulong ownerId, ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out ownerId);
+
+ Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ ownerId = extraData.OwnerId;
+ return Result.Success;
+ }
+ }
+
+ public static Result GetSaveDataOwnerId(this FileSystemClient fs, out ulong ownerId, SaveDataSpaceId spaceId,
ulong saveDataId)
{
- UnsafeHelpers.SkipParamInit(out flags);
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
- Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId,
- saveDataId);
- if (rc.IsFailure()) return rc;
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetOwnerId(fs, out ownerId, spaceId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
- flags = extraData.Flags;
- return Result.Success;
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetOwnerId(fs, out ownerId, spaceId, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetOwnerId(FileSystemClient fs, out ulong ownerId, SaveDataSpaceId spaceId, ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out ownerId);
+
+ Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId,
+ saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ ownerId = extraData.OwnerId;
+ return Result.Success;
+ }
}
- }
- public static Result GetSystemSaveDataFlags(this FileSystemClient fs, out SaveDataFlags flags,
- SaveDataSpaceId spaceId, ulong saveDataId, UserId userId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x80];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result GetSaveDataFlags(this FileSystemClient fs, out SaveDataFlags flags, ulong saveDataId)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetFlags(fs, out flags, spaceId, saveDataId, userId);
- Tick end = fs.Hos.Os.GetSystemTick();
+ Result rc;
+ Span logBuffer = stackalloc byte[0x40];
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetFlags(fs, out flags, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16);
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetFlags(fs, out flags, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetFlags(FileSystemClient fs, out SaveDataFlags flags, ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out flags);
+
+ Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ flags = extraData.Flags;
+ return Result.Success;
+ }
}
- else
+
+ public static Result GetSaveDataFlags(this FileSystemClient fs, out SaveDataFlags flags,
+ SaveDataSpaceId spaceId, ulong saveDataId)
{
- rc = GetFlags(fs, out flags, spaceId, saveDataId, userId);
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetFlags(fs, out flags, spaceId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetFlags(fs, out flags, spaceId, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetFlags(FileSystemClient fs, out SaveDataFlags flags, SaveDataSpaceId spaceId,
+ ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out flags);
+
+ Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId,
+ saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ flags = extraData.Flags;
+ return Result.Success;
+ }
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetFlags(FileSystemClient fs, out SaveDataFlags flags, SaveDataSpaceId spaceId,
- ulong saveDataId, UserId userId)
+ public static Result GetSystemSaveDataFlags(this FileSystemClient fs, out SaveDataFlags flags,
+ SaveDataSpaceId spaceId, ulong saveDataId, UserId userId)
{
- UnsafeHelpers.SkipParamInit(out flags);
+ Result rc;
+ Span logBuffer = stackalloc byte[0x80];
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
- SaveDataType.System, userId, saveDataId);
- if (rc.IsFailure()) return rc;
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetFlags(fs, out flags, spaceId, saveDataId, userId);
+ Tick end = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId, in attribute);
- if (rc.IsFailure()) return rc;
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
- flags = extraData.Flags;
- return Result.Success;
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetFlags(fs, out flags, spaceId, saveDataId, userId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetFlags(FileSystemClient fs, out SaveDataFlags flags, SaveDataSpaceId spaceId,
+ ulong saveDataId, UserId userId)
+ {
+ UnsafeHelpers.SkipParamInit(out flags);
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
+ SaveDataType.System, userId, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId, in attribute);
+ if (rc.IsFailure()) return rc;
+
+ flags = extraData.Flags;
+ return Result.Success;
+ }
}
- }
- public static Result SetSaveDataFlags(this FileSystemClient fs, ulong saveDataId, SaveDataFlags flags)
- {
- return SetSaveDataFlags(fs, saveDataId, SaveDataSpaceId.System, flags);
- }
-
- public static Result SetSaveDataFlags(this FileSystemClient fs, ulong saveDataId, SaveDataSpaceId spaceId,
- SaveDataFlags flags)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x70];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result SetSaveDataFlags(this FileSystemClient fs, ulong saveDataId, SaveDataFlags flags)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = SetFlags(fs, saveDataId, spaceId, flags);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = SetFlags(fs, saveDataId, spaceId, flags);
+ return SetSaveDataFlags(fs, saveDataId, SaveDataSpaceId.System, flags);
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result SetFlags(FileSystemClient fs, ulong saveDataId, SaveDataSpaceId spaceId, SaveDataFlags flags)
- {
- Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId,
- saveDataId);
- if (rc.IsFailure()) return rc;
-
- extraData.Flags = flags;
-
- return fs.Impl.WriteSaveDataFileSystemExtraData(spaceId, saveDataId, in extraData);
- }
- }
-
- public static Result SetSystemSaveDataFlags(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
- UserId userId, SaveDataFlags flags)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0xA0];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = SetFlags(fs, spaceId, saveDataId, userId, flags);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
- .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = SetFlags(fs, spaceId, saveDataId, userId, flags);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result SetFlags(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId,
+ public static Result SetSaveDataFlags(this FileSystemClient fs, ulong saveDataId, SaveDataSpaceId spaceId,
SaveDataFlags flags)
{
- var extraDataMask = new SaveDataExtraData();
- extraDataMask.Flags = unchecked((SaveDataFlags)0xFFFFFFFF);
+ Result rc;
+ Span logBuffer = stackalloc byte[0x70];
- var extraData = new SaveDataExtraData();
- extraData.Flags = flags;
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = SetFlags(fs, saveDataId, spaceId, flags);
+ Tick end = fs.Hos.Os.GetSystemTick();
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
- SaveDataType.System, userId, saveDataId);
- if (rc.IsFailure()) return rc;
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
- return fs.Impl.WriteSaveDataFileSystemExtraData(spaceId, in attribute, in extraData, in extraDataMask);
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = SetFlags(fs, saveDataId, spaceId, flags);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result SetFlags(FileSystemClient fs, ulong saveDataId, SaveDataSpaceId spaceId, SaveDataFlags flags)
+ {
+ Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId,
+ saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ extraData.Flags = flags;
+
+ return fs.Impl.WriteSaveDataFileSystemExtraData(spaceId, saveDataId, in extraData);
+ }
}
- }
- public static Result GetSaveDataTimeStamp(this FileSystemClient fs, out PosixTime timeStamp, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x30];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result SetSystemSaveDataFlags(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
+ UserId userId, SaveDataFlags flags)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetTimeStamp(fs, out timeStamp, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
+ Result rc;
+ Span logBuffer = stackalloc byte[0xA0];
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = SetFlags(fs, spaceId, saveDataId, userId, flags);
+ Tick end = fs.Hos.Os.GetSystemTick();
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16)
+ .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataFlags).AppendFormat((int)flags, 'X', 8);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = SetFlags(fs, spaceId, saveDataId, userId, flags);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result SetFlags(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, UserId userId,
+ SaveDataFlags flags)
+ {
+ SaveDataExtraData extraDataMask = default;
+ extraDataMask.Flags = unchecked((SaveDataFlags)0xFFFFFFFF);
+
+ SaveDataExtraData extraData = default;
+ extraData.Flags = flags;
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId,
+ SaveDataType.System, userId, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ return fs.Impl.WriteSaveDataFileSystemExtraData(spaceId, in attribute, in extraData, in extraDataMask);
+ }
}
- else
+
+ public static Result GetSaveDataTimeStamp(this FileSystemClient fs, out PosixTime timeStamp, ulong saveDataId)
{
- rc = GetTimeStamp(fs, out timeStamp, saveDataId);
+ Result rc;
+ Span logBuffer = stackalloc byte[0x30];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetTimeStamp(fs, out timeStamp, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetTimeStamp(fs, out timeStamp, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetTimeStamp(FileSystemClient fs, out PosixTime timeStamp, ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out timeStamp);
+
+ Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ timeStamp = new PosixTime(extraData.TimeStamp);
+ return Result.Success;
+ }
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetTimeStamp(FileSystemClient fs, out PosixTime timeStamp, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out timeStamp);
-
- Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
- if (rc.IsFailure()) return rc;
-
- timeStamp = new PosixTime(extraData.TimeStamp);
- return Result.Success;
- }
- }
-
- public static Result SetSaveDataTimeStamp(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
- PosixTime timeStamp)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x80];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = SetTimeStamp(fs, spaceId, saveDataId, timeStamp);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataTimeStamp).AppendFormat(timeStamp.Value, 'd');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = SetTimeStamp(fs, spaceId, saveDataId, timeStamp);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result SetTimeStamp(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
+ public static Result SetSaveDataTimeStamp(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
PosixTime timeStamp)
{
- var extraDataMask = new SaveDataExtraData();
- extraDataMask.TimeStamp = unchecked((long)0xFFFFFFFFFFFFFFFF);
+ Result rc;
+ Span logBuffer = stackalloc byte[0x80];
- var extraData = new SaveDataExtraData();
- extraData.TimeStamp = timeStamp.Value;
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = SetTimeStamp(fs, spaceId, saveDataId, timeStamp);
+ Tick end = fs.Hos.Os.GetSystemTick();
- return fs.Impl.WriteSaveDataFileSystemExtraData(spaceId, saveDataId, in extraData, in extraDataMask);
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataTimeStamp).AppendFormat(timeStamp.Value, 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = SetTimeStamp(fs, spaceId, saveDataId, timeStamp);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result SetTimeStamp(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
+ PosixTime timeStamp)
+ {
+ SaveDataExtraData extraDataMask = default;
+ extraDataMask.TimeStamp = unchecked((long)0xFFFFFFFFFFFFFFFF);
+
+ SaveDataExtraData extraData = default;
+ extraData.TimeStamp = timeStamp.Value;
+
+ return fs.Impl.WriteSaveDataFileSystemExtraData(spaceId, saveDataId, in extraData, in extraDataMask);
+ }
}
- }
- public static Result GetSaveDataTimeStamp(this FileSystemClient fs, out PosixTime timeStamp,
- SaveDataSpaceId spaceId, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result GetSaveDataTimeStamp(this FileSystemClient fs, out PosixTime timeStamp,
+ SaveDataSpaceId spaceId, ulong saveDataId)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetTimeStamp(fs, out timeStamp, spaceId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetTimeStamp(fs, out timeStamp, spaceId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetTimeStamp(fs, out timeStamp, spaceId, saveDataId);
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetTimeStamp(fs, out timeStamp, spaceId, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetTimeStamp(FileSystemClient fs, out PosixTime timeStamp, SaveDataSpaceId spaceId,
+ ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out timeStamp);
+
+ Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId,
+ saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ timeStamp = new PosixTime(extraData.TimeStamp);
+ return Result.Success;
+ }
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetTimeStamp(FileSystemClient fs, out PosixTime timeStamp, SaveDataSpaceId spaceId,
+ public static Result GetSaveDataAvailableSize(this FileSystemClientImpl fs, out long availableSize,
ulong saveDataId)
{
- UnsafeHelpers.SkipParamInit(out timeStamp);
+ UnsafeHelpers.SkipParamInit(out availableSize);
- Result rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId,
- saveDataId);
+ Result rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
if (rc.IsFailure()) return rc;
- timeStamp = new PosixTime(extraData.TimeStamp);
- return Result.Success;
- }
- }
-
- public static Result GetSaveDataAvailableSize(this FileSystemClientImpl fs, out long availableSize,
- ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out availableSize);
-
- Result rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
- if (rc.IsFailure()) return rc;
-
- availableSize = extraData.DataSize;
- return Result.Success;
- }
-
- public static Result GetSaveDataAvailableSize(this FileSystemClientImpl fs, out long availableSize,
- SaveDataSpaceId spaceId, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out availableSize);
-
- Result rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId, saveDataId);
- if (rc.IsFailure()) return rc;
-
- availableSize = extraData.DataSize;
- return Result.Success;
- }
-
- public static Result GetSaveDataAvailableSize(this FileSystemClient fs, out long availableSize,
- ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x40];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.GetSaveDataAvailableSize(out availableSize, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.GetSaveDataAvailableSize(out availableSize, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result GetSaveDataAvailableSize(this FileSystemClient fs, out long availableSize,
- SaveDataSpaceId spaceId, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.GetSaveDataAvailableSize(out availableSize, spaceId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.GetSaveDataAvailableSize(out availableSize, spaceId, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result GetSaveDataJournalSize(this FileSystemClientImpl fs, out long journalSize,
- ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out journalSize);
-
- Result rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
- if (rc.IsFailure()) return rc;
-
- journalSize = extraData.JournalSize;
- return Result.Success;
- }
-
- public static Result GetSaveDataJournalSize(this FileSystemClientImpl fs, out long journalSize,
- SaveDataSpaceId spaceId, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out journalSize);
-
- Result rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId, saveDataId);
- if (rc.IsFailure()) return rc;
-
- journalSize = extraData.JournalSize;
- return Result.Success;
- }
-
- public static Result GetSaveDataJournalSize(this FileSystemClient fs, out long journalSize, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x40];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.GetSaveDataJournalSize(out journalSize, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.GetSaveDataJournalSize(out journalSize, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result GetSaveDataJournalSize(this FileSystemClient fs, out long journalSize,
- SaveDataSpaceId spaceId, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.GetSaveDataJournalSize(out journalSize, spaceId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.GetSaveDataJournalSize(out journalSize, spaceId, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result GetSaveDataCommitId(this FileSystemClient fs, out long commitId, SaveDataSpaceId spaceId,
- ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetCommitId(fs, out commitId, spaceId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetCommitId(fs, out commitId, spaceId, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetCommitId(FileSystemClient fs, out long commitId, SaveDataSpaceId spaceId, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out commitId);
-
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- return fileSystemProxy.Get.GetSaveDataCommitId(out commitId, spaceId, saveDataId);
- }
- }
-
- public static Result SetSaveDataCommitId(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
- long commitId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x80];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = SetCommitId(fs, spaceId, saveDataId, commitId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
- .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataCommitId).AppendFormat(commitId, 'X', 16);
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = SetCommitId(fs, spaceId, saveDataId, commitId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result SetCommitId(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, long commitId)
- {
- var extraDataMask = new SaveDataExtraData();
- extraDataMask.CommitId = unchecked((long)0xFFFFFFFFFFFFFFFF);
-
- var extraData = new SaveDataExtraData();
- extraData.CommitId = commitId;
-
- return fs.Impl.WriteSaveDataFileSystemExtraData(spaceId, saveDataId, in extraData, in extraDataMask);
- }
- }
-
- public static Result QuerySaveDataInternalStorageTotalSize(this FileSystemClientImpl fs, out long size,
- SaveDataSpaceId spaceId, ulong saveDataId)
- {
- UnsafeHelpers.SkipParamInit(out size);
-
- using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
-
- return fileSystemProxy.Get.QuerySaveDataInternalStorageTotalSize(out size, spaceId, saveDataId);
- }
-
- public static Result QuerySaveDataInternalStorageTotalSize(this FileSystemClient fs, out long size,
- SaveDataSpaceId spaceId, ulong saveDataId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x50];
-
- if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.QuerySaveDataInternalStorageTotalSize(out size, spaceId, saveDataId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var idString = new IdString();
- var sb = new U8StringBuilder(logBuffer, true);
-
- sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
- .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.QuerySaveDataInternalStorageTotalSize(out size, spaceId, saveDataId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result VerifySaveData(this FileSystemClient fs, out bool isValid, ulong saveDataId,
- Span workBuffer)
- {
- return VerifySaveData(fs, out isValid, SaveDataSpaceId.System, saveDataId, workBuffer);
- }
-
- public static Result VerifySaveData(this FileSystemClient fs, out bool isValid, SaveDataSpaceId spaceId,
- ulong saveDataId, Span workBuffer)
- {
- UnsafeHelpers.SkipParamInit(out isValid);
-
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.VerifySaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId,
- new OutBuffer(workBuffer));
-
- if (ResultFs.DataCorrupted.Includes(rc))
- {
- isValid = false;
+ availableSize = extraData.DataSize;
return Result.Success;
}
- fs.Impl.AbortIfNeeded(rc);
-
- if (rc.IsSuccess())
+ public static Result GetSaveDataAvailableSize(this FileSystemClientImpl fs, out long availableSize,
+ SaveDataSpaceId spaceId, ulong saveDataId)
{
- isValid = true;
+ UnsafeHelpers.SkipParamInit(out availableSize);
+
+ Result rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ availableSize = extraData.DataSize;
return Result.Success;
}
- return rc;
- }
-
- public static Result CorruptSaveDataForDebug(this FileSystemClient fs, ulong saveDataId)
- {
- return CorruptSaveDataForDebug(fs, SaveDataSpaceId.System, saveDataId);
- }
-
- public static Result CorruptSaveDataForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
- ulong saveDataId)
- {
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.CorruptSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result CorruptSaveDataForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
- ulong saveDataId, long offset)
- {
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.CorruptSaveDataFileSystemByOffset(spaceId, saveDataId, offset);
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static void DisableAutoSaveDataCreation(this FileSystemClient fs)
- {
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- Result rc = fileSystemProxy.Get.DisableAutoSaveDataCreation();
-
- fs.Impl.LogResultErrorMessage(rc);
- Abort.DoAbortUnless(rc.IsSuccess());
- }
-
- public static Result DeleteCacheStorage(this FileSystemClient fs, int index)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x20];
-
- if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
+ public static Result GetSaveDataAvailableSize(this FileSystemClient fs, out long availableSize,
+ ulong saveDataId)
{
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = Delete(fs, index);
- Tick end = fs.Hos.Os.GetSystemTick();
+ Result rc;
+ Span logBuffer = stackalloc byte[0x40];
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogIndex).AppendFormat(index, 'd');
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.GetSaveDataAvailableSize(out availableSize, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = Delete(fs, index);
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.GetSaveDataAvailableSize(out availableSize, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result Delete(FileSystemClient fs, int index)
+ public static Result GetSaveDataAvailableSize(this FileSystemClient fs, out long availableSize,
+ SaveDataSpaceId spaceId, ulong saveDataId)
{
- if (index < 0)
- return ResultFs.InvalidArgument.Log();
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.GetSaveDataAvailableSize(out availableSize, spaceId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
- return fileSystemProxy.Get.DeleteCacheStorage((ushort)index);
- }
- }
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
- public static Result GetCacheStorageSize(this FileSystemClient fs, out long saveSize, out long journalSize,
- int index)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x60];
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
- if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetSize(fs, out saveSize, out journalSize, index);
- Tick end = fs.Hos.Os.GetSystemTick();
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.GetSaveDataAvailableSize(out availableSize, spaceId, saveDataId);
+ }
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogIndex).AppendFormat(index, 'd')
- .Append(LogSaveDataSize).AppendFormat(AccessLogImpl.DereferenceOutValue(in saveSize, rc), 'd')
- .Append(LogSaveDataJournalSize)
- .AppendFormat(AccessLogImpl.DereferenceOutValue(in journalSize, rc), 'd');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetSize(fs, out saveSize, out journalSize, index);
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
}
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetSize(FileSystemClient fs, out long saveSize, out long journalSize, int index)
+ public static Result GetSaveDataJournalSize(this FileSystemClientImpl fs, out long journalSize,
+ ulong saveDataId)
{
- UnsafeHelpers.SkipParamInit(out saveSize, out journalSize);
+ UnsafeHelpers.SkipParamInit(out journalSize);
- if (index < 0)
- return ResultFs.InvalidArgument.Log();
-
- // Note: Nintendo gets the service object in the outer function and captures it for the inner function
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- return fileSystemProxy.Get.GetCacheStorageSize(out saveSize, out journalSize, (ushort)index);
- }
- }
-
- public static Result UpdateSaveDataMacForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
- ulong saveDataId)
- {
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- return fileSystemProxy.Get.UpdateSaveDataMacForDebug(spaceId, saveDataId);
- }
-
- public static Result ListApplicationAccessibleSaveDataOwnerId(this FileSystemClient fs, out int readCount,
- Span idBuffer, Ncm.ApplicationId applicationId, int programIndex, int startIndex)
- {
- if (idBuffer.IsEmpty)
- {
- readCount = 0;
- return Result.Success;
- }
-
- using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
-
- var programId = new ProgramId(applicationId.Value + (uint)programIndex);
- OutBuffer idOutBuffer = OutBuffer.FromSpan(idBuffer);
-
- Result rc = fileSystemProxy.Get.ListAccessibleSaveDataOwnerId(out readCount, idOutBuffer, programId, startIndex,
- idBuffer.Length);
- fs.Impl.AbortIfNeeded(rc);
- return rc;
- }
-
- public static Result GetSaveDataRestoreFlag(this FileSystemClient fs, out bool isRestoreFlagSet,
- U8Span mountName)
- {
- UnsafeHelpers.SkipParamInit(out isRestoreFlagSet);
-
- Result rc;
- FileSystemAccessor fileSystem;
- Span logBuffer = stackalloc byte[0x40];
-
- if (fs.Impl.IsEnabledAccessLog())
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = fs.Impl.Find(out fileSystem, mountName);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogName).Append(mountName).Append(LogQuote);
-
- fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = fs.Impl.Find(out fileSystem, mountName);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- if (rc.IsFailure()) return rc;
-
- if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetRestoreFlagValue(fs, out isRestoreFlagSet, fileSystem);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- ReadOnlySpan isSetString =
- AccessLogImpl.ConvertFromBoolToAccessLogBooleanValue(
- AccessLogImpl.DereferenceOutValue(in isRestoreFlagSet, rc));
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogName).Append(mountName).Append(LogQuote)
- .Append(LogRestoreFlag).Append(isSetString);
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetRestoreFlagValue(fs, out isRestoreFlagSet, fileSystem);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetRestoreFlagValue(FileSystemClient fs, out bool isRestoreFlagSet,
- FileSystemAccessor fileSystem)
- {
- Unsafe.SkipInit(out isRestoreFlagSet);
-
- if (fileSystem is null)
- return ResultFs.NullptrArgument.Log();
-
- Result rc = fileSystem.GetSaveDataAttribute(out SaveDataAttribute attribute);
+ Result rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, saveDataId);
if (rc.IsFailure()) return rc;
- if (attribute.ProgramId == Fs.SaveData.InvalidProgramId)
- attribute.ProgramId = Fs.SaveData.AutoResolveCallerProgramId;
-
- var extraDataMask = new SaveDataExtraData();
- extraDataMask.Flags = SaveDataFlags.Restore;
-
- rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId.User,
- in attribute, in extraDataMask);
- if (rc.IsFailure()) return rc;
-
- isRestoreFlagSet = extraData.Flags.HasFlag(SaveDataFlags.Restore);
- return Result.Success;
- }
- }
-
- public static Result GetDeviceSaveDataSize(this FileSystemClient fs, out long saveSize,
- out long journalSize, ApplicationId applicationId)
- {
- Result rc;
- Span logBuffer = stackalloc byte[0x70];
-
- if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
- {
- Tick start = fs.Hos.Os.GetSystemTick();
- rc = GetSize(fs, out saveSize, out journalSize, applicationId);
- Tick end = fs.Hos.Os.GetSystemTick();
-
- var sb = new U8StringBuilder(logBuffer, true);
- sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
- .Append(LogSaveDataSize).AppendFormat(AccessLogImpl.DereferenceOutValue(in saveSize, rc), 'd')
- .Append(LogSaveDataJournalSize)
- .AppendFormat(AccessLogImpl.DereferenceOutValue(in journalSize, rc), 'd');
-
- fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
- }
- else
- {
- rc = GetSize(fs, out saveSize, out journalSize, applicationId);
- }
-
- fs.Impl.AbortIfNeeded(rc);
- return rc;
-
- static Result GetSize(FileSystemClient fs, out long saveSize, out long journalSize,
- ApplicationId applicationId)
- {
- UnsafeHelpers.SkipParamInit(out saveSize, out journalSize);
-
- var extraDataMask = new SaveDataExtraData();
- extraDataMask.DataSize = unchecked((long)0xFFFFFFFFFFFFFFFF);
- extraDataMask.JournalSize = unchecked((long)0xFFFFFFFFFFFFFFFF);
-
- Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value),
- SaveDataType.Device, Fs.SaveData.InvalidUserId, 0);
- if (rc.IsFailure()) return rc;
-
- rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId.User,
- in attribute, in extraDataMask);
- if (rc.IsFailure()) return rc;
-
- saveSize = extraData.DataSize;
journalSize = extraData.JournalSize;
-
return Result.Success;
}
+
+ public static Result GetSaveDataJournalSize(this FileSystemClientImpl fs, out long journalSize,
+ SaveDataSpaceId spaceId, ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out journalSize);
+
+ Result rc = fs.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, spaceId, saveDataId);
+ if (rc.IsFailure()) return rc;
+
+ journalSize = extraData.JournalSize;
+ return Result.Success;
+ }
+
+ public static Result GetSaveDataJournalSize(this FileSystemClient fs, out long journalSize, ulong saveDataId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x40];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.GetSaveDataJournalSize(out journalSize, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.GetSaveDataJournalSize(out journalSize, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result GetSaveDataJournalSize(this FileSystemClient fs, out long journalSize,
+ SaveDataSpaceId spaceId, ulong saveDataId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.GetSaveDataJournalSize(out journalSize, spaceId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.GetSaveDataJournalSize(out journalSize, spaceId, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result GetSaveDataCommitId(this FileSystemClient fs, out long commitId, SaveDataSpaceId spaceId,
+ ulong saveDataId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetCommitId(fs, out commitId, spaceId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetCommitId(fs, out commitId, spaceId, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetCommitId(FileSystemClient fs, out long commitId, SaveDataSpaceId spaceId, ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out commitId);
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ return fileSystemProxy.Get.GetSaveDataCommitId(out commitId, spaceId, saveDataId);
+ }
+ }
+
+ public static Result SetSaveDataCommitId(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
+ long commitId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x80];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = SetCommitId(fs, spaceId, saveDataId, commitId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
+ .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataCommitId).AppendFormat(commitId, 'X', 16);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = SetCommitId(fs, spaceId, saveDataId, commitId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result SetCommitId(FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, long commitId)
+ {
+ SaveDataExtraData extraDataMask = default;
+ extraDataMask.CommitId = unchecked((long)0xFFFFFFFFFFFFFFFF);
+
+ SaveDataExtraData extraData = default;
+ extraData.CommitId = commitId;
+
+ return fs.Impl.WriteSaveDataFileSystemExtraData(spaceId, saveDataId, in extraData, in extraDataMask);
+ }
+ }
+
+ public static Result QuerySaveDataInternalStorageTotalSize(this FileSystemClientImpl fs, out long size,
+ SaveDataSpaceId spaceId, ulong saveDataId)
+ {
+ UnsafeHelpers.SkipParamInit(out size);
+
+ using SharedRef fileSystemProxy = fs.GetFileSystemProxyServiceObject();
+
+ return fileSystemProxy.Get.QuerySaveDataInternalStorageTotalSize(out size, spaceId, saveDataId);
+ }
+
+ public static Result QuerySaveDataInternalStorageTotalSize(this FileSystemClient fs, out long size,
+ SaveDataSpaceId spaceId, ulong saveDataId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x50];
+
+ if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System) && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.QuerySaveDataInternalStorageTotalSize(out size, spaceId, saveDataId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var idString = new IdString();
+ var sb = new U8StringBuilder(logBuffer, true);
+
+ sb.Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
+ .Append(LogSaveDataId).AppendFormat(saveDataId, 'X');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.QuerySaveDataInternalStorageTotalSize(out size, spaceId, saveDataId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result VerifySaveData(this FileSystemClient fs, out bool isValid, ulong saveDataId,
+ Span workBuffer)
+ {
+ return VerifySaveData(fs, out isValid, SaveDataSpaceId.System, saveDataId, workBuffer);
+ }
+
+ public static Result VerifySaveData(this FileSystemClient fs, out bool isValid, SaveDataSpaceId spaceId,
+ ulong saveDataId, Span workBuffer)
+ {
+ UnsafeHelpers.SkipParamInit(out isValid);
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.VerifySaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId,
+ new OutBuffer(workBuffer));
+
+ if (ResultFs.DataCorrupted.Includes(rc))
+ {
+ isValid = false;
+ return Result.Success;
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+
+ if (rc.IsSuccess())
+ {
+ isValid = true;
+ return Result.Success;
+ }
+
+ return rc;
+ }
+
+ public static Result CorruptSaveDataForDebug(this FileSystemClient fs, ulong saveDataId)
+ {
+ return CorruptSaveDataForDebug(fs, SaveDataSpaceId.System, saveDataId);
+ }
+
+ public static Result CorruptSaveDataForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
+ ulong saveDataId)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.CorruptSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result CorruptSaveDataForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
+ ulong saveDataId, long offset)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.CorruptSaveDataFileSystemByOffset(spaceId, saveDataId, offset);
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static void DisableAutoSaveDataCreation(this FileSystemClient fs)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.DisableAutoSaveDataCreation();
+
+ fs.Impl.LogResultErrorMessage(rc);
+ Abort.DoAbortUnless(rc.IsSuccess());
+ }
+
+ public static Result DeleteCacheStorage(this FileSystemClient fs, int index)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x20];
+
+ if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = Delete(fs, index);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogIndex).AppendFormat(index, 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = Delete(fs, index);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result Delete(FileSystemClient fs, int index)
+ {
+ if (index < 0)
+ return ResultFs.InvalidArgument.Log();
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ return fileSystemProxy.Get.DeleteCacheStorage((ushort)index);
+ }
+ }
+
+ public static Result GetCacheStorageSize(this FileSystemClient fs, out long saveSize, out long journalSize,
+ int index)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x60];
+
+ if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetSize(fs, out saveSize, out journalSize, index);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogIndex).AppendFormat(index, 'd')
+ .Append(LogSaveDataSize).AppendFormat(AccessLogImpl.DereferenceOutValue(in saveSize, rc), 'd')
+ .Append(LogSaveDataJournalSize)
+ .AppendFormat(AccessLogImpl.DereferenceOutValue(in journalSize, rc), 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetSize(fs, out saveSize, out journalSize, index);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetSize(FileSystemClient fs, out long saveSize, out long journalSize, int index)
+ {
+ UnsafeHelpers.SkipParamInit(out saveSize, out journalSize);
+
+ if (index < 0)
+ return ResultFs.InvalidArgument.Log();
+
+ // Note: Nintendo gets the service object in the outer function and captures it for the inner function
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ return fileSystemProxy.Get.GetCacheStorageSize(out saveSize, out journalSize, (ushort)index);
+ }
+ }
+
+ public static Result OpenCacheStorageList(this FileSystemClient fs, out CacheStorageListHandle handle)
+ {
+ UnsafeHelpers.SkipParamInit(out handle);
+
+ Result rc;
+ Span logBuffer = stackalloc byte[0x40];
+
+ CacheStorageListCache listCache;
+
+ if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = Open(fs, out listCache);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogCacheStorageListHandle).AppendFormat(listCache.GetHashCode(), 'x');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = Open(fs, out listCache);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ handle = new CacheStorageListHandle(listCache);
+ return Result.Success;
+
+ static Result Open(FileSystemClient fs, out CacheStorageListCache listCache)
+ {
+ UnsafeHelpers.SkipParamInit(out listCache);
+ CacheStorageListCache tempListCache = null;
+
+ Result rc = Utility.DoContinuouslyUntilSaveDataListFetched(fs.Hos, () =>
+ {
+ // Note: Nintendo uses the same CacheStorageListCache for every attempt to fetch the save data list
+ // without clearing it between runs. This means that if it has to retry fetching the list, the
+ // CacheStorageListCache may contain duplicate entries if the save data indexer was reset while this
+ // function was running.
+ tempListCache = new CacheStorageListCache();
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var reader = new SharedRef();
+
+ Result result = fileSystemProxy.Get.OpenSaveDataInfoReaderOnlyCacheStorage(ref reader.Ref());
+ if (result.IsFailure()) return result.Miss();
+
+ while (true)
+ {
+ Unsafe.SkipInit(out SaveDataInfo info);
+
+ result = reader.Get.Read(out long readCount, new OutBuffer(SpanHelpers.AsByteSpan(ref info)));
+ if (result.IsFailure()) return result.Miss();
+
+ if (readCount == 0)
+ break;
+
+ var cacheEntry = new CacheStorageListCache.CacheEntry(info.Index);
+ result = tempListCache.PushBack(in cacheEntry);
+ if (result.IsFailure()) return result.Miss();
+ }
+
+ return Result.Success;
+ });
+ if (rc.IsFailure()) return rc.Miss();
+
+ Assert.SdkRequiresNotNull(tempListCache);
+
+ listCache = tempListCache;
+ return Result.Success;
+ }
+ }
+
+ public static Result ReadCacheStorageList(this FileSystemClient fs, out int storageInfoReadCount,
+ Span storageInfoBuffer, CacheStorageListHandle handle)
+ {
+ UnsafeHelpers.SkipParamInit(out storageInfoReadCount);
+
+ Result rc;
+ Span logBuffer = stackalloc byte[0x70];
+
+ if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = Read(out storageInfoReadCount, storageInfoBuffer, handle);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogCacheStorageListHandle).AppendFormat(handle.Cache.GetHashCode(), 'x')
+ .Append(LogInfoBufferCount).AppendFormat(storageInfoBuffer.Length, 'X')
+ .Append(LogCacheStorageCount).AppendFormat(AccessLogImpl.DereferenceOutValue(in storageInfoReadCount, rc), 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = Read(out storageInfoReadCount, storageInfoBuffer, handle);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+
+ static Result Read(out int storageCount, Span infoBuffer, CacheStorageListHandle handle)
+ {
+ int count = 0;
+
+ var listCache = CacheStorageListCache.GetCacheStorageListCache(handle);
+
+ while (count < infoBuffer.Length)
+ {
+ ref readonly CacheStorageListCache.CacheEntry entry = ref listCache.PopFront();
+
+ // We're done iterating if we get a null ref
+ if (Unsafe.IsNullRef(ref Unsafe.AsRef(in entry)))
+ break;
+
+ infoBuffer[count] = default;
+ infoBuffer[count].Index = entry.GetCacheStorageIndex();
+ count++;
+ }
+
+ storageCount = count;
+ return Result.Success;
+ }
+ }
+
+ public static void CloseCacheStorageList(this FileSystemClient fs, CacheStorageListHandle handle)
+ {
+ Span logBuffer = stackalloc byte[0x40];
+
+ var listCache = CacheStorageListCache.GetCacheStorageListCache(handle);
+
+ listCache?.Dispose();
+
+ if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogCacheStorageListHandle).AppendFormat(handle.Cache.GetHashCode(), 'x');
+
+ fs.Impl.OutputAccessLog(Result.Success, start, end, null, new U8Span(sb.Buffer));
+ }
+ }
+
+ public static Result UpdateSaveDataMacForDebug(this FileSystemClient fs, SaveDataSpaceId spaceId,
+ ulong saveDataId)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ Result rc = fileSystemProxy.Get.UpdateSaveDataMacForDebug(spaceId, saveDataId);
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result ListApplicationAccessibleSaveDataOwnerId(this FileSystemClient fs, out int readCount,
+ Span idBuffer, Ncm.ApplicationId applicationId, int programIndex, int startIndex)
+ {
+ if (idBuffer.IsEmpty)
+ {
+ readCount = 0;
+ return Result.Success;
+ }
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+
+ var programId = new ProgramId(applicationId.Value + (uint)programIndex);
+ OutBuffer idOutBuffer = OutBuffer.FromSpan(idBuffer);
+
+ Result rc = fileSystemProxy.Get.ListAccessibleSaveDataOwnerId(out readCount, idOutBuffer, programId, startIndex,
+ idBuffer.Length);
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+ }
+
+ public static Result GetSaveDataRestoreFlag(this FileSystemClient fs, out bool isRestoreFlagSet,
+ U8Span mountName)
+ {
+ UnsafeHelpers.SkipParamInit(out isRestoreFlagSet);
+
+ Result rc;
+ FileSystemAccessor fileSystem;
+ Span logBuffer = stackalloc byte[0x40];
+
+ if (fs.Impl.IsEnabledAccessLog())
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = fs.Impl.Find(out fileSystem, mountName);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogName).Append(mountName).Append(LogQuote);
+
+ fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = fs.Impl.Find(out fileSystem, mountName);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc;
+
+ if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetRestoreFlagValue(fs, out isRestoreFlagSet, fileSystem);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ ReadOnlySpan isSetString =
+ AccessLogImpl.ConvertFromBoolToAccessLogBooleanValue(
+ AccessLogImpl.DereferenceOutValue(in isRestoreFlagSet, rc));
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogName).Append(mountName).Append(LogQuote)
+ .Append(LogRestoreFlag).Append(isSetString);
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetRestoreFlagValue(fs, out isRestoreFlagSet, fileSystem);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetRestoreFlagValue(FileSystemClient fs, out bool isRestoreFlagSet,
+ FileSystemAccessor fileSystem)
+ {
+ Unsafe.SkipInit(out isRestoreFlagSet);
+
+ if (fileSystem is null)
+ return ResultFs.NullptrArgument.Log();
+
+ Result rc = fileSystem.GetSaveDataAttribute(out SaveDataAttribute attribute);
+ if (rc.IsFailure()) return rc;
+
+ if (attribute.ProgramId == Fs.SaveData.InvalidProgramId)
+ attribute.ProgramId = Fs.SaveData.AutoResolveCallerProgramId;
+
+ SaveDataExtraData extraDataMask = default;
+ extraDataMask.Flags = SaveDataFlags.Restore;
+
+ rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId.User,
+ in attribute, in extraDataMask);
+ if (rc.IsFailure()) return rc;
+
+ isRestoreFlagSet = extraData.Flags.HasFlag(SaveDataFlags.Restore);
+ return Result.Success;
+ }
+ }
+
+ public static Result GetDeviceSaveDataSize(this FileSystemClient fs, out long saveSize,
+ out long journalSize, ApplicationId applicationId)
+ {
+ Result rc;
+ Span logBuffer = stackalloc byte[0x70];
+
+ if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledHandleAccessLog(null))
+ {
+ Tick start = fs.Hos.Os.GetSystemTick();
+ rc = GetSize(fs, out saveSize, out journalSize, applicationId);
+ Tick end = fs.Hos.Os.GetSystemTick();
+
+ var sb = new U8StringBuilder(logBuffer, true);
+ sb.Append(LogApplicationId).AppendFormat(applicationId.Value, 'X')
+ .Append(LogSaveDataSize).AppendFormat(AccessLogImpl.DereferenceOutValue(in saveSize, rc), 'd')
+ .Append(LogSaveDataJournalSize)
+ .AppendFormat(AccessLogImpl.DereferenceOutValue(in journalSize, rc), 'd');
+
+ fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
+ }
+ else
+ {
+ rc = GetSize(fs, out saveSize, out journalSize, applicationId);
+ }
+
+ fs.Impl.AbortIfNeeded(rc);
+ return rc;
+
+ static Result GetSize(FileSystemClient fs, out long saveSize, out long journalSize,
+ ApplicationId applicationId)
+ {
+ UnsafeHelpers.SkipParamInit(out saveSize, out journalSize);
+
+ SaveDataExtraData extraDataMask = default;
+ extraDataMask.DataSize = unchecked((long)0xFFFFFFFFFFFFFFFF);
+ extraDataMask.JournalSize = unchecked((long)0xFFFFFFFFFFFFFFFF);
+
+ Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value),
+ SaveDataType.Device, Fs.SaveData.InvalidUserId, staticSaveDataId: 0);
+ if (rc.IsFailure()) return rc;
+
+ rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId.User,
+ in attribute, in extraDataMask);
+ if (rc.IsFailure()) return rc;
+
+ saveSize = extraData.DataSize;
+ journalSize = extraData.JournalSize;
+
+ return Result.Success;
+ }
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/LibHac/Fs/Utility.cs b/src/LibHac/Fs/Utility.cs
new file mode 100644
index 00000000..955c983f
--- /dev/null
+++ b/src/LibHac/Fs/Utility.cs
@@ -0,0 +1,50 @@
+using System;
+using LibHac.Account;
+using LibHac.Os;
+
+namespace LibHac.Fs;
+
+///
+/// Contains various utility functions used by FS client code.
+///
+/// Based on nnSdk 13.4.0
+public static class Utility
+{
+ public static UserId ConvertAccountUidToFsUserId(Uid uid)
+ {
+ return new UserId(uid.Id.High, uid.Id.Low);
+ }
+
+ public static Result CheckUid(HorizonClient hos, Uid uid)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Result DoContinuouslyUntilSaveDataListFetched(HorizonClient hos, Func listGetter)
+ {
+ const int maxTryCount = 5;
+ const int initialSleepTimeMs = 5;
+ const int sleepTimeMultiplier = 2;
+
+ Result lastResult = Result.Success;
+ long sleepTime = initialSleepTimeMs;
+
+ for (int i = 0; i < maxTryCount; i++)
+ {
+ Result rc = listGetter();
+
+ if (rc.IsSuccess())
+ return rc;
+
+ // Try again if any save data were added or removed while getting the list
+ if (!ResultFs.InvalidHandle.Includes(rc))
+ return rc.Miss();
+
+ lastResult = rc;
+ hos.Os.SleepThread(TimeSpan.FromMilliSeconds(sleepTime));
+ sleepTime *= sleepTimeMultiplier;
+ }
+
+ return lastResult.Log();
+ }
+}
\ No newline at end of file
diff --git a/src/LibHac/FsSrv/FileSystemProxyCoreImpl.cs b/src/LibHac/FsSrv/FileSystemProxyCoreImpl.cs
index c4e30339..46872992 100644
--- a/src/LibHac/FsSrv/FileSystemProxyCoreImpl.cs
+++ b/src/LibHac/FsSrv/FileSystemProxyCoreImpl.cs
@@ -6,7 +6,8 @@ using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.Fs.Shim;
using LibHac.FsSrv.FsCreator;
-using LibHac.FsSrv.Impl;
+
+using Utility = LibHac.FsSrv.Impl.Utility;
namespace LibHac.FsSrv;
diff --git a/src/LibHac/FsSrv/FsCreator/EmulatedBisFileSystemCreator.cs b/src/LibHac/FsSrv/FsCreator/EmulatedBisFileSystemCreator.cs
index 9255f1b2..368d66ff 100644
--- a/src/LibHac/FsSrv/FsCreator/EmulatedBisFileSystemCreator.cs
+++ b/src/LibHac/FsSrv/FsCreator/EmulatedBisFileSystemCreator.cs
@@ -2,7 +2,8 @@
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
-using LibHac.FsSrv.Impl;
+
+using Utility = LibHac.FsSrv.Impl.Utility;
namespace LibHac.FsSrv.FsCreator;
@@ -134,4 +135,4 @@ public class EmulatedBisFileSystemCreator : IBuiltInStorageFileSystemCreator
return string.Empty;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/LibHac/FsSrv/FsCreator/EmulatedSdCardFileSystemCreator.cs b/src/LibHac/FsSrv/FsCreator/EmulatedSdCardFileSystemCreator.cs
index ef4a5234..b7359146 100644
--- a/src/LibHac/FsSrv/FsCreator/EmulatedSdCardFileSystemCreator.cs
+++ b/src/LibHac/FsSrv/FsCreator/EmulatedSdCardFileSystemCreator.cs
@@ -2,9 +2,10 @@
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
-using LibHac.FsSrv.Impl;
using LibHac.Util;
+using Utility = LibHac.FsSrv.Impl.Utility;
+
namespace LibHac.FsSrv.FsCreator;
public class EmulatedSdCardFileSystemCreator : ISdCardProxyFileSystemCreator, IDisposable
@@ -85,4 +86,4 @@ public class EmulatedSdCardFileSystemCreator : ISdCardProxyFileSystemCreator, ID
{
throw new NotImplementedException();
}
-}
+}
\ No newline at end of file
diff --git a/src/LibHac/Tools/FsSystem/FileSystemExtensions.cs b/src/LibHac/Tools/FsSystem/FileSystemExtensions.cs
index 4df57c9d..72c0c451 100644
--- a/src/LibHac/Tools/FsSystem/FileSystemExtensions.cs
+++ b/src/LibHac/Tools/FsSystem/FileSystemExtensions.cs
@@ -10,6 +10,7 @@ using LibHac.FsSystem;
using LibHac.Tools.Fs;
using LibHac.Util;
using Path = LibHac.Fs.Path;
+using Utility = LibHac.FsSystem.Utility;
namespace LibHac.Tools.FsSystem;
diff --git a/tests/LibHac.Tests/Fs/FileSystemClientTests/ApplicationSaveDataManagementTests.cs b/tests/LibHac.Tests/Fs/FileSystemClientTests/ApplicationSaveDataManagementTests.cs
index 560d8dae..97f3d8d5 100644
--- a/tests/LibHac.Tests/Fs/FileSystemClientTests/ApplicationSaveDataManagementTests.cs
+++ b/tests/LibHac.Tests/Fs/FileSystemClientTests/ApplicationSaveDataManagementTests.cs
@@ -35,7 +35,7 @@ public class ApplicationSaveDataManagementTests
Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId);
- Assert.Equal(ConvertAccountUidToFsUserId(userId), info[0].UserId);
+ Assert.Equal(Utility.ConvertAccountUidToFsUserId(userId), info[0].UserId);
Assert.Equal(SaveDataType.Account, info[0].Type);
}
diff --git a/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs b/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs
index 5bf97d8c..dda8a063 100644
--- a/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs
+++ b/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs
@@ -577,6 +577,73 @@ public class SaveDataManagement
Assert.Equal(timeStamp, actualTimeStamp);
}
+ [Fact]
+ public void OpenCacheStorageList_ReadIntoLargeBuffer_AllIndexesAreRead()
+ {
+ var applicationId = new Ncm.ApplicationId(1);
+
+ Horizon hos = HorizonFactory.CreateBasicHorizon();
+
+ HorizonClient client = hos.CreateHorizonClient(new ProgramLocation(applicationId, StorageId.BuiltInSystem),
+ (AccessControlBits.Bits)ulong.MaxValue);
+
+ Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, 0, SaveDataFlags.None));
+ Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 6, 0, 0, SaveDataFlags.None));
+ Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 2, 0, 0, SaveDataFlags.None));
+ Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 3, 0, 0, SaveDataFlags.None));
+
+ Assert.Success(client.Fs.OpenCacheStorageList(out CacheStorageListHandle handle));
+ var infoBuffer = new CacheStorageInfo[5];
+
+ Assert.Success(client.Fs.ReadCacheStorageList(out int readCount, infoBuffer, handle));
+
+ Assert.Equal(4, readCount);
+
+ Assert.Equal(0, infoBuffer[0].Index);
+ Assert.Equal(2, infoBuffer[1].Index);
+ Assert.Equal(3, infoBuffer[2].Index);
+ Assert.Equal(6, infoBuffer[3].Index);
+
+ client.Fs.CloseCacheStorageList(handle);
+ }
+
+ [Fact]
+ public void OpenCacheStorageList_ReadIntoMultipleBuffers_AllIndexesAreRead()
+ {
+ var applicationId = new Ncm.ApplicationId(1);
+
+ Horizon hos = HorizonFactory.CreateBasicHorizon();
+
+ HorizonClient client = hos.CreateHorizonClient(new ProgramLocation(applicationId, StorageId.BuiltInSystem),
+ (AccessControlBits.Bits)ulong.MaxValue);
+
+ Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, 0, SaveDataFlags.None));
+ Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 6, 0, 0, SaveDataFlags.None));
+ Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 2, 0, 0, SaveDataFlags.None));
+ Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 3, 0, 0, SaveDataFlags.None));
+
+ Assert.Success(client.Fs.OpenCacheStorageList(out CacheStorageListHandle handle));
+ var infoBuffer = new CacheStorageInfo[2];
+
+ Assert.Success(client.Fs.ReadCacheStorageList(out int readCount, infoBuffer, handle));
+
+ Assert.Equal(2, readCount);
+ Assert.Equal(0, infoBuffer[0].Index);
+ Assert.Equal(2, infoBuffer[1].Index);
+
+ Assert.Success(client.Fs.ReadCacheStorageList(out readCount, infoBuffer, handle));
+
+ Assert.Equal(2, readCount);
+ Assert.Equal(3, infoBuffer[0].Index);
+ Assert.Equal(6, infoBuffer[1].Index);
+
+ Assert.Success(client.Fs.ReadCacheStorageList(out readCount, infoBuffer, handle));
+
+ Assert.Equal(0, readCount);
+
+ client.Fs.CloseCacheStorageList(handle);
+ }
+
private static Result PopulateSaveData(FileSystemClient fs, int count, int seed = -1)
{
if (seed == -1)
diff --git a/tests/LibHac.Tests/Fs/TypeLayoutTests.cs b/tests/LibHac.Tests/Fs/TypeLayoutTests.cs
index bbef6c80..363850a6 100644
--- a/tests/LibHac.Tests/Fs/TypeLayoutTests.cs
+++ b/tests/LibHac.Tests/Fs/TypeLayoutTests.cs
@@ -354,4 +354,15 @@ public class TypeLayoutTests
Assert.Equal(3, GetOffset(in s, in s.CompressionRate));
Assert.Equal(4, GetOffset(in s, in s.Reserved));
}
+
+ [Fact]
+ public static void CacheStorageInfo_Layout()
+ {
+ var s = new CacheStorageInfo();
+
+ Assert.Equal(0x20, Unsafe.SizeOf());
+
+ Assert.Equal(0, GetOffset(in s, in s.Index));
+ Assert.Equal(4, GetOffset(in s, in s.Reserved));
+ }
}
\ No newline at end of file