Ensure more FS classes are updated for 13.1.0

- FsSrv.Impl.IResultConvertDirectory
- FsSrv.Impl.IResultConvertFile
- FsSrv.Impl.IResultConvertFileSystem
- FsSrv.Impl.SaveDataExtraDataAccessorCacheManager
- FsSrv.Impl.SaveDataExtraDataResultConvertAccessor
- FsSrv.Impl.SaveDataResultConvert
- FsSrv.Impl.SaveDataResultConvertDirectory
- FsSrv.Impl.SaveDataResultConvertFile
- FsSrv.Impl.SaveDataResultConvertFileSystem
- FsSrv.Impl.StorageInterfaceAdapter
- FsSystem.ISaveDataCommitTimeStampGetter
- FsSystem.ISaveDataExtraDataAccessor
- FsSystem.ISaveDataFileSystemCacheManager
- FsSystem.SaveDataFileSystemCacheManager
- FsSystem.SaveDataFileSystemCacheRegisterBase
This commit is contained in:
Alex Barney 2022-01-27 15:05:58 -07:00
parent 32ffda1d3f
commit e969554639
11 changed files with 132 additions and 71 deletions

View file

@ -6,6 +6,11 @@ using LibHac.Fs.Fsa;
namespace LibHac.FsSrv.Impl;
// ReSharper disable once InconsistentNaming
/// <summary>
/// Wraps an <see cref="IFile"/>, converting its returned <see cref="Result"/>s to different
/// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public abstract class IResultConvertFile : IFile
{
protected UniqueRef<IFile> BaseFile;
@ -56,6 +61,11 @@ public abstract class IResultConvertFile : IFile
}
// ReSharper disable once InconsistentNaming
/// <summary>
/// Wraps an <see cref="IDirectory"/>, converting its returned <see cref="Result"/>s to different
/// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public abstract class IResultConvertDirectory : IDirectory
{
protected UniqueRef<IDirectory> BaseDirectory;
@ -85,6 +95,11 @@ public abstract class IResultConvertDirectory : IDirectory
}
// ReSharper disable once InconsistentNaming
/// <summary>
/// Wraps an <see cref="IFileSystem"/>, converting its returned <see cref="Result"/>s to different
/// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public abstract class IResultConvertFileSystem : IFileSystem
{
protected SharedRef<IFileSystem> BaseFileSystem;
@ -145,6 +160,8 @@ public abstract class IResultConvertFileSystem : IFileSystem
return ConvertResult(BaseFileSystem.Get.GetEntryType(out entryType, path));
}
// Note: The original code uses templates to determine which type of IFile/IDirectory to return. To make things
// easier in C# these two functions have been made abstract functions.
protected abstract override Result DoOpenFile(ref UniqueRef<IFile> outFile, in Path path, OpenMode mode);
protected abstract override Result DoOpenDirectory(ref UniqueRef<IDirectory> outDirectory, in Path path,
@ -192,4 +209,4 @@ public abstract class IResultConvertFileSystem : IFileSystem
}
protected abstract Result ConvertResult(Result result);
}
}

View file

@ -10,8 +10,13 @@ namespace LibHac.FsSrv.Impl;
/// <summary>
/// Holds the <see cref="ISaveDataExtraDataAccessor"/>s for opened save data file systems.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class SaveDataExtraDataAccessorCacheManager : ISaveDataExtraDataAccessorCacheObserver
{
/// <summary>
/// Holds a single cached extra data accessor identified by its save data ID and save data space ID.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[NonCopyable]
private struct Cache : IDisposable
{
@ -19,8 +24,7 @@ public class SaveDataExtraDataAccessorCacheManager : ISaveDataExtraDataAccessorC
private readonly SaveDataSpaceId _spaceId;
private readonly ulong _saveDataId;
public Cache(in SharedRef<ISaveDataExtraDataAccessor> accessor, SaveDataSpaceId spaceId,
ulong saveDataId)
public Cache(in SharedRef<ISaveDataExtraDataAccessor> accessor, SaveDataSpaceId spaceId, ulong saveDataId)
{
_accessor = new WeakRef<ISaveDataExtraDataAccessor>(in accessor);
_spaceId = spaceId;
@ -49,7 +53,7 @@ public class SaveDataExtraDataAccessorCacheManager : ISaveDataExtraDataAccessorC
public SaveDataExtraDataAccessorCacheManager()
{
_accessorList = new LinkedList<Cache>();
_mutex.Initialize();
_mutex = new SdkRecursiveMutexType();
}
public void Dispose()
@ -138,4 +142,4 @@ public class SaveDataExtraDataAccessorCacheManager : ISaveDataExtraDataAccessorC
{
return new UniqueLockRef<SdkRecursiveMutexType>(ref _mutex);
}
}
}

View file

@ -6,6 +6,10 @@ using LibHac.FsSystem;
namespace LibHac.FsSrv.Impl;
/// <summary>
/// Contains functions for converting internal save data <see cref="Result"/>s to external <see cref="Result"/>s.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public static class SaveDataResultConvert
{
private static Result ConvertCorruptedResult(Result result)
@ -13,19 +17,19 @@ public static class SaveDataResultConvert
if (ResultFs.IntegrityVerificationStorageCorrupted.Includes(result))
{
if (ResultFs.IncorrectIntegrityVerificationMagicCode.Includes(result))
return ResultFs.IncorrectSaveDataIntegrityVerificationMagicCode.Value;
return ResultFs.IncorrectSaveDataIntegrityVerificationMagicCode.LogConverted(result);
if (ResultFs.InvalidZeroHash.Includes(result))
return ResultFs.InvalidSaveDataZeroHash.Value;
return ResultFs.InvalidSaveDataZeroHash.LogConverted(result);
if (ResultFs.NonRealDataVerificationFailed.Includes(result))
return ResultFs.SaveDataNonRealDataVerificationFailed.Value;
return ResultFs.SaveDataNonRealDataVerificationFailed.LogConverted(result);
if (ResultFs.ClearedRealDataVerificationFailed.Includes(result))
return ResultFs.ClearedSaveDataRealDataVerificationFailed.Value;
return ResultFs.ClearedSaveDataRealDataVerificationFailed.LogConverted(result);
if (ResultFs.UnclearedRealDataVerificationFailed.Includes(result))
return ResultFs.UnclearedSaveDataRealDataVerificationFailed.Value;
return ResultFs.UnclearedSaveDataRealDataVerificationFailed.LogConverted(result);
Assert.SdkAssert(false);
}
@ -33,16 +37,16 @@ public static class SaveDataResultConvert
if (ResultFs.HostFileSystemCorrupted.Includes(result))
{
if (ResultFs.HostEntryCorrupted.Includes(result))
return ResultFs.SaveDataHostEntryCorrupted.Value;
return ResultFs.SaveDataHostEntryCorrupted.LogConverted(result);
if (ResultFs.HostFileDataCorrupted.Includes(result))
return ResultFs.SaveDataHostFileDataCorrupted.Value;
return ResultFs.SaveDataHostFileDataCorrupted.LogConverted(result);
if (ResultFs.HostFileCorrupted.Includes(result))
return ResultFs.SaveDataHostFileCorrupted.Value;
return ResultFs.SaveDataHostFileCorrupted.LogConverted(result);
if (ResultFs.InvalidHostHandle.Includes(result))
return ResultFs.InvalidSaveDataHostHandle.Value;
return ResultFs.InvalidSaveDataHostHandle.LogConverted(result);
Assert.SdkAssert(false);
}
@ -50,25 +54,25 @@ public static class SaveDataResultConvert
if (ResultFs.DatabaseCorrupted.Includes(result))
{
if (ResultFs.InvalidAllocationTableBlock.Includes(result))
return ResultFs.InvalidSaveDataAllocationTableBlock.Value;
return ResultFs.InvalidSaveDataAllocationTableBlock.LogConverted(result);
if (ResultFs.InvalidKeyValueListElementIndex.Includes(result))
return ResultFs.InvalidSaveDataKeyValueListElementIndex.Value;
return ResultFs.InvalidSaveDataKeyValueListElementIndex.LogConverted(result);
if (ResultFs.InvalidAllocationTableChainEntry.Includes(result))
return ResultFs.InvalidSaveDataAllocationTableChainEntry.Value;
return ResultFs.InvalidSaveDataAllocationTableChainEntry.LogConverted(result);
if (ResultFs.InvalidAllocationTableOffset.Includes(result))
return ResultFs.InvalidSaveDataAllocationTableOffset.Value;
return ResultFs.InvalidSaveDataAllocationTableOffset.LogConverted(result);
if (ResultFs.InvalidAllocationTableBlockCount.Includes(result))
return ResultFs.InvalidSaveDataAllocationTableBlockCount.Value;
return ResultFs.InvalidSaveDataAllocationTableBlockCount.LogConverted(result);
if (ResultFs.InvalidKeyValueListEntryIndex.Includes(result))
return ResultFs.InvalidSaveDataKeyValueListEntryIndex.Value;
return ResultFs.InvalidSaveDataKeyValueListEntryIndex.LogConverted(result);
if (ResultFs.InvalidBitmapIndex.Includes(result))
return ResultFs.InvalidSaveDataBitmapIndex.Value;
return ResultFs.InvalidSaveDataBitmapIndex.LogConverted(result);
Assert.SdkAssert(false);
}
@ -76,7 +80,7 @@ public static class SaveDataResultConvert
if (ResultFs.ZeroBitmapFileCorrupted.Includes(result))
{
if (ResultFs.IncompleteBlockInZeroBitmapHashStorageFile.Includes(result))
return ResultFs.IncompleteBlockInZeroBitmapHashStorageFileSaveData.Value;
return ResultFs.IncompleteBlockInZeroBitmapHashStorageFileSaveData.LogConverted(result);
Assert.SdkAssert(false);
}
@ -84,13 +88,13 @@ public static class SaveDataResultConvert
return result;
}
public static Result ConvertSaveFsDriverPublicResult(Result result)
public static Result ConvertSaveFsDriverPrivateResult(Result result)
{
if (result.IsSuccess())
return result;
if (ResultFs.UnsupportedVersion.Includes(result))
return ResultFs.UnsupportedSaveDataVersion.Value;
return ResultFs.UnsupportedSaveDataVersion.LogConverted(result);
if (ResultFs.IntegrityVerificationStorageCorrupted.Includes(result) ||
ResultFs.BuiltInStorageCorrupted.Includes(result) ||
@ -105,21 +109,21 @@ public static class SaveDataResultConvert
return result;
if (ResultFs.NotFound.Includes(result))
return ResultFs.PathNotFound.Value;
return ResultFs.PathNotFound.LogConverted(result);
if (ResultFs.AllocationTableFull.Includes(result))
return ResultFs.UsableSpaceNotEnough.Value;
return ResultFs.UsableSpaceNotEnough.LogConverted(result);
if (ResultFs.AlreadyExists.Includes(result))
return ResultFs.PathAlreadyExists.Value;
return ResultFs.PathAlreadyExists.LogConverted(result);
if (ResultFs.InvalidOffset.Includes(result))
return ResultFs.OutOfRange.Value;
return ResultFs.OutOfRange.LogConverted(result);
if (ResultFs.IncompatiblePath.Includes(result) ||
ResultFs.FileNotFound.Includes(result))
{
return ResultFs.PathNotFound.Value;
return ResultFs.PathNotFound.LogConverted(result);
}
return result;
@ -130,6 +134,7 @@ public static class SaveDataResultConvert
/// Wraps an <see cref="IFile"/>, converting its returned <see cref="Result"/>s
/// to save-data-specific <see cref="Result"/>s.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class SaveDataResultConvertFile : IResultConvertFile
{
public SaveDataResultConvertFile(ref UniqueRef<IFile> baseFile) : base(ref baseFile)
@ -138,7 +143,7 @@ public class SaveDataResultConvertFile : IResultConvertFile
protected override Result ConvertResult(Result result)
{
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(result);
return SaveDataResultConvert.ConvertSaveFsDriverPrivateResult(result);
}
}
@ -146,6 +151,7 @@ public class SaveDataResultConvertFile : IResultConvertFile
/// Wraps an <see cref="IDirectory"/>, converting its returned <see cref="Result"/>s
/// to save-data-specific <see cref="Result"/>s.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class SaveDataResultConvertDirectory : IResultConvertDirectory
{
public SaveDataResultConvertDirectory(ref UniqueRef<IDirectory> baseDirectory) : base(ref baseDirectory)
@ -154,7 +160,7 @@ public class SaveDataResultConvertDirectory : IResultConvertDirectory
protected override Result ConvertResult(Result result)
{
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(result);
return SaveDataResultConvert.ConvertSaveFsDriverPrivateResult(result);
}
}
@ -162,6 +168,7 @@ public class SaveDataResultConvertDirectory : IResultConvertDirectory
/// Wraps an <see cref="IFileSystem"/>, converting its returned <see cref="Result"/>s
/// to save-data-specific <see cref="Result"/>s.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class SaveDataResultConvertFileSystem : IResultConvertFileSystem
{
public SaveDataResultConvertFileSystem(ref SharedRef<IFileSystem> baseFileSystem)
@ -192,7 +199,7 @@ public class SaveDataResultConvertFileSystem : IResultConvertFileSystem
protected override Result ConvertResult(Result result)
{
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(result);
return SaveDataResultConvert.ConvertSaveFsDriverPrivateResult(result);
}
}
@ -200,6 +207,7 @@ public class SaveDataResultConvertFileSystem : IResultConvertFileSystem
/// Wraps an <see cref="ISaveDataExtraDataAccessor"/>, converting its returned <see cref="Result"/>s
/// to save-data-specific <see cref="Result"/>s.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class SaveDataExtraDataResultConvertAccessor : ISaveDataExtraDataAccessor
{
private SharedRef<ISaveDataExtraDataAccessor> _accessor;
@ -217,19 +225,19 @@ public class SaveDataExtraDataResultConvertAccessor : ISaveDataExtraDataAccessor
public Result WriteExtraData(in SaveDataExtraData extraData)
{
Result rc = _accessor.Get.WriteExtraData(in extraData);
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(rc);
return SaveDataResultConvert.ConvertSaveFsDriverPrivateResult(rc);
}
public Result CommitExtraData(bool updateTimeStamp)
{
Result rc = _accessor.Get.CommitExtraData(updateTimeStamp);
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(rc);
return SaveDataResultConvert.ConvertSaveFsDriverPrivateResult(rc);
}
public Result ReadExtraData(out SaveDataExtraData extraData)
{
Result rc = _accessor.Get.ReadExtraData(out extraData);
return SaveDataResultConvert.ConvertSaveFsDriverPublicResult(rc);
return SaveDataResultConvert.ConvertSaveFsDriverPrivateResult(rc);
}
public void RegisterCacheObserver(ISaveDataExtraDataAccessorCacheObserver observer, SaveDataSpaceId spaceId,
@ -237,4 +245,4 @@ public class SaveDataExtraDataResultConvertAccessor : ISaveDataExtraDataAccessor
{
_accessor.Get.RegisterCacheObserver(observer, spaceId, saveDataId);
}
}
}

View file

@ -8,6 +8,10 @@ using IStorageSf = LibHac.FsSrv.Sf.IStorage;
namespace LibHac.FsSrv.Impl;
/// <summary>
/// Wraps an <see cref="IStorage"/> to allow interfacing with it via the <see cref="IStorageSf"/> interface over IPC.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class StorageInterfaceAdapter : IStorageSf
{
private SharedRef<IStorage> _baseStorage;
@ -32,6 +36,9 @@ public class StorageInterfaceAdapter : IStorageSf
if (destination.Size < 0)
return ResultFs.InvalidSize.Log();
if (destination.Size < size)
return ResultFs.InvalidSize.Log();
Result rc = Result.Success;
for (int tryNum = 0; tryNum < maxTryCount; tryNum++)
@ -54,6 +61,9 @@ public class StorageInterfaceAdapter : IStorageSf
if (source.Size < 0)
return ResultFs.InvalidSize.Log();
if (source.Size < size)
return ResultFs.InvalidSize.Log();
using var scopedPriorityChanger = new ScopedThreadPriorityChangerByAccessPriority(
ScopedThreadPriorityChangerByAccessPriority.AccessMode.Write);
@ -99,4 +109,4 @@ public class StorageInterfaceAdapter : IStorageSf
return Result.Success;
}
}
}

View file

@ -1,6 +1,10 @@
namespace LibHac.FsSystem;
/// <summary>
/// Gets Unix timestamps used to update a save data's commit time.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public interface ISaveDataCommitTimeStampGetter
{
Result Get(out long timeStamp);
}
}

View file

@ -3,10 +3,14 @@ using LibHac.Fs;
namespace LibHac.FsSystem;
/// <summary>
/// Provides read/write access to a save data file system's extra data.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public interface ISaveDataExtraDataAccessor : IDisposable
{
Result WriteExtraData(in SaveDataExtraData extraData);
Result CommitExtraData(bool updateTimeStamp);
Result ReadExtraData(out SaveDataExtraData extraData);
void RegisterCacheObserver(ISaveDataExtraDataAccessorCacheObserver observer, SaveDataSpaceId spaceId, ulong saveDataId);
}
}

View file

@ -1,9 +1,16 @@
using System;
using LibHac.Fs;
using LibHac.FsSrv.Impl;
namespace LibHac.FsSystem;
/// <summary>
/// Used when adding an <see cref="ISaveDataExtraDataAccessor"/> to the
/// <see cref="SaveDataExtraDataAccessorCacheManager"/>. When an extra data accessor is disposed, the accessor will
/// use this interface to notify the cache manager that it should be removed from the extra data cache.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public interface ISaveDataExtraDataAccessorCacheObserver : IDisposable
{
void Unregister(SaveDataSpaceId spaceId, ulong saveDataId);
}
}

View file

@ -4,10 +4,14 @@ using LibHac.Fs;
namespace LibHac.FsSystem;
/// <summary>
/// Provides a mechanism for caching save data file systems.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public interface ISaveDataFileSystemCacheManager : IDisposable
{
bool GetCache(ref SharedRef<SaveDataFileSystemHolder> outFileSystem, SaveDataSpaceId spaceId, ulong saveDataId);
void Register(ref SharedRef<SaveDataFileSystemHolder> fileSystem);
void Register(ref SharedRef<ApplicationTemporaryFileSystem> fileSystem);
void Unregister(SaveDataSpaceId spaceId, ulong saveDataId);
}
}

View file

@ -5,8 +5,17 @@ using LibHac.Os;
namespace LibHac.FsSystem;
/// <summary>
/// Manages a list of cached save data file systems. Each file system is registered and retrieved
/// based on its save data ID and save data space ID.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class SaveDataFileSystemCacheManager : ISaveDataFileSystemCacheManager
{
/// <summary>
/// Holds a single cached file system identified by its save data ID and save data space ID.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[NonCopyable]
private struct Cache
{
@ -26,9 +35,9 @@ public class SaveDataFileSystemCacheManager : ISaveDataFileSystemCacheManager
return _fileSystem.HasValue && _spaceId == spaceId && _saveDataId == saveDataId;
}
public void Move(ref SharedRef<SaveDataFileSystemHolder> outFileSystem)
public SharedRef<SaveDataFileSystemHolder> Move()
{
outFileSystem.SetByMove(ref _fileSystem);
return SharedRef<SaveDataFileSystemHolder>.CreateMove(ref _fileSystem);
}
public void Register(ref SharedRef<SaveDataFileSystemHolder> fileSystem)
@ -52,7 +61,7 @@ public class SaveDataFileSystemCacheManager : ISaveDataFileSystemCacheManager
public SaveDataFileSystemCacheManager()
{
_mutex.Initialize();
_mutex = new SdkRecursiveMutexType();
}
public void Dispose()
@ -77,11 +86,12 @@ public class SaveDataFileSystemCacheManager : ISaveDataFileSystemCacheManager
Assert.SdkAssert(_cachedFileSystems is null);
_maxCachedFileSystemCount = maxCacheCount;
if (maxCacheCount <= 0)
return Result.Success;
if (maxCacheCount > 0)
{
// Note: The original checks for overflow here
_cachedFileSystems = new Cache[maxCacheCount];
}
// Note: The original checks for overflow here
_cachedFileSystems = new Cache[maxCacheCount];
return Result.Success;
}
@ -96,7 +106,9 @@ public class SaveDataFileSystemCacheManager : ISaveDataFileSystemCacheManager
{
if (_cachedFileSystems[i].IsCached(spaceId, saveDataId))
{
_cachedFileSystems[i].Move(ref outFileSystem);
using SharedRef<SaveDataFileSystemHolder> cachedFs = _cachedFileSystems[i].Move();
outFileSystem.SetByMove(ref cachedFs.Ref());
return true;
}
}
@ -156,4 +168,4 @@ public class SaveDataFileSystemCacheManager : ISaveDataFileSystemCacheManager
{
return new UniqueLockRef<SdkRecursiveMutexType>(ref _mutex);
}
}
}

View file

@ -1,5 +1,5 @@
using System;
using InlineIL;
using System.Runtime.CompilerServices;
using LibHac.Common;
using LibHac.Diag;
using LibHac.Fs;
@ -14,6 +14,7 @@ namespace LibHac.FsSystem;
/// </summary>
/// <typeparam name="T">The type of the base file system. Must be one of <see cref="SaveDataFileSystem"/>,
/// <see cref="ApplicationTemporaryFileSystem"/> or <see cref="DirectorySaveDataFileSystem"/>.</typeparam>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
public class SaveDataFileSystemCacheRegisterBase<T> : IFileSystem where T : IFileSystem
{
private SharedRef<T> _baseFileSystem;
@ -36,11 +37,11 @@ public class SaveDataFileSystemCacheRegisterBase<T> : IFileSystem where T : IFil
{
if (typeof(T) == typeof(SaveDataFileSystemHolder))
{
_cacheManager.Register(ref GetBaseFileSystemNormal());
_cacheManager.Register(ref Unsafe.As<SharedRef<T>, SharedRef<SaveDataFileSystemHolder>>(ref _baseFileSystem));
}
else if (typeof(T) == typeof(ApplicationTemporaryFileSystem))
{
_cacheManager.Register(ref GetBaseFileSystemTemp());
_cacheManager.Register(ref Unsafe.As<SharedRef<T>, SharedRef<ApplicationTemporaryFileSystem>>(ref _baseFileSystem));
}
else
{
@ -48,23 +49,6 @@ public class SaveDataFileSystemCacheRegisterBase<T> : IFileSystem where T : IFil
}
}
// Hack around not being able to use Unsafe.As on ref structs
private ref SharedRef<SaveDataFileSystemHolder> GetBaseFileSystemNormal()
{
IL.Emit.Ldarg_0();
IL.Emit.Ldflda(new FieldRef(typeof(SaveDataFileSystemCacheRegisterBase<T>), nameof(_baseFileSystem)));
IL.Emit.Ret();
throw IL.Unreachable();
}
private ref SharedRef<ApplicationTemporaryFileSystem> GetBaseFileSystemTemp()
{
IL.Emit.Ldarg_0();
IL.Emit.Ldflda(new FieldRef(typeof(SaveDataFileSystemCacheRegisterBase<T>), nameof(_baseFileSystem)));
IL.Emit.Ret();
throw IL.Unreachable();
}
protected override Result DoOpenFile(ref UniqueRef<IFile> outFile, in Path path, OpenMode mode)
{
return _baseFileSystem.Get.OpenFile(ref outFile, path, mode);

View file

@ -6,6 +6,13 @@ using LibHac.Fs.Fsa;
namespace LibHac.FsSystem;
/// <summary>
/// Holds a file system for adding to the save data file system cache.
/// </summary>
/// <remarks> Nintendo uses concrete types in <see cref="ISaveDataFileSystemCacheManager"/> instead of an interface.
/// This class allows <see cref="DirectorySaveDataFileSystem"/> to be cached in a way that changes the original
/// design as little as possible.
/// </remarks>
public class SaveDataFileSystemHolder : ForwardingFileSystem
{
public SaveDataFileSystemHolder(ref SharedRef<IFileSystem> baseFileSystem) : base(ref baseFileSystem)
@ -49,4 +56,4 @@ public class SaveDataFileSystemHolder : ForwardingFileSystem
throw new NotImplementedException();
}
}
}