diff --git a/src/LibHac/Fs/Fsa/Registrar.cs b/src/LibHac/Fs/Fsa/Registrar.cs
index 1a2e06f0..5ac0b76a 100644
--- a/src/LibHac/Fs/Fsa/Registrar.cs
+++ b/src/LibHac/Fs/Fsa/Registrar.cs
@@ -1,7 +1,7 @@
using System;
using LibHac.Common;
+using LibHac.Diag;
using LibHac.Fs.Impl;
-using LibHac.Util;
namespace LibHac.Fs.Fsa;
@@ -15,12 +15,93 @@ public interface ISaveDataAttributeGetter : IDisposable
Result GetSaveDataAttribute(out SaveDataAttribute attribute);
}
+public interface IUnmountHookInvoker : IDisposable
+{
+ void Invoke();
+}
+
///
/// Contains functions for registering and unregistering mounted s.
///
-/// Based on FS 12.1.0 (nnSdk 12.3.1)
+/// Based on FS 13.1.0 (nnSdk 13.4.0)
public static class Registrar
{
+ private class UnmountHookFileSystem : IFileSystem
+ {
+ private UniqueRef _fileSystem;
+ private UniqueRef _unmountHookInvoker;
+
+ public UnmountHookFileSystem(ref UniqueRef fileSystem,
+ ref UniqueRef unmountHookInvoker)
+ {
+ _fileSystem = new UniqueRef(ref fileSystem);
+ _unmountHookInvoker = new UniqueRef(ref unmountHookInvoker);
+ }
+
+ public override void Dispose()
+ {
+ if (_unmountHookInvoker.HasValue)
+ _unmountHookInvoker.Get.Invoke();
+
+ _unmountHookInvoker.Destroy();
+ _fileSystem.Destroy();
+
+ base.Dispose();
+ }
+
+ protected override Result DoCreateFile(in Path path, long size, CreateFileOptions option) =>
+ _fileSystem.Get.CreateFile(in path, size, option);
+
+ protected override Result DoDeleteFile(in Path path) => _fileSystem.Get.DeleteFile(in path);
+
+ protected override Result DoCreateDirectory(in Path path) => _fileSystem.Get.CreateDirectory(in path);
+
+ protected override Result DoDeleteDirectory(in Path path) => _fileSystem.Get.DeleteDirectory(in path);
+
+ protected override Result DoDeleteDirectoryRecursively(in Path path) =>
+ _fileSystem.Get.DeleteDirectoryRecursively(in path);
+
+ protected override Result DoCleanDirectoryRecursively(in Path path) =>
+ _fileSystem.Get.CleanDirectoryRecursively(in path);
+
+ protected override Result DoRenameFile(in Path currentPath, in Path newPath) =>
+ _fileSystem.Get.RenameFile(in currentPath, in newPath);
+
+ protected override Result DoRenameDirectory(in Path currentPath, in Path newPath) =>
+ _fileSystem.Get.RenameDirectory(in currentPath, in newPath);
+
+ protected override Result DoGetEntryType(out DirectoryEntryType entryType, in Path path) =>
+ _fileSystem.Get.GetEntryType(out entryType, in path);
+
+ protected override Result DoGetFreeSpaceSize(out long freeSpace, in Path path) =>
+ _fileSystem.Get.GetFreeSpaceSize(out freeSpace, in path);
+
+ protected override Result DoGetTotalSpaceSize(out long totalSpace, in Path path) =>
+ _fileSystem.Get.GetTotalSpaceSize(out totalSpace, in path);
+
+ protected override Result DoOpenFile(ref UniqueRef outFile, in Path path, OpenMode mode) =>
+ _fileSystem.Get.OpenFile(ref outFile, in path, mode);
+
+ protected override Result DoOpenDirectory(ref UniqueRef outDirectory, in Path path,
+ OpenDirectoryMode mode) =>
+ _fileSystem.Get.OpenDirectory(ref outDirectory, in path, mode);
+
+ protected override Result DoCommit() => _fileSystem.Get.Commit();
+
+ protected override Result DoCommitProvisionally(long counter) =>
+ _fileSystem.Get.CommitProvisionally(counter);
+
+ protected override Result DoRollback() => _fileSystem.Get.Rollback();
+
+ protected override Result DoFlush() => _fileSystem.Get.Flush();
+
+ protected override Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, in Path path) =>
+ _fileSystem.Get.GetFileTimeStampRaw(out timeStamp, in path);
+
+ protected override Result DoQueryEntry(Span outBuffer, ReadOnlySpan inBuffer, QueryId queryId,
+ in Path path) => _fileSystem.Get.QueryEntry(outBuffer, inBuffer, queryId, in path);
+ }
+
public static Result Register(this FileSystemClient fs, U8Span name, ref UniqueRef fileSystem)
{
using var attributeGetter = new UniqueRef();
@@ -51,12 +132,28 @@ public static class Registrar
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
ref UniqueRef fileSystem, ref UniqueRef mountNameGenerator,
- bool useDataCache, bool usePathCache)
+ bool useDataCache, IStorage storageForPurgeFileDataCache, bool usePathCache)
+ {
+ using var unmountHookInvoker = new UniqueRef();
+ using var attributeGetter = new UniqueRef();
+
+ Result rc = Register(fs, name, multiCommitTarget, ref fileSystem, ref mountNameGenerator,
+ ref attributeGetter.Ref(), useDataCache, storageForPurgeFileDataCache, usePathCache,
+ ref unmountHookInvoker.Ref());
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
+ ref UniqueRef fileSystem, ref UniqueRef mountNameGenerator,
+ bool useDataCache, IStorage storageForPurgeFileDataCache, bool usePathCache,
+ ref UniqueRef unmountHook)
{
using var attributeGetter = new UniqueRef();
Result rc = Register(fs, name, multiCommitTarget, ref fileSystem, ref mountNameGenerator,
- ref attributeGetter.Ref(), useDataCache, usePathCache, new Optional());
+ ref attributeGetter.Ref(), useDataCache, storageForPurgeFileDataCache, usePathCache, ref unmountHook);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
@@ -64,12 +161,14 @@ public static class Registrar
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
ref UniqueRef fileSystem, ref UniqueRef mountNameGenerator,
- bool useDataCache, bool usePathCache, Optional dataId)
+ ref UniqueRef saveAttributeGetter, bool useDataCache,
+ IStorage storageForPurgeFileDataCache, bool usePathCache)
{
- using var attributeGetter = new UniqueRef();
+ using var unmountHookInvoker = new UniqueRef();
Result rc = Register(fs, name, multiCommitTarget, ref fileSystem, ref mountNameGenerator,
- ref attributeGetter.Ref(), useDataCache, usePathCache, dataId);
+ ref saveAttributeGetter, useDataCache, storageForPurgeFileDataCache, usePathCache,
+ ref unmountHookInvoker.Ref());
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
@@ -77,29 +176,29 @@ public static class Registrar
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
ref UniqueRef fileSystem, ref UniqueRef mountNameGenerator,
- ref UniqueRef saveAttributeGetter, bool useDataCache, bool usePathCache)
+ ref UniqueRef saveAttributeGetter, bool useDataCache,
+ IStorage storageForPurgeFileDataCache, bool usePathCache, ref UniqueRef unmountHook)
{
- Result rc = Register(fs, name, multiCommitTarget, ref fileSystem, ref mountNameGenerator,
- ref saveAttributeGetter, useDataCache, usePathCache, new Optional());
- if (rc.IsFailure()) return rc.Miss();
+ if (useDataCache)
+ Assert.SdkAssert(storageForPurgeFileDataCache is not null);
- return Result.Success;
- }
+ using (var unmountHookFileSystem =
+ new UniqueRef(new UnmountHookFileSystem(ref fileSystem, ref unmountHook)))
+ {
+ fileSystem.Set(ref unmountHookFileSystem.Ref());
+ }
+
+ if (!fileSystem.HasValue)
+ return ResultFs.AllocationMemoryFailedInRegisterB.Log();
- public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
- ref UniqueRef fileSystem, ref UniqueRef mountNameGenerator,
- ref UniqueRef saveAttributeGetter, bool useDataCache, bool usePathCache,
- Optional dataId)
- {
using var accessor = new UniqueRef(new FileSystemAccessor(fs.Hos, name,
multiCommitTarget, ref fileSystem, ref mountNameGenerator, ref saveAttributeGetter));
if (!accessor.HasValue)
return ResultFs.AllocationMemoryFailedInRegisterB.Log();
- // accessor.Get.SetFileDataCacheAttachable(useDataCache);
+ accessor.Get.SetFileDataCacheAttachable(useDataCache, storageForPurgeFileDataCache);
accessor.Get.SetPathBasedFileDataCacheAttachable(usePathCache);
- // accessor.Get.SetDataId(dataId);
Result rc = fs.Impl.Register(ref accessor.Ref());
if (rc.IsFailure()) return rc.Miss();
diff --git a/src/LibHac/Fs/Shim/SaveData.cs b/src/LibHac/Fs/Shim/SaveData.cs
index 704f58d6..9a11a4cd 100644
--- a/src/LibHac/Fs/Shim/SaveData.cs
+++ b/src/LibHac/Fs/Shim/SaveData.cs
@@ -50,7 +50,7 @@ public static class SaveData
using var mountNameGenerator = new UniqueRef();
rc = fs.Fs.Register(mountName, fileSystemAdapterRaw, ref fileSystemAdapter.Ref(),
- ref mountNameGenerator.Ref(), false, true);
+ ref mountNameGenerator.Ref(), false, null, true);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
@@ -291,4 +291,4 @@ public static class SaveData
return rc;
}
-}
+}
\ No newline at end of file
diff --git a/src/LibHac/Fs/Shim/SystemSaveData.cs b/src/LibHac/Fs/Shim/SystemSaveData.cs
index c55c85c0..3de0cab7 100644
--- a/src/LibHac/Fs/Shim/SystemSaveData.cs
+++ b/src/LibHac/Fs/Shim/SystemSaveData.cs
@@ -87,7 +87,7 @@ public static class SystemSaveData
{
using var mountNameGenerator = new UniqueRef();
return fs.Register(mountName, fileSystemAdapterRaw, ref fileSystemAdapter.Ref(),
- ref mountNameGenerator.Ref(), false, false);
+ ref mountNameGenerator.Ref(), false, null, false);
}
else
{
@@ -95,4 +95,4 @@ public static class SystemSaveData
}
}
}
-}
+}
\ No newline at end of file