Fixup ApplicationSaveDataManagement and update to 13.1.0

This commit is contained in:
Alex Barney 2022-01-24 15:02:32 -07:00
parent dea3b3a8b0
commit 0ba0a9ad9c
15 changed files with 958 additions and 531 deletions

View file

@ -9,7 +9,7 @@ namespace LibHac.Account;
[StructLayout(LayoutKind.Sequential, Size = 0x10)] [StructLayout(LayoutKind.Sequential, Size = 0x10)]
public struct Uid : IEquatable<Uid>, IComparable<Uid>, IComparable public struct Uid : IEquatable<Uid>, IComparable<Uid>, IComparable
{ {
public static Uid Zero => default; public static Uid InvalidUid => default;
public readonly Id128 Id; public readonly Id128 Id;
@ -55,4 +55,4 @@ public struct Uid : IEquatable<Uid>, IComparable<Uid>, IComparable
public static bool operator >(Uid left, Uid right) => left.CompareTo(right) > 0; public static bool operator >(Uid left, Uid right) => left.CompareTo(right) > 0;
public static bool operator <=(Uid left, Uid right) => left.CompareTo(right) <= 0; public static bool operator <=(Uid left, Uid right) => left.CompareTo(right) <= 0;
public static bool operator >=(Uid left, Uid right) => left.CompareTo(right) >= 0; public static bool operator >=(Uid left, Uid right) => left.CompareTo(right) >= 0;
} }

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using InlineIL;
using static InlineIL.IL.Emit; using static InlineIL.IL.Emit;
namespace LibHac.Common; namespace LibHac.Common;
@ -11,7 +12,7 @@ public static class UniqueRefExtensions
{ {
Ldarg(nameof(value)); Ldarg(nameof(value));
Ret(); Ret();
throw InlineIL.IL.Unreachable(); throw IL.Unreachable();
} }
} }
@ -20,7 +21,17 @@ public struct UniqueRef<T> : IDisposable where T : class, IDisposable
{ {
private T _value; private T _value;
public readonly T Get => _value; public readonly ref T Get
{
get
{
Ldarg_0();
Ldflda(new FieldRef(typeof(UniqueRef<T>), nameof(_value)));
Ret();
throw IL.Unreachable();
}
}
public readonly bool HasValue => Get is not null; public readonly bool HasValue => Get is not null;
public UniqueRef(T value) public UniqueRef(T value)
@ -87,4 +98,4 @@ public struct UniqueRef<T> : IDisposable where T : class, IDisposable
return oldValue; return oldValue;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -5,8 +5,8 @@ namespace LibHac.Fs;
public static class SaveData public static class SaveData
{ {
public static readonly ulong SaveIndexerId = 0x8000000000000000; public static readonly ulong SaveIndexerId = 0x8000000000000000;
public static ProgramId InvalidProgramId => ProgramId.InvalidId; public static ProgramId InvalidProgramId => default;
public static ProgramId AutoResolveCallerProgramId => new ProgramId(ulong.MaxValue - 1); public static ProgramId AutoResolveCallerProgramId => new ProgramId(ulong.MaxValue - 1);
public static UserId InvalidUserId => UserId.InvalidId; public static UserId InvalidUserId => default;
public static ulong InvalidSystemSaveDataId => 0; public static ulong InvalidSystemSaveDataId => 0;
} }

View file

@ -17,30 +17,10 @@ public struct SaveDataAttribute : IEquatable<SaveDataAttribute>, IComparable<Sav
public ushort Index; public ushort Index;
public Array24<byte> Reserved; public Array24<byte> Reserved;
public SaveDataAttribute(ProgramId programId, SaveDataType type, UserId userId, ulong saveDataId) : this(
programId, type, userId, saveDataId, 0, SaveDataRank.Primary)
{ }
public SaveDataAttribute(ProgramId programId, SaveDataType type, UserId userId, ulong saveDataId,
ushort index) : this(programId, type, userId, saveDataId, index, SaveDataRank.Primary)
{ }
public SaveDataAttribute(ProgramId programId, SaveDataType type, UserId userId, ulong saveDataId, ushort index,
SaveDataRank rank)
{
ProgramId = programId;
Type = type;
UserId = userId;
StaticSaveDataId = saveDataId;
Index = index;
Rank = rank;
Reserved = new Array24<byte>();
}
public static Result Make(out SaveDataAttribute attribute, ProgramId programId, SaveDataType type, public static Result Make(out SaveDataAttribute attribute, ProgramId programId, SaveDataType type,
UserId userId, ulong staticSaveDataId) UserId userId, ulong staticSaveDataId)
{ {
return Make(out attribute, programId, type, userId, staticSaveDataId, 0, SaveDataRank.Primary); return Make(out attribute, programId, type, userId, staticSaveDataId, index: 0, SaveDataRank.Primary);
} }
public static Result Make(out SaveDataAttribute attribute, ProgramId programId, SaveDataType type, public static Result Make(out SaveDataAttribute attribute, ProgramId programId, SaveDataType type,
@ -154,36 +134,6 @@ public struct SaveDataFilter
public SaveDataAttribute Attribute; public SaveDataAttribute Attribute;
public void SetProgramId(ProgramId value)
{
FilterByProgramId = true;
Attribute.ProgramId = value;
}
public void SetSaveDataType(SaveDataType value)
{
FilterBySaveDataType = true;
Attribute.Type = value;
}
public void SetUserId(UserId value)
{
FilterByUserId = true;
Attribute.UserId = value;
}
public void SetSaveDataId(ulong value)
{
FilterBySaveDataId = true;
Attribute.StaticSaveDataId = value;
}
public void SetIndex(ushort value)
{
FilterByIndex = true;
Attribute.Index = value;
}
public static Result Make(out SaveDataFilter filter, Optional<ulong> programId, Optional<SaveDataType> saveType, public static Result Make(out SaveDataFilter filter, Optional<ulong> programId, Optional<SaveDataType> saveType,
Optional<UserId> userId, Optional<ulong> saveDataId, Optional<ushort> index) Optional<UserId> userId, Optional<ulong> saveDataId, Optional<ushort> index)
{ {

View file

@ -5,7 +5,9 @@ using LibHac.Fs.Fsa;
using LibHac.Fs.Impl; using LibHac.Fs.Impl;
using LibHac.FsSrv.Sf; using LibHac.FsSrv.Sf;
using LibHac.Os; using LibHac.Os;
using static LibHac.Fs.Impl.AccessLogStrings; using static LibHac.Fs.Impl.AccessLogStrings;
using static LibHac.Fs.SaveData;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem; using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem; using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
@ -58,7 +60,7 @@ public static class BcatSaveData
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Bcat, rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Bcat,
Fs.SaveData.InvalidUserId, 0); InvalidUserId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
using var fileSystem = new SharedRef<IFileSystemSf>(); using var fileSystem = new SharedRef<IFileSystemSf>();

View file

@ -6,7 +6,9 @@ using LibHac.Fs.Impl;
using LibHac.FsSrv.Sf; using LibHac.FsSrv.Sf;
using LibHac.Ncm; using LibHac.Ncm;
using LibHac.Os; using LibHac.Os;
using static LibHac.Fs.Impl.AccessLogStrings; using static LibHac.Fs.Impl.AccessLogStrings;
using static LibHac.Fs.SaveData;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem; using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem; using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
@ -48,7 +50,8 @@ public static class SaveData
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, programId, type, userId, 0, index); rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, programId, type, userId, InvalidSystemSaveDataId,
index);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
using var fileSystem = new SharedRef<IFileSystemSf>(); using var fileSystem = new SharedRef<IFileSystemSf>();
@ -86,7 +89,7 @@ public static class SaveData
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, ProgramId.InvalidId, SaveDataType.Account, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, ProgramId.InvalidId, SaveDataType.Account,
UserId.InvalidId, 0); InvalidUserId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, SaveDataSizeForDebug, rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, SaveDataSizeForDebug,
@ -127,7 +130,7 @@ public static class SaveData
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application)) if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
{ {
Tick start = fs.Hos.Os.GetSystemTick(); Tick start = fs.Hos.Os.GetSystemTick();
rc = MountSaveData(fs.Impl, mountName, UserId.InvalidId); rc = MountSaveData(fs.Impl, mountName, InvalidUserId);
Tick end = fs.Hos.Os.GetSystemTick(); Tick end = fs.Hos.Os.GetSystemTick();
var sb = new U8StringBuilder(logBuffer, true); var sb = new U8StringBuilder(logBuffer, true);
@ -138,7 +141,7 @@ public static class SaveData
} }
else else
{ {
rc = MountSaveData(fs.Impl, mountName, UserId.InvalidId); rc = MountSaveData(fs.Impl, mountName, InvalidUserId);
} }
fs.Impl.AbortIfNeeded(rc); fs.Impl.AbortIfNeeded(rc);
@ -238,7 +241,8 @@ public static class SaveData
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, type, UserId.InvalidId, 0); Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, type, userId,
InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc.Miss(); if (rc.IsFailure()) return rc.Miss();
using var fileSystem = new SharedRef<IFileSystemSf>(); using var fileSystem = new SharedRef<IFileSystemSf>();
@ -267,8 +271,8 @@ public static class SaveData
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application)) if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
{ {
Tick start = fs.Hos.Os.GetSystemTick(); Tick start = fs.Hos.Os.GetSystemTick();
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.Temporary, Fs.SaveData.InvalidProgramId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.Temporary, InvalidProgramId, InvalidUserId,
Fs.SaveData.InvalidUserId, SaveDataType.Temporary, openReadOnly: false, index: 0); SaveDataType.Temporary, openReadOnly: false, index: 0);
Tick end = fs.Hos.Os.GetSystemTick(); Tick end = fs.Hos.Os.GetSystemTick();
var sb = new U8StringBuilder(logBuffer, true); var sb = new U8StringBuilder(logBuffer, true);
@ -278,8 +282,8 @@ public static class SaveData
} }
else else
{ {
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.Temporary, Fs.SaveData.InvalidProgramId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.Temporary, InvalidProgramId, InvalidUserId,
Fs.SaveData.InvalidUserId, SaveDataType.Temporary, openReadOnly: false, index: 0); SaveDataType.Temporary, openReadOnly: false, index: 0);
} }
fs.Impl.AbortIfNeeded(rc); fs.Impl.AbortIfNeeded(rc);
@ -299,8 +303,8 @@ public static class SaveData
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application)) if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
{ {
Tick start = fs.Hos.Os.GetSystemTick(); Tick start = fs.Hos.Os.GetSystemTick();
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, Fs.SaveData.InvalidProgramId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, InvalidProgramId,
Fs.SaveData.InvalidUserId, SaveDataType.Cache, openReadOnly: false, index: 0); InvalidUserId, SaveDataType.Cache, openReadOnly: false, index: 0);
Tick end = fs.Hos.Os.GetSystemTick(); Tick end = fs.Hos.Os.GetSystemTick();
var sb = new U8StringBuilder(logBuffer, true); var sb = new U8StringBuilder(logBuffer, true);
@ -310,8 +314,8 @@ public static class SaveData
} }
else else
{ {
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, Fs.SaveData.InvalidProgramId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, InvalidProgramId,
Fs.SaveData.InvalidUserId, SaveDataType.Cache, openReadOnly: false, index: 0); InvalidUserId, SaveDataType.Cache, openReadOnly: false, index: 0);
} }
fs.Impl.AbortIfNeeded(rc); fs.Impl.AbortIfNeeded(rc);
@ -332,8 +336,8 @@ public static class SaveData
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application)) if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.Application))
{ {
Tick start = fs.Hos.Os.GetSystemTick(); Tick start = fs.Hos.Os.GetSystemTick();
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, Fs.SaveData.InvalidProgramId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, InvalidProgramId,
Fs.SaveData.InvalidUserId, SaveDataType.Cache, openReadOnly: false, (ushort)index); InvalidUserId, SaveDataType.Cache, openReadOnly: false, (ushort)index);
Tick end = fs.Hos.Os.GetSystemTick(); Tick end = fs.Hos.Os.GetSystemTick();
var sb = new U8StringBuilder(logBuffer, true); var sb = new U8StringBuilder(logBuffer, true);
@ -344,8 +348,8 @@ public static class SaveData
} }
else else
{ {
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, Fs.SaveData.InvalidProgramId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, InvalidProgramId,
Fs.SaveData.InvalidUserId, SaveDataType.Cache, openReadOnly: false, (ushort)index); InvalidUserId, SaveDataType.Cache, openReadOnly: false, (ushort)index);
} }
fs.Impl.AbortIfNeeded(rc); fs.Impl.AbortIfNeeded(rc);
@ -366,7 +370,7 @@ public static class SaveData
{ {
Tick start = fs.Hos.Os.GetSystemTick(); Tick start = fs.Hos.Os.GetSystemTick();
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, applicationId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, applicationId,
Fs.SaveData.InvalidUserId, SaveDataType.Cache, openReadOnly: false, index: 0); InvalidUserId, SaveDataType.Cache, openReadOnly: false, index: 0);
Tick end = fs.Hos.Os.GetSystemTick(); Tick end = fs.Hos.Os.GetSystemTick();
var sb = new U8StringBuilder(logBuffer, true); var sb = new U8StringBuilder(logBuffer, true);
@ -378,7 +382,7 @@ public static class SaveData
else else
{ {
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, applicationId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, applicationId,
Fs.SaveData.InvalidUserId, SaveDataType.Cache, openReadOnly: false, index: 0); InvalidUserId, SaveDataType.Cache, openReadOnly: false, index: 0);
} }
fs.Impl.AbortIfNeeded(rc); fs.Impl.AbortIfNeeded(rc);
@ -400,7 +404,7 @@ public static class SaveData
{ {
Tick start = fs.Hos.Os.GetSystemTick(); Tick start = fs.Hos.Os.GetSystemTick();
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, applicationId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, applicationId,
Fs.SaveData.InvalidUserId, SaveDataType.Cache, openReadOnly: false, (ushort)index); InvalidUserId, SaveDataType.Cache, openReadOnly: false, (ushort)index);
Tick end = fs.Hos.Os.GetSystemTick(); Tick end = fs.Hos.Os.GetSystemTick();
var sb = new U8StringBuilder(logBuffer, true); var sb = new U8StringBuilder(logBuffer, true);
@ -413,7 +417,7 @@ public static class SaveData
else else
{ {
rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, applicationId, rc = MountSaveDataImpl(fs.Impl, mountName, SaveDataSpaceId.User, applicationId,
Fs.SaveData.InvalidUserId, SaveDataType.Cache, openReadOnly: false, (ushort)index); InvalidUserId, SaveDataType.Cache, openReadOnly: false, (ushort)index);
} }
fs.Impl.AbortIfNeeded(rc); fs.Impl.AbortIfNeeded(rc);

View file

@ -12,7 +12,9 @@ using LibHac.Ncm;
using LibHac.Os; using LibHac.Os;
using LibHac.Sf; using LibHac.Sf;
using LibHac.Time; using LibHac.Time;
using static LibHac.Fs.Impl.AccessLogStrings; using static LibHac.Fs.Impl.AccessLogStrings;
using static LibHac.Fs.SaveData;
namespace LibHac.Fs namespace LibHac.Fs
{ {
@ -297,7 +299,7 @@ namespace LibHac.Fs.Shim
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account,
userId, staticSaveDataId: 0); userId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags, rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
@ -319,7 +321,7 @@ namespace LibHac.Fs.Shim
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Bcat, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Bcat,
Fs.SaveData.InvalidUserId, staticSaveDataId: 0); InvalidUserId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size,
@ -345,7 +347,7 @@ namespace LibHac.Fs.Shim
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Device, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Device,
Fs.SaveData.InvalidUserId, staticSaveDataId: 0); InvalidUserId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags, rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
@ -367,7 +369,7 @@ namespace LibHac.Fs.Shim
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Cache, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Cache,
Fs.SaveData.InvalidUserId, staticSaveDataId: 0, index); InvalidUserId, InvalidSystemSaveDataId, index);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags, rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
@ -492,7 +494,7 @@ namespace LibHac.Fs.Shim
{ {
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, InvalidProgramId,
SaveDataType.System, userId, saveDataId); SaveDataType.System, userId, saveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -529,7 +531,7 @@ namespace LibHac.Fs.Shim
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value), Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value),
SaveDataType.Device, Fs.SaveData.InvalidUserId, staticSaveDataId: 0); SaveDataType.Device, InvalidUserId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId.User, in attribute); return fileSystemProxy.Get.DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId.User, in attribute);
@ -587,7 +589,7 @@ namespace LibHac.Fs.Shim
} }
public static Result ReadSaveDataIteratorSaveDataInfo(this FileSystemClientImpl fs, out long readCount, public static Result ReadSaveDataIteratorSaveDataInfo(this FileSystemClientImpl fs, out long readCount,
Span<SaveDataInfo> buffer, in SaveDataIterator iterator) Span<SaveDataInfo> buffer, ref SaveDataIterator iterator)
{ {
Result rc = iterator.ReadSaveDataInfo(out readCount, buffer); Result rc = iterator.ReadSaveDataInfo(out readCount, buffer);
if (rc.IsFailure()) return rc.Miss(); if (rc.IsFailure()) return rc.Miss();
@ -743,7 +745,7 @@ namespace LibHac.Fs.Shim
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Account,
userId, staticSaveDataId: 0); userId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags, rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize, ownerId, flags,
@ -820,7 +822,7 @@ namespace LibHac.Fs.Shim
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Temporary, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, applicationId, SaveDataType.Temporary,
Fs.SaveData.InvalidUserId, staticSaveDataId: 0); InvalidUserId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize: 0, ownerId, flags, rc = SaveDataCreationInfo.Make(out SaveDataCreationInfo creationInfo, size, journalSize: 0, ownerId, flags,
@ -946,7 +948,7 @@ namespace LibHac.Fs.Shim
{ {
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, InvalidProgramId,
SaveDataType.System, userId, saveDataId); SaveDataType.System, userId, saveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -961,8 +963,7 @@ namespace LibHac.Fs.Shim
public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId, public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId,
ulong ownerId, long size, long journalSize, SaveDataFlags flags) ulong ownerId, long size, long journalSize, SaveDataFlags flags)
{ {
return CreateSystemSaveData(fs, SaveDataSpaceId.System, saveDataId, userId, ownerId, size, journalSize, return CreateSystemSaveData(fs, SaveDataSpaceId.System, saveDataId, userId, ownerId, size, journalSize, flags);
flags);
} }
public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId, long size, public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId, long size,
@ -974,20 +975,19 @@ namespace LibHac.Fs.Shim
public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, ulong ownerId, long size, public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, ulong ownerId, long size,
long journalSize, SaveDataFlags flags) long journalSize, SaveDataFlags flags)
{ {
return CreateSystemSaveData(fs, saveDataId, Fs.SaveData.InvalidUserId, ownerId, size, journalSize, flags); return CreateSystemSaveData(fs, saveDataId, InvalidUserId, ownerId, size, journalSize, flags);
} }
public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, long size, public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, long size,
long journalSize, SaveDataFlags flags) long journalSize, SaveDataFlags flags)
{ {
return CreateSystemSaveData(fs, saveDataId, Fs.SaveData.InvalidUserId, ownerId: 0, size, journalSize, flags); return CreateSystemSaveData(fs, saveDataId, InvalidUserId, ownerId: 0, size, journalSize, flags);
} }
public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId, public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
ulong ownerId, long size, long journalSize, SaveDataFlags flags) ulong ownerId, long size, long journalSize, SaveDataFlags flags)
{ {
return CreateSystemSaveData(fs, spaceId, saveDataId, Fs.SaveData.InvalidUserId, ownerId, size, journalSize, return CreateSystemSaveData(fs, spaceId, saveDataId, InvalidUserId, ownerId, size, journalSize, flags);
flags);
} }
public static Result ExtendSaveData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId, ulong saveDataId, public static Result ExtendSaveData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId, ulong saveDataId,
@ -1295,7 +1295,7 @@ namespace LibHac.Fs.Shim
{ {
UnsafeHelpers.SkipParamInit(out flags); UnsafeHelpers.SkipParamInit(out flags);
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, InvalidProgramId,
SaveDataType.System, userId, saveDataId); SaveDataType.System, userId, saveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -1392,7 +1392,7 @@ namespace LibHac.Fs.Shim
SaveDataExtraData extraData = default; SaveDataExtraData extraData = default;
extraData.Flags = flags; extraData.Flags = flags;
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId, Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, InvalidProgramId,
SaveDataType.System, userId, saveDataId); SaveDataType.System, userId, saveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -2186,8 +2186,8 @@ namespace LibHac.Fs.Shim
Result rc = fileSystem.GetSaveDataAttribute(out SaveDataAttribute attribute); Result rc = fileSystem.GetSaveDataAttribute(out SaveDataAttribute attribute);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
if (attribute.ProgramId == Fs.SaveData.InvalidProgramId) if (attribute.ProgramId == InvalidProgramId)
attribute.ProgramId = Fs.SaveData.AutoResolveCallerProgramId; attribute.ProgramId = AutoResolveCallerProgramId;
SaveDataExtraData extraDataMask = default; SaveDataExtraData extraDataMask = default;
extraDataMask.Flags = SaveDataFlags.Restore; extraDataMask.Flags = SaveDataFlags.Restore;
@ -2239,7 +2239,7 @@ namespace LibHac.Fs.Shim
extraDataMask.JournalSize = unchecked((long)0xFFFFFFFFFFFFFFFF); extraDataMask.JournalSize = unchecked((long)0xFFFFFFFFFFFFFFFF);
Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value), Result rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, new ProgramId(applicationId.Value),
SaveDataType.Device, Fs.SaveData.InvalidUserId, staticSaveDataId: 0); SaveDataType.Device, InvalidUserId, InvalidSystemSaveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId.User, rc = fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId.User,

View file

@ -178,7 +178,7 @@ namespace LibHac.Fs
public Result OpenSaveDataImporter(ref UniqueRef<ISaveDataDivisionImporter> outImporter, public Result OpenSaveDataImporter(ref UniqueRef<ISaveDataDivisionImporter> outImporter,
in InitialDataVersion2 initialData, SaveDataSpaceId spaceId, bool useSwap) in InitialDataVersion2 initialData, SaveDataSpaceId spaceId, bool useSwap)
{ {
return OpenSaveDataImporterImpl(ref outImporter, in initialData, UserId.InvalidId, spaceId, useSwap); return OpenSaveDataImporterImpl(ref outImporter, in initialData, InvalidUserId, spaceId, useSwap);
} }
public Result OpenSaveDataImporterByContext(ref UniqueRef<ISaveDataDivisionImporter> outImporter, public Result OpenSaveDataImporterByContext(ref UniqueRef<ISaveDataDivisionImporter> outImporter,
@ -354,7 +354,7 @@ namespace LibHac.Fs.Shim
Unsafe.SkipInit(out SaveDataInfo info); Unsafe.SkipInit(out SaveDataInfo info);
rc = fs.Impl.ReadSaveDataIteratorSaveDataInfo(out long count, SpanHelpers.AsSpan(ref info), rc = fs.Impl.ReadSaveDataIteratorSaveDataInfo(out long count, SpanHelpers.AsSpan(ref info),
iterator.Get); ref iterator.Get);
fs.Impl.LogResultErrorMessage(rc); fs.Impl.LogResultErrorMessage(rc);
if (rc.IsFailure()) return rc.Miss(); if (rc.IsFailure()) return rc.Miss();

View file

@ -5,7 +5,9 @@ using LibHac.Fs.Fsa;
using LibHac.Fs.Impl; using LibHac.Fs.Impl;
using LibHac.FsSrv.Sf; using LibHac.FsSrv.Sf;
using LibHac.Os; using LibHac.Os;
using static LibHac.Fs.Impl.AccessLogStrings; using static LibHac.Fs.Impl.AccessLogStrings;
using static LibHac.Fs.SaveData;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem; using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem; using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
@ -20,7 +22,7 @@ public static class SystemSaveData
{ {
public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName, ulong saveDataId) public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName, ulong saveDataId)
{ {
return fs.MountSystemSaveData(mountName, saveDataId, Fs.SaveData.InvalidUserId); return fs.MountSystemSaveData(mountName, saveDataId, InvalidUserId);
} }
public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName, ulong saveDataId, public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName, ulong saveDataId,
@ -32,7 +34,7 @@ public static class SystemSaveData
public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName, SaveDataSpaceId spaceId, public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName, SaveDataSpaceId spaceId,
ulong saveDataId) ulong saveDataId)
{ {
return fs.MountSystemSaveData(mountName, spaceId, saveDataId, Fs.SaveData.InvalidUserId); return fs.MountSystemSaveData(mountName, spaceId, saveDataId, InvalidUserId);
} }
public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName, public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName,
@ -77,7 +79,7 @@ public static class SystemSaveData
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, Fs.SaveData.InvalidProgramId, rc = SaveDataAttribute.Make(out SaveDataAttribute attribute, InvalidProgramId,
SaveDataType.System, userId, saveDataId); SaveDataType.System, userId, saveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;

View file

@ -10,13 +10,15 @@ using LibHac.Kvdb;
using LibHac.Ncm; using LibHac.Ncm;
using LibHac.Sf; using LibHac.Sf;
using LibHac.Util; using LibHac.Util;
using static LibHac.Fs.SaveData;
using static LibHac.Fs.StringTraits;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem; using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem; using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
using IFile = LibHac.Fs.Fsa.IFile; using IFile = LibHac.Fs.Fsa.IFile;
using IFileSf = LibHac.FsSrv.Sf.IFile; using IFileSf = LibHac.FsSrv.Sf.IFile;
using Path = LibHac.Fs.Path; using Path = LibHac.Fs.Path;
using SaveData = LibHac.Fs.SaveData;
using static LibHac.Fs.StringTraits;
using Utility = LibHac.FsSystem.Utility; using Utility = LibHac.FsSystem.Utility;
namespace LibHac.FsSrv; namespace LibHac.FsSrv;
@ -146,7 +148,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
return ResultFs.PermissionDenied.Log(); return ResultFs.PermissionDenied.Log();
} }
} }
else if (attribute.Type == SaveDataType.Account && attribute.UserId == UserId.InvalidId) else if (attribute.Type == SaveDataType.Account && attribute.UserId == InvalidUserId)
{ {
bool canAccess = bool canAccess =
accessControl.CanCall(OperationType.CreateSaveData) || accessControl.CanCall(OperationType.CreateSaveData) ||
@ -195,7 +197,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
} }
else if (attribute.Type == SaveDataType.Account) else if (attribute.Type == SaveDataType.Account)
{ {
bool canAccess = attribute.UserId != UserId.InvalidId || bool canAccess = attribute.UserId != InvalidUserId ||
accessControl.CanCall(OperationType.DebugSaveData); accessControl.CanCall(OperationType.DebugSaveData);
if (!canAccess) if (!canAccess)
@ -478,7 +480,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
private Result DeleteSaveDataFileSystemBySaveDataSpaceIdCore(SaveDataSpaceId spaceId, ulong saveDataId) private Result DeleteSaveDataFileSystemBySaveDataSpaceIdCore(SaveDataSpaceId spaceId, ulong saveDataId)
{ {
if (saveDataId != SaveData.SaveIndexerId) if (saveDataId != SaveIndexerId)
{ {
using var accessor = new UniqueRef<SaveDataIndexerAccessor>(); using var accessor = new UniqueRef<SaveDataIndexerAccessor>();
Result rc = OpenSaveDataIndexerAccessor(ref accessor.Ref(), spaceId); Result rc = OpenSaveDataIndexerAccessor(ref accessor.Ref(), spaceId);
@ -515,7 +517,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
SaveDataSpaceId actualSpaceId; SaveDataSpaceId actualSpaceId;
// Only the FS process may delete the save indexer's save data. // Only the FS process may delete the save indexer's save data.
if (saveDataId == SaveData.SaveIndexerId) if (saveDataId == SaveIndexerId)
{ {
if (!_serviceImpl.FsServer.IsCurrentProcess(_processId)) if (!_serviceImpl.FsServer.IsCurrentProcess(_processId))
return ResultFs.PermissionDenied.Log(); return ResultFs.PermissionDenied.Log();
@ -565,7 +567,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
// Remove the save data from the indexer. // Remove the save data from the indexer.
// The indexer doesn't track itself, so skip if deleting its save data. // The indexer doesn't track itself, so skip if deleting its save data.
if (saveDataId != SaveData.SaveIndexerId) if (saveDataId != SaveIndexerId)
{ {
rc = accessor.Get.GetInterface().Delete(saveDataId); rc = accessor.Get.GetInterface().Delete(saveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -656,7 +658,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
// ReSharper disable once UnusedParameter.Global // ReSharper disable once UnusedParameter.Global
public Result UpdateSaveDataMacForDebug(SaveDataSpaceId spaceId, ulong saveDataId) public Result UpdateSaveDataMacForDebug(SaveDataSpaceId spaceId, ulong saveDataId)
{ {
if (saveDataId == SaveData.SaveIndexerId) if (saveDataId == SaveIndexerId)
return ResultFs.InvalidArgument.Log(); return ResultFs.InvalidArgument.Log();
return ResultFs.NotImplemented.Log(); return ResultFs.NotImplemented.Log();
@ -697,10 +699,10 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
try try
{ {
// Add the new save data to the save indexer // Add the new save data to the save indexer
if (attribute.StaticSaveDataId == SaveData.SaveIndexerId) if (attribute.StaticSaveDataId == SaveIndexerId)
{ {
// The save indexer doesn't index itself // The save indexer doesn't index itself
saveDataId = SaveData.SaveIndexerId; saveDataId = SaveIndexerId;
rc = _serviceImpl.DoesSaveDataEntityExist(out bool saveExists, creationInfo.SpaceId, saveDataId); rc = _serviceImpl.DoesSaveDataEntityExist(out bool saveExists, creationInfo.SpaceId, saveDataId);
if (rc.IsSuccess() && saveExists) if (rc.IsSuccess() && saveExists)
@ -720,7 +722,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
SaveDataAttribute indexerKey = attribute; SaveDataAttribute indexerKey = attribute;
// Add the new value to the indexer // Add the new value to the indexer
if (attribute.StaticSaveDataId != 0 && attribute.UserId == UserId.InvalidId) if (attribute.StaticSaveDataId != 0 && attribute.UserId == InvalidUserId)
{ {
// If a static save data ID is specified that ID is always used // If a static save data ID is specified that ID is always used
saveDataId = attribute.StaticSaveDataId; saveDataId = attribute.StaticSaveDataId;
@ -823,7 +825,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
} }
// The indexer's save data isn't tracked, so we don't need to update its state. // The indexer's save data isn't tracked, so we don't need to update its state.
if (attribute.StaticSaveDataId != SaveData.SaveIndexerId) if (attribute.StaticSaveDataId != SaveIndexerId)
{ {
// Mark the save data as being successfully created // Mark the save data as being successfully created
rc = accessor.Get.GetInterface().SetState(saveDataId, SaveDataState.Normal); rc = accessor.Get.GetInterface().SetState(saveDataId, SaveDataState.Normal);
@ -843,7 +845,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
{ {
DeleteSaveDataFileSystemCore(creationInfo.SpaceId, saveDataId, false).IgnoreResult(); DeleteSaveDataFileSystemCore(creationInfo.SpaceId, saveDataId, false).IgnoreResult();
if (accessorInitialized && saveDataId != SaveData.SaveIndexerId) if (accessorInitialized && saveDataId != SaveIndexerId)
{ {
rc = accessor.Get.GetInterface().GetValue(out SaveDataIndexerValue value, saveDataId); rc = accessor.Get.GetInterface().GetValue(out SaveDataIndexerValue value, saveDataId);
@ -922,7 +924,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
rc = SaveDataAccessibilityChecker.CheckCreate(in attribute, in creationInfo, programInfo, programId); rc = SaveDataAccessibilityChecker.CheckCreate(in attribute, in creationInfo, programInfo, programId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
if (tempAttribute.Type == SaveDataType.Account && tempAttribute.UserId == UserId.InvalidId) if (tempAttribute.Type == SaveDataType.Account && tempAttribute.UserId == InvalidUserId)
{ {
if (tempAttribute.ProgramId == ProgramId.InvalidId) if (tempAttribute.ProgramId == ProgramId.InvalidId)
{ {
@ -995,7 +997,8 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
using var accessor = new UniqueRef<SaveDataIndexerAccessor>(); using var accessor = new UniqueRef<SaveDataIndexerAccessor>();
ulong tempSaveDataId; ulong tempSaveDataId;
bool isStaticSaveDataId = attribute.StaticSaveDataId != 0 && attribute.UserId == UserId.InvalidId; bool isStaticSaveDataId =
attribute.StaticSaveDataId != InvalidSystemSaveDataId && attribute.UserId == InvalidUserId;
// Get the ID of the save data // Get the ID of the save data
if (isStaticSaveDataId) if (isStaticSaveDataId)
@ -1052,7 +1055,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
Result RemoveSaveIndexerEntry() Result RemoveSaveIndexerEntry()
{ {
if (tempSaveDataId == SaveData.SaveIndexerId) if (tempSaveDataId == SaveIndexerId)
return Result.Success; return Result.Success;
if (isStaticSaveDataId) if (isStaticSaveDataId)
@ -1379,7 +1382,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
SaveDataAttribute tempAttribute = attribute; SaveDataAttribute tempAttribute = attribute;
if (tempAttribute.ProgramId == SaveData.AutoResolveCallerProgramId) if (tempAttribute.ProgramId == AutoResolveCallerProgramId)
{ {
tempAttribute.ProgramId = ResolveDefaultSaveDataReferenceProgramId(programInfo.ProgramId); tempAttribute.ProgramId = ResolveDefaultSaveDataReferenceProgramId(programInfo.ProgramId);
} }
@ -1428,7 +1431,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
SaveDataAttribute tempAttribute = attribute; SaveDataAttribute tempAttribute = attribute;
if (tempAttribute.ProgramId == SaveData.AutoResolveCallerProgramId) if (tempAttribute.ProgramId == AutoResolveCallerProgramId)
{ {
tempAttribute.ProgramId = ResolveDefaultSaveDataReferenceProgramId(programInfo.ProgramId); tempAttribute.ProgramId = ResolveDefaultSaveDataReferenceProgramId(programInfo.ProgramId);
} }
@ -1505,7 +1508,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
SaveDataAttribute tempAttribute = attribute; SaveDataAttribute tempAttribute = attribute;
if (tempAttribute.ProgramId == SaveData.AutoResolveCallerProgramId) if (tempAttribute.ProgramId == AutoResolveCallerProgramId)
{ {
tempAttribute.ProgramId = ResolveDefaultSaveDataReferenceProgramId(programInfo.ProgramId); tempAttribute.ProgramId = ResolveDefaultSaveDataReferenceProgramId(programInfo.ProgramId);
} }
@ -2042,7 +2045,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
{ {
Index = 0, Index = 0,
Type = SaveDataType.System, Type = SaveDataType.System,
UserId = UserId.InvalidId, UserId = InvalidUserId,
StaticSaveDataId = MultiCommitManager.SaveDataId, StaticSaveDataId = MultiCommitManager.SaveDataId,
ProgramId = new ProgramId(MultiCommitManager.ProgramId) ProgramId = new ProgramId(MultiCommitManager.ProgramId)
}; };
@ -2067,7 +2070,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave
{ {
Index = saveInfo.Index, Index = saveInfo.Index,
Type = saveInfo.Type, Type = saveInfo.Type,
UserId = UserId.InvalidId, UserId = InvalidUserId,
StaticSaveDataId = saveInfo.StaticSaveDataId, StaticSaveDataId = saveInfo.StaticSaveDataId,
ProgramId = saveInfo.ProgramId ProgramId = saveInfo.ProgramId
}; };

View file

@ -12,7 +12,8 @@ using LibHac.Kvdb;
using LibHac.Os; using LibHac.Os;
using LibHac.Sf; using LibHac.Sf;
using LibHac.Util; using LibHac.Util;
using SaveData = LibHac.Fs.SaveData;
using static LibHac.Fs.SaveData;
namespace LibHac.FsSrv; namespace LibHac.FsSrv;
@ -451,8 +452,8 @@ public class SaveDataIndexer : ISaveDataIndexer
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
Assert.SdkRequires(_isLoaded); Assert.SdkRequires(_isLoaded);
Assert.SdkRequires(key.StaticSaveDataId != SaveData.InvalidSystemSaveDataId); Assert.SdkRequires(key.StaticSaveDataId != InvalidSystemSaveDataId);
Assert.SdkRequires(key.UserId == SaveData.InvalidUserId); Assert.SdkRequires(key.UserId == InvalidUserId);
// Iterate through all existing values to check if the save ID is already in use. // Iterate through all existing values to check if the save ID is already in use.
FlatMapKeyValueStore<SaveDataAttribute>.Iterator iterator = _kvDatabase.GetBeginIterator(); FlatMapKeyValueStore<SaveDataAttribute>.Iterator iterator = _kvDatabase.GetBeginIterator();

View file

@ -5,7 +5,7 @@ using LibHac.Fs.Shim;
using LibHac.Ns; using LibHac.Ns;
using Xunit; using Xunit;
using static LibHac.Fs.ApplicationSaveDataManagement; using static LibHac.Fs.SaveData;
namespace LibHac.Tests.Fs.FileSystemClientTests; namespace LibHac.Tests.Fs.FileSystemClientTests;
@ -19,13 +19,13 @@ public class ApplicationSaveDataManagementTests
var applicationId = new Ncm.ApplicationId(11); var applicationId = new Ncm.ApplicationId(11);
var userId = new Uid(2, 3); var userId = new Uid(2, 3);
var nacp = new ApplicationControlProperty var controlProperty = new ApplicationControlProperty
{ {
UserAccountSaveDataSize = 0x1000, UserAccountSaveDataSize = 0x1000,
UserAccountSaveDataJournalSize = 0x1000 UserAccountSaveDataJournalSize = 0x1000
}; };
Assert.Success(EnsureApplicationSaveData(fs, out _, applicationId, ref nacp, ref userId)); Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId));
using var iterator = new UniqueRef<SaveDataIterator>(); using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User);
@ -47,13 +47,13 @@ public class ApplicationSaveDataManagementTests
var applicationId = new Ncm.ApplicationId(11); var applicationId = new Ncm.ApplicationId(11);
var userId = new Uid(2, 3); var userId = new Uid(2, 3);
var nacp = new ApplicationControlProperty var controlProperty = new ApplicationControlProperty
{ {
DeviceSaveDataSize = 0x1000, DeviceSaveDataSize = 0x1000,
DeviceSaveDataJournalSize = 0x1000 DeviceSaveDataJournalSize = 0x1000
}; };
Assert.Success(EnsureApplicationSaveData(fs, out _, applicationId, ref nacp, ref userId)); Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId));
using var iterator = new UniqueRef<SaveDataIterator>(); using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User);
@ -63,7 +63,7 @@ public class ApplicationSaveDataManagementTests
Assert.Equal(1, entriesRead); Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId); Assert.Equal(applicationId, info[0].ProgramId);
Assert.Equal(UserId.InvalidId, info[0].UserId); Assert.Equal(InvalidUserId, info[0].UserId);
Assert.Equal(SaveDataType.Device, info[0].Type); Assert.Equal(SaveDataType.Device, info[0].Type);
} }
@ -75,12 +75,12 @@ public class ApplicationSaveDataManagementTests
var applicationId = new Ncm.ApplicationId(11); var applicationId = new Ncm.ApplicationId(11);
var userId = new Uid(2, 3); var userId = new Uid(2, 3);
var nacp = new ApplicationControlProperty var controlProperty = new ApplicationControlProperty
{ {
BcatDeliveryCacheStorageSize = 0x1000 BcatDeliveryCacheStorageSize = 0x1000
}; };
Assert.Success(EnsureApplicationSaveData(fs, out _, applicationId, ref nacp, ref userId)); Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId));
using var iterator = new UniqueRef<SaveDataIterator>(); using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User); fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User);
@ -90,7 +90,7 @@ public class ApplicationSaveDataManagementTests
Assert.Equal(1, entriesRead); Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId); Assert.Equal(applicationId, info[0].ProgramId);
Assert.Equal(UserId.InvalidId, info[0].UserId); Assert.Equal(InvalidUserId, info[0].UserId);
Assert.Equal(SaveDataType.Bcat, info[0].Type); Assert.Equal(SaveDataType.Bcat, info[0].Type);
} }
@ -102,12 +102,12 @@ public class ApplicationSaveDataManagementTests
var applicationId = new Ncm.ApplicationId(11); var applicationId = new Ncm.ApplicationId(11);
var userId = new Uid(2, 3); var userId = new Uid(2, 3);
var nacp = new ApplicationControlProperty var controlProperty = new ApplicationControlProperty
{ {
TemporaryStorageSize = 0x1000 TemporaryStorageSize = 0x1000
}; };
Assert.Success(EnsureApplicationSaveData(fs, out _, applicationId, ref nacp, ref userId)); Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId));
using var iterator = new UniqueRef<SaveDataIterator>(); using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.Temporary); fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.Temporary);
@ -117,9 +117,53 @@ public class ApplicationSaveDataManagementTests
Assert.Equal(1, entriesRead); Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId); Assert.Equal(applicationId, info[0].ProgramId);
Assert.Equal(UserId.InvalidId, info[0].UserId); Assert.Equal(InvalidUserId, info[0].UserId);
Assert.Equal(SaveDataType.Temporary, info[0].Type); Assert.Equal(SaveDataType.Temporary, info[0].Type);
} }
[Fact]
public static void EnsureApplicationSaveData_NeedsExtension_IsExtended()
{
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
var applicationId = new Ncm.ApplicationId(11);
var userId = new Uid(2, 3);
var controlProperty = new ApplicationControlProperty
{
UserAccountSaveDataSize = 0x1000,
UserAccountSaveDataJournalSize = 0x1000
};
Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId));
const int newAvailableSize = 1024 * 1024 * 2;
const int newJournalSize = 1024 * 1024;
controlProperty.UserAccountSaveDataSize = newAvailableSize;
controlProperty.UserAccountSaveDataJournalSize = newJournalSize;
Assert.Success(fs.EnsureApplicationSaveData(out _, applicationId, in controlProperty, in userId));
using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User);
var info = new SaveDataInfo[2];
Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info));
Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId);
Assert.Equal(Utility.ConvertAccountUidToFsUserId(userId), info[0].UserId);
Assert.Equal(SaveDataType.Account, info[0].Type);
// ReSharper disable UnusedVariable
Assert.Success(fs.GetSaveDataAvailableSize(out long availableSize, SaveDataSpaceId.User, info[0].SaveDataId));
Assert.Success(fs.GetSaveDataJournalSize(out long journalSize, SaveDataSpaceId.User, info[0].SaveDataId));
// ReSharper restore UnusedVariable
// Todo: Remove once save data extension is implemented
// Assert.Equal(newAvailableSize, availableSize);
// Assert.Equal(newJournalSize, journalSize);
}
[Fact] [Fact]
public static void EnsureApplicationCacheStorage_SdCardAvailable_CreatesCacheStorageOnSd() public static void EnsureApplicationCacheStorage_SdCardAvailable_CreatesCacheStorageOnSd()
@ -128,14 +172,14 @@ public class ApplicationSaveDataManagementTests
var applicationId = new Ncm.ApplicationId(11); var applicationId = new Ncm.ApplicationId(11);
var nacp = new ApplicationControlProperty var controlProperty = new ApplicationControlProperty
{ {
CacheStorageSize = 0x1000, CacheStorageSize = 0x1000,
CacheStorageJournalSize = 0x1000 CacheStorageJournalSize = 0x1000
}; };
Assert.Success(fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia target, applicationId, Assert.Success(fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia target, applicationId,
ref nacp)); in controlProperty));
Assert.Equal(CacheStorageTargetMedia.SdCard, target); Assert.Equal(CacheStorageTargetMedia.SdCard, target);
@ -157,14 +201,14 @@ public class ApplicationSaveDataManagementTests
var applicationId = new Ncm.ApplicationId(11); var applicationId = new Ncm.ApplicationId(11);
var nacp = new ApplicationControlProperty var controlProperty = new ApplicationControlProperty
{ {
CacheStorageSize = 0x1000, CacheStorageSize = 0x1000,
CacheStorageJournalSize = 0x1000 CacheStorageJournalSize = 0x1000
}; };
Assert.Success(fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia target, applicationId, Assert.Success(fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia target, applicationId,
ref nacp)); in controlProperty));
Assert.Equal(CacheStorageTargetMedia.Nand, target); Assert.Equal(CacheStorageTargetMedia.Nand, target);
@ -188,13 +232,14 @@ public class ApplicationSaveDataManagementTests
var applicationId = new Ncm.ApplicationId(11); var applicationId = new Ncm.ApplicationId(11);
var nacp = new ApplicationControlProperty var controlProperty = new ApplicationControlProperty
{ {
CacheStorageSize = 0x1000, CacheStorageSize = 0x1000,
CacheStorageJournalSize = 0x1000 CacheStorageJournalSize = 0x1000
}; };
fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia targetFromCreation, applicationId, ref nacp); fs.EnsureApplicationCacheStorage(out _, out CacheStorageTargetMedia targetFromCreation, applicationId,
in controlProperty);
Assert.Success(fs.GetCacheStorageTargetMedia(out CacheStorageTargetMedia target, applicationId)); Assert.Success(fs.GetCacheStorageTargetMedia(out CacheStorageTargetMedia target, applicationId));
Assert.Equal(targetFromCreation, target); Assert.Equal(targetFromCreation, target);

View file

@ -8,6 +8,8 @@ using LibHac.Ncm;
using LibHac.Time; using LibHac.Time;
using Xunit; using Xunit;
using static LibHac.Fs.SaveData;
namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests; namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests;
public class SaveDataManagement public class SaveDataManagement
@ -322,7 +324,7 @@ public class SaveDataManagement
Assert.Success(client.Fs.RegisterProgramIndexMapInfo(mapInfo)); Assert.Success(client.Fs.RegisterProgramIndexMapInfo(mapInfo));
Assert.Success(subProgramClient.Fs.CreateSaveData(Ncm.ApplicationId.InvalidId, UserId.InvalidId, 0, 0x4000, Assert.Success(subProgramClient.Fs.CreateSaveData(Ncm.ApplicationId.InvalidId, InvalidUserId, 0, 0x4000,
0x4000, SaveDataFlags.None)); 0x4000, SaveDataFlags.None));
// Get the created save data's ID // Get the created save data's ID
@ -497,7 +499,8 @@ public class SaveDataManagement
Assert.Success(fs.CreateSaveData(applicationId, user2Id, 0, 0x4000, 0x4000, SaveDataFlags.None)); Assert.Success(fs.CreateSaveData(applicationId, user2Id, 0, 0x4000, 0x4000, SaveDataFlags.None));
} }
Assert.Success(SaveDataFilter.Make(out SaveDataFilter filter, default, default, user2Id, default, default)); Assert.Success(SaveDataFilter.Make(out SaveDataFilter filter, programId: default, saveType: default, user2Id,
saveDataId: default, index: default));
using var iterator = new UniqueRef<SaveDataIterator>(); using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User, in filter)); Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User, in filter));
@ -651,7 +654,7 @@ public class SaveDataManagement
for (int i = 1; i <= count; i++) for (int i = 1; i <= count; i++)
{ {
var applicationId = new Ncm.ApplicationId((uint)i); var applicationId = new Ncm.ApplicationId((uint)i);
Result rc = fs.CreateSaveData(applicationId, UserId.InvalidId, 0, 0x4000, 0x4000, SaveDataFlags.None); Result rc = fs.CreateSaveData(applicationId, InvalidUserId, 0, 0x4000, 0x4000, SaveDataFlags.None);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
} }
} }
@ -662,7 +665,7 @@ public class SaveDataManagement
for (int i = 1; i <= count; i++) for (int i = 1; i <= count; i++)
{ {
var applicationId = new Ncm.ApplicationId((uint)rng.Next()); var applicationId = new Ncm.ApplicationId((uint)rng.Next());
Result rc = fs.CreateSaveData(applicationId, UserId.InvalidId, 0, 0x4000, 0x4000, SaveDataFlags.None); Result rc = fs.CreateSaveData(applicationId, InvalidUserId, 0, 0x4000, 0x4000, SaveDataFlags.None);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
} }
} }

View file

@ -6,6 +6,8 @@ using LibHac.Fs.Shim;
using LibHac.Tests.Fs.FileSystemClientTests; using LibHac.Tests.Fs.FileSystemClientTests;
using Xunit; using Xunit;
using static LibHac.Fs.SaveData;
namespace LibHac.Tests.Fs.FsaTests; namespace LibHac.Tests.Fs.FsaTests;
public class MultiCommitTests public class MultiCommitTests
@ -25,8 +27,8 @@ public class MultiCommitTests
foreach ((int id, string name) info in saveInfo) foreach ((int id, string name) info in saveInfo)
{ {
var applicationId = new Ncm.ApplicationId((uint)info.id); var applicationId = new Ncm.ApplicationId((uint)info.id);
fs.CreateSaveData(applicationId, UserId.InvalidId, 0, 0x4000, 0x4000, SaveDataFlags.None); fs.CreateSaveData(applicationId, InvalidUserId, 0, 0x4000, 0x4000, SaveDataFlags.None);
fs.MountSaveData(info.name.ToU8Span(), applicationId, UserId.InvalidId); fs.MountSaveData(info.name.ToU8Span(), applicationId, InvalidUserId);
} }
foreach ((int id, string name) info in saveInfo) foreach ((int id, string name) info in saveInfo)
@ -51,7 +53,7 @@ public class MultiCommitTests
foreach ((int id, string name) info in saveInfo) foreach ((int id, string name) info in saveInfo)
{ {
var applicationId = new Ncm.ApplicationId((uint)info.id); var applicationId = new Ncm.ApplicationId((uint)info.id);
fs.MountSaveData(info.name.ToU8Span(), applicationId, UserId.InvalidId); fs.MountSaveData(info.name.ToU8Span(), applicationId, InvalidUserId);
} }
foreach ((int id, string name) info in saveInfo) foreach ((int id, string name) info in saveInfo)
@ -59,4 +61,4 @@ public class MultiCommitTests
Assert.Success(fs.GetEntryType(out _, $"{info.name}:/file{info.id}".ToU8Span())); Assert.Success(fs.GetEntryType(out _, $"{info.name}:/file{info.id}".ToU8Span()));
} }
} }
} }