Add some savedata client functions

This commit is contained in:
Alex Barney 2019-09-27 23:36:43 -05:00
parent 00eb988793
commit 838bb18a09
7 changed files with 274 additions and 29 deletions

View file

@ -0,0 +1,94 @@
using System;
using LibHac.FsService;
namespace LibHac.Fs
{
public partial class FileSystemClient
{
private GlobalAccessLogMode GlobalAccessLogMode { get; set; }
private LocalAccessLogMode LocalAccessLogMode { get; set; }
private bool AccessLogInitialized { get; set; }
private readonly object _accessLogInitLocker = new object();
public Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode)
{
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
return fsProxy.GetGlobalAccessLogMode(out mode);
}
public Result SetGlobalAccessLogMode(GlobalAccessLogMode mode)
{
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
return fsProxy.SetGlobalAccessLogMode(mode);
}
public void SetLocalAccessLogMode(LocalAccessLogMode mode)
{
LocalAccessLogMode = mode;
}
internal bool IsEnabledAccessLog(LocalAccessLogMode mode)
{
if (!LocalAccessLogMode.HasFlag(mode))
{
return false;
}
if (AccessLogInitialized)
{
return GlobalAccessLogMode != GlobalAccessLogMode.None;
}
lock (_accessLogInitLocker)
{
if (!AccessLogInitialized)
{
IFileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
Result rc = fsProxy.GetGlobalAccessLogMode(out GlobalAccessLogMode globalMode);
GlobalAccessLogMode = globalMode;
if (rc.IsFailure())
{
throw new LibHacException("Abort");
}
if (GlobalAccessLogMode != GlobalAccessLogMode.None)
{
InitAccessLog();
}
AccessLogInitialized = true;
}
}
return GlobalAccessLogMode != GlobalAccessLogMode.None;
}
private void InitAccessLog()
{
}
}
[Flags]
public enum LocalAccessLogMode
{
None = 0,
Application = 1 << 0,
Internal = 1 << 1,
All = Application | Internal
}
[Flags]
public enum GlobalAccessLogMode
{
None = 0,
Log = 1 << 0,
SdCard = 1 << 1,
All = Log | SdCard
}
}

144
src/LibHac/Fs/SaveData.cs Normal file
View file

@ -0,0 +1,144 @@
using System;
using LibHac.Common;
using LibHac.FsService;
namespace LibHac.Fs
{
public static class SaveData
{
public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName,
SaveDataSpaceId spaceId, ulong saveDataId, UserId userId)
{
Result rc = MountHelpers.CheckMountName(mountName);
if (rc.IsFailure()) return rc;
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
SaveDataAttribute attribute = default;
attribute.UserId = userId;
attribute.SaveDataId = saveDataId;
rc = fsProxy.OpenSaveDataFileSystemBySystemSaveDataId(out IFileSystem fileSystem, spaceId, ref attribute);
if (rc.IsFailure()) return rc;
return fs.Register(mountName, fileSystem);
}
public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
UserId userId, ulong ownerId, long size, long journalSize, uint flags)
{
if (fs.IsEnabledAccessLog(LocalAccessLogMode.Internal))
{
TimeSpan startTime = fs.Time.GetCurrent();
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
var attribute = new SaveDataAttribute
{
UserId = userId,
SaveDataId = saveDataId
};
var createInfo = new SaveDataCreateInfo
{
Size = size,
JournalSize = journalSize,
BlockSize = 0x4000,
OwnerId = ownerId,
Flags = flags,
SpaceId = spaceId
};
Result rc = fsProxy.CreateSaveDataFileSystemBySystemSaveDataId(ref attribute, ref createInfo);
TimeSpan endTime = fs.Time.GetCurrent();
fs.OutputAccessLog(rc, startTime, endTime,
$", savedataspaceid: {spaceId}, savedataid: 0x{saveDataId:X}, userid: 0x{userId.Id.High:X16}{userId.Id.Low:X16}, save_data_owner_id: 0x{ownerId:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{flags:X8}");
return rc;
}
else
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
var attribute = new SaveDataAttribute
{
UserId = userId,
SaveDataId = saveDataId
};
var createInfo = new SaveDataCreateInfo
{
Size = size,
JournalSize = journalSize,
BlockSize = 0x4000,
OwnerId = ownerId,
Flags = flags,
SpaceId = spaceId
};
return fsProxy.CreateSaveDataFileSystemBySystemSaveDataId(ref attribute, ref createInfo);
}
}
public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, UserId userId,
ulong ownerId, long size, long journalSize, uint 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, uint flags)
{
return CreateSystemSaveData(fs, SaveDataSpaceId.System, saveDataId, userId, 0, size, journalSize, flags);
}
public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, ulong ownerId, long size,
long journalSize, uint flags)
{
return CreateSystemSaveData(fs, SaveDataSpaceId.System, saveDataId, new UserId(0, 0), ownerId, size, journalSize, flags);
}
public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, long size,
long journalSize, uint flags)
{
return CreateSystemSaveData(fs, SaveDataSpaceId.System, saveDataId, new UserId(0, 0), 0, size, journalSize, flags);
}
public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId,
ulong ownerId, long size, long journalSize, uint flags)
{
return CreateSystemSaveData(fs, spaceId, saveDataId, new UserId(0, 0), ownerId, size, journalSize, flags);
}
public static Result DeleteSaveData(this FileSystemClient fs, ulong saveDataId)
{
if (fs.IsEnabledAccessLog(LocalAccessLogMode.Internal))
{
TimeSpan startTime = fs.Time.GetCurrent();
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
Result result = fsProxy.DeleteSaveDataFileSystem(saveDataId);
TimeSpan endTime = fs.Time.GetCurrent();
fs.OutputAccessLog(result, startTime, endTime, $", savedataid: 0x{saveDataId:X}");
return result;
}
else
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
return fsProxy.DeleteSaveDataFileSystem(saveDataId);
}
}
public static Result DisableAutoSaveDataCreation(this FileSystemClient fsClient)
{
IFileSystemProxy fsProxy = fsClient.GetFileSystemProxyServiceObject();
return fsProxy.DisableAutoSaveDataCreation();
}
}
}

View file

@ -5,7 +5,7 @@ using LibHac.Kvdb;
namespace LibHac.Fs
{
public class SaveDataAttribute : IComparable<SaveDataAttribute>, IComparable, IEquatable<SaveDataAttribute>, IExportable
public class SaveDataAttributeKvdb : IComparable<SaveDataAttributeKvdb>, IComparable, IEquatable<SaveDataAttributeKvdb>, IExportable
{
public ulong TitleId { get; private set; }
public UserId UserId { get; private set; }
@ -44,7 +44,7 @@ namespace LibHac.Fs
public void Freeze() => _isFrozen = true;
public bool Equals(SaveDataAttribute other)
public bool Equals(SaveDataAttributeKvdb other)
{
return other != null && TitleId == other.TitleId && UserId.Equals(other.UserId) && SaveId == other.SaveId &&
Type == other.Type && Rank == other.Rank && Index == other.Index;
@ -52,7 +52,7 @@ namespace LibHac.Fs
public override bool Equals(object obj)
{
return obj is SaveDataAttribute other && Equals(other);
return obj is SaveDataAttributeKvdb other && Equals(other);
}
public override int GetHashCode()
@ -71,7 +71,7 @@ namespace LibHac.Fs
}
}
public int CompareTo(SaveDataAttribute other)
public int CompareTo(SaveDataAttributeKvdb other)
{
int titleIdComparison = TitleId.CompareTo(other.TitleId);
if (titleIdComparison != 0) return titleIdComparison;
@ -89,7 +89,7 @@ namespace LibHac.Fs
public int CompareTo(object obj)
{
if (obj is null) return 1;
return obj is SaveDataAttribute other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(SaveDataAttribute)}");
return obj is SaveDataAttributeKvdb other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(SaveDataAttributeKvdb)}");
}
}
}

View file

@ -7,7 +7,7 @@ using LibHac.Ncm;
namespace LibHac.Fs
{
[StructLayout(LayoutKind.Explicit, Size = 0x40)]
public struct SaveDataAttribute2
public struct SaveDataAttribute
{
[FieldOffset(0x00)] public ulong TitleId;
[FieldOffset(0x08)] public UserId UserId;
@ -78,6 +78,12 @@ namespace LibHac.Fs
[StructLayout(LayoutKind.Explicit, Size = 0x40)]
public struct SaveDataCreateInfo
{
// Todo
[FieldOffset(0x00)] public long Size;
[FieldOffset(0x08)] public long JournalSize;
[FieldOffset(0x10)] public ulong BlockSize;
[FieldOffset(0x18)] public ulong OwnerId;
[FieldOffset(0x20)] public uint Flags;
[FieldOffset(0x24)] public SaveDataSpaceId SpaceId;
[FieldOffset(0x25)] public bool Field25;
}
}

View file

@ -112,7 +112,7 @@ namespace LibHac.FsService
throw new NotImplementedException();
}
public Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId, ref SaveDataAttribute2 attribute)
public Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId, ref SaveDataAttribute attribute)
{
throw new NotImplementedException();
}
@ -122,19 +122,19 @@ namespace LibHac.FsService
throw new NotImplementedException();
}
public Result CreateSaveDataFileSystem(ref SaveDataAttribute2 attribute, ref SaveDataCreateInfo createInfo,
public Result CreateSaveDataFileSystem(ref SaveDataAttribute attribute, ref SaveDataCreateInfo createInfo,
ref SaveMetaCreateInfo metaCreateInfo)
{
throw new NotImplementedException();
}
public Result CreateSaveDataFileSystemWithHashSalt(ref SaveDataAttribute2 attribute, ref SaveDataCreateInfo createInfo,
public Result CreateSaveDataFileSystemWithHashSalt(ref SaveDataAttribute attribute, ref SaveDataCreateInfo createInfo,
ref SaveMetaCreateInfo metaCreateInfo, ref HashSalt hashSalt)
{
throw new NotImplementedException();
}
public Result CreateSaveDataFileSystemBySystemSaveDataId(ref SaveDataAttribute2 attribute, ref SaveDataCreateInfo createInfo)
public Result CreateSaveDataFileSystemBySystemSaveDataId(ref SaveDataAttribute attribute, ref SaveDataCreateInfo createInfo)
{
throw new NotImplementedException();
}
@ -147,11 +147,11 @@ namespace LibHac.FsService
private Result OpenSaveDataFileSystemImpl(out IFileSystem fileSystem, out ulong saveDataId,
SaveDataSpaceId spaceId, ref SaveDataAttribute attribute, bool openReadOnly, bool cacheExtraData)
{
bool hasFixedId = attribute.SaveId != 0 && attribute.UserId.Id == Id128.InvalidId;
bool hasFixedId = attribute.SaveDataId != 0 && attribute.UserId.Id == Id128.InvalidId;
if (hasFixedId)
{
saveDataId = attribute.SaveId;
saveDataId = attribute.SaveDataId;
}
else
{
@ -194,7 +194,7 @@ namespace LibHac.FsService
// Missing permission check, speed emulation storage type wrapper, and FileSystemInterfaceAdapter
fileSystem = default;
if (!IsSystemSaveDataId(attribute.SaveId)) return ResultFs.InvalidArgument.Log();
if (!IsSystemSaveDataId(attribute.SaveDataId)) return ResultFs.InvalidArgument.Log();
Result rc = OpenSaveDataFileSystemImpl(out IFileSystem saveFs, out _, spaceId,
ref attribute, false, true);
@ -219,7 +219,7 @@ namespace LibHac.FsService
}
public Result ReadSaveDataFileSystemExtraDataBySaveDataAttribute(Span<byte> extraDataBuffer, SaveDataSpaceId spaceId,
ref SaveDataAttribute2 attribute)
ref SaveDataAttribute attribute)
{
throw new NotImplementedException();
}
@ -229,7 +229,7 @@ namespace LibHac.FsService
throw new NotImplementedException();
}
public Result WriteSaveDataFileSystemExtraDataBySaveDataAttribute(ref SaveDataAttribute2 attribute, SaveDataSpaceId spaceId,
public Result WriteSaveDataFileSystemExtraDataBySaveDataAttribute(ref SaveDataAttribute attribute, SaveDataSpaceId spaceId,
ReadOnlySpan<byte> extraDataBuffer, ReadOnlySpan<byte> maskBuffer)
{
throw new NotImplementedException();
@ -352,7 +352,7 @@ namespace LibHac.FsService
throw new NotImplementedException();
}
public Result OpenSaveDataMetaFile(out IFile file, SaveDataSpaceId spaceId, ref SaveDataAttribute2 attribute,
public Result OpenSaveDataMetaFile(out IFile file, SaveDataSpaceId spaceId, ref SaveDataAttribute attribute,
SaveMetaType type)
{
throw new NotImplementedException();
@ -520,12 +520,12 @@ namespace LibHac.FsService
return Result.Success;
}
public Result SetGlobalAccessLogMode(int mode)
public Result SetGlobalAccessLogMode(GlobalAccessLogMode mode)
{
throw new NotImplementedException();
}
public Result GetGlobalAccessLogMode(out int mode)
public Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode)
{
throw new NotImplementedException();
}

View file

@ -21,19 +21,19 @@ namespace LibHac.FsService
Result OpenSdCardFileSystem(out IFileSystem fileSystem);
Result FormatSdCardFileSystem();
Result DeleteSaveDataFileSystem(ulong saveDataId);
Result CreateSaveDataFileSystem(ref SaveDataAttribute2 attribute, ref SaveDataCreateInfo createInfo, ref SaveMetaCreateInfo metaCreateInfo);
Result CreateSaveDataFileSystemBySystemSaveDataId(ref SaveDataAttribute2 attribute, ref SaveDataCreateInfo createInfo);
Result CreateSaveDataFileSystem(ref SaveDataAttribute attribute, ref SaveDataCreateInfo createInfo, ref SaveMetaCreateInfo metaCreateInfo);
Result CreateSaveDataFileSystemBySystemSaveDataId(ref SaveDataAttribute attribute, ref SaveDataCreateInfo createInfo);
Result RegisterSaveDataFileSystemAtomicDeletion(ReadOnlySpan<ulong> saveDataIds);
Result DeleteSaveDataFileSystemBySaveDataSpaceId(SaveDataSpaceId spaceId, ulong saveDataId);
Result FormatSdCardDryRun();
Result IsExFatSupported(out bool isSupported);
Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId, ref SaveDataAttribute2 attribute);
Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId, ref SaveDataAttribute attribute);
Result OpenGameCardStorage(out IStorage storage, GameCardHandle handle, GameCardPartitionRaw partitionId);
Result OpenGameCardFileSystem(out IFileSystem fileSystem, GameCardHandle handle, GameCardPartition partitionId);
Result ExtendSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long dataSize, long journalSize);
Result DeleteCacheStorage(short index);
Result GetCacheStorageSize(out long dataSize, out long journalSize, short index);
Result CreateSaveDataFileSystemWithHashSalt(ref SaveDataAttribute2 attribute, ref SaveDataCreateInfo createInfo, ref SaveMetaCreateInfo metaCreateInfo, ref HashSalt hashSalt);
Result CreateSaveDataFileSystemWithHashSalt(ref SaveDataAttribute attribute, ref SaveDataCreateInfo createInfo, ref SaveMetaCreateInfo metaCreateInfo, ref HashSalt hashSalt);
Result OpenSaveDataFileSystem(out IFileSystem fileSystem, SaveDataSpaceId spaceId, ref SaveDataAttribute attribute);
Result OpenSaveDataFileSystemBySystemSaveDataId(out IFileSystem fileSystem, SaveDataSpaceId spaceId, ref SaveDataAttribute attribute);
Result OpenReadOnlySaveDataFileSystem(out IFileSystem fileSystem, SaveDataSpaceId spaceId, ref SaveDataAttribute attribute);
@ -48,9 +48,9 @@ namespace LibHac.FsService
Result WriteSaveDataFileSystemExtraDataWithMask(ulong saveDataId, SaveDataSpaceId spaceId, ReadOnlySpan<byte> extraDataBuffer, ReadOnlySpan<byte> maskBuffer);
Result FindSaveDataWithFilter(out long count, Span<byte> saveDataInfoBuffer, SaveDataSpaceId spaceId, ref SaveDataFilter filter);
Result OpenSaveDataInfoReaderWithFilter(out ISaveDataInfoReader infoReader, SaveDataSpaceId spaceId, ref SaveDataFilter filter);
Result ReadSaveDataFileSystemExtraDataBySaveDataAttribute(Span<byte> extraDataBuffer, SaveDataSpaceId spaceId, ref SaveDataAttribute2 attribute);
Result WriteSaveDataFileSystemExtraDataBySaveDataAttribute(ref SaveDataAttribute2 attribute, SaveDataSpaceId spaceId, ReadOnlySpan<byte> extraDataBuffer, ReadOnlySpan<byte> maskBuffer);
Result OpenSaveDataMetaFile(out IFile file, SaveDataSpaceId spaceId, ref SaveDataAttribute2 attribute, SaveMetaType type);
Result ReadSaveDataFileSystemExtraDataBySaveDataAttribute(Span<byte> extraDataBuffer, SaveDataSpaceId spaceId, ref SaveDataAttribute attribute);
Result WriteSaveDataFileSystemExtraDataBySaveDataAttribute(ref SaveDataAttribute attribute, SaveDataSpaceId spaceId, ReadOnlySpan<byte> extraDataBuffer, ReadOnlySpan<byte> maskBuffer);
Result OpenSaveDataMetaFile(out IFile file, SaveDataSpaceId spaceId, ref SaveDataAttribute attribute, SaveMetaType type);
Result ListAccessibleSaveDataOwnerId(out int readCount, Span<TitleId> idBuffer, TitleId programId, int startIndex, int bufferIdCount);
Result OpenImageDirectoryFileSystem(out IFileSystem fileSystem, ImageDirectoryId dirId);
@ -90,8 +90,8 @@ namespace LibHac.FsService
Result SetSaveDataSize(long saveDataSize, long saveDataJournalSize);
Result SetSaveDataRootPath(ref FsPath path);
Result DisableAutoSaveDataCreation();
Result SetGlobalAccessLogMode(int mode);
Result GetGlobalAccessLogMode(out int mode);
Result SetGlobalAccessLogMode(GlobalAccessLogMode mode);
Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode);
Result OutputAccessLogToSdCard(U8Span logString);
Result RegisterUpdatePartition();
Result OpenRegisteredUpdatePartition(out IFileSystem fileSystem);

View file

@ -288,6 +288,7 @@ namespace LibHac.FsSystem.Save
BcatDeliveryCacheStorage = 2,
DeviceSaveData = 3,
TemporaryStorage = 4,
CacheStorage = 5
CacheStorage = 5,
BcatSystemStorage = 6
}
}