Implement ApplicationTemporaryFileSystem

This commit is contained in:
Alex Barney 2024-03-09 18:38:04 -07:00
parent 2c14770ceb
commit 45975ddadd
4 changed files with 110 additions and 36 deletions

View file

@ -1069,6 +1069,7 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
2,6396,,,,UnsupportedRollbackOnlyModifiedForDirectorySaveDataFileSystem, 2,6396,,,,UnsupportedRollbackOnlyModifiedForDirectorySaveDataFileSystem,
2,6397,,,,UnsupportedOperateRangeForRegionSwitchStorage, 2,6397,,,,UnsupportedOperateRangeForRegionSwitchStorage,
2,6398,,,,UnsupportedOperateRangeForSaveDataFile, 2,6398,,,,UnsupportedOperateRangeForSaveDataFile,
2,6399,,,,UnsupportedOperateRangeForApplicationTemporaryFile,
2,6400,6449,,,PermissionDenied, 2,6400,6449,,,PermissionDenied,
2,6403,,,,HostFileSystemOperationDisabled,Returned when opening a host FS on a retail device. 2,6403,,,,HostFileSystemOperationDisabled,Returned when opening a host FS on a retail device.

1 Module DescriptionStart DescriptionEnd Flags Namespace Name Summary
1069 3 506 505 OutOfAddressSpace OutOfTransferMemory
1070 3 510 506 SessionClosedForReceive OutOfAddressSpace
1071 3 511 510 SessionClosedForReply SessionClosedForReceive
1072 3 511 SessionClosedForReply
1073 3 512 ReceiveListBroken
1074 4 9 InvalidHandle
1075 4 2001 InvalidArgument

View file

@ -1962,6 +1962,8 @@ public static class ResultFs
public static Result.Base UnsupportedOperateRangeForRegionSwitchStorage => new Result.Base(ModuleFs, 6397); public static Result.Base UnsupportedOperateRangeForRegionSwitchStorage => new Result.Base(ModuleFs, 6397);
/// <summary>Error code: 2002-6398; Inner value: 0x31fc02</summary> /// <summary>Error code: 2002-6398; Inner value: 0x31fc02</summary>
public static Result.Base UnsupportedOperateRangeForSaveDataFile => new Result.Base(ModuleFs, 6398); public static Result.Base UnsupportedOperateRangeForSaveDataFile => new Result.Base(ModuleFs, 6398);
/// <summary>Error code: 2002-6399; Inner value: 0x31fe02</summary>
public static Result.Base UnsupportedOperateRangeForApplicationTemporaryFile => new Result.Base(ModuleFs, 6399);
/// <summary>Error code: 2002-6400; Range: 6400-6449; Inner value: 0x320002</summary> /// <summary>Error code: 2002-6400; Range: 6400-6449; Inner value: 0x320002</summary>
public static Result.Base PermissionDenied { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 6400, 6449); } public static Result.Base PermissionDenied { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 6400, 6449); }

View file

@ -1,7 +1,9 @@
// ReSharper disable UnusedMember.Local UnusedType.Local // ReSharper disable UnusedMember.Local UnusedType.Local
#pragma warning disable CS0169 // Field is never used #pragma warning disable CS0169 // Field is never used
using System; using System;
using System.Runtime.CompilerServices;
using LibHac.Common; using LibHac.Common;
using LibHac.Diag;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
using LibHac.FsSystem.Save; using LibHac.FsSystem.Save;
@ -14,43 +16,75 @@ file class ApplicationTemporaryFile : IFile
public ApplicationTemporaryFile(ref UniqueRef<IFile> file) public ApplicationTemporaryFile(ref UniqueRef<IFile> file)
{ {
throw new NotImplementedException(); _file = new UniqueRef<IFile>(ref file);
Assert.SdkRequiresNotNull(in _file);
} }
public override void Dispose() public override void Dispose()
{ {
throw new NotImplementedException(); Assert.SdkRequiresNotNull(in _file);
_file.Destroy();
base.Dispose();
} }
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option) protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option)
{ {
throw new NotImplementedException(); Assert.SdkRequiresNotNull(in _file);
Result res = _file.Get.Read(out bytesRead, offset, destination);
if (res.IsFailure())
{
if (ResultFs.InvalidSaveDataFileReadOffset.Includes(res))
{
return ResultFs.OutOfRange.LogConverted(res);
}
return res.Miss();
}
return Result.Success;
} }
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option) protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
{ {
throw new NotImplementedException(); Assert.SdkRequiresNotNull(in _file);
return _file.Get.Write(offset, source, in option).Ret();
} }
protected override Result DoFlush() protected override Result DoFlush()
{ {
throw new NotImplementedException(); Assert.SdkRequiresNotNull(in _file);
return _file.Get.Flush().Ret();
} }
protected override Result DoSetSize(long size) protected override Result DoSetSize(long size)
{ {
throw new NotImplementedException(); Assert.SdkRequiresNotNull(in _file);
return _file.Get.SetSize(size).Ret();
} }
protected override Result DoGetSize(out long size) protected override Result DoGetSize(out long size)
{ {
throw new NotImplementedException(); Assert.SdkRequiresNotNull(in _file);
return _file.Get.GetSize(out size).Ret();
} }
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size, protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
ReadOnlySpan<byte> inBuffer) ReadOnlySpan<byte> inBuffer)
{ {
throw new NotImplementedException(); Assert.SdkRequiresNotNull(in _file);
if (operationId == OperationId.InvalidateCache)
return ResultFs.UnsupportedOperateRangeForApplicationTemporaryFile.Log();
return _file.Get.OperateRange(outBuffer, operationId, offset, size, inBuffer).Ret();
} }
} }
@ -65,140 +99,177 @@ public class ApplicationTemporaryFileSystem : ISaveDataFileSystem, ISaveDataExtr
public ApplicationTemporaryFileSystem() public ApplicationTemporaryFileSystem()
{ {
throw new NotImplementedException(); _baseStorage = new SharedRef<IStorage>();
_saveFsDriver = new IntegritySaveDataFileSystemDriver();
_isInitialized = false;
_cacheObserver = null;
} }
public override void Dispose() public override void Dispose()
{ {
throw new NotImplementedException(); if (_isInitialized)
{
_saveFsDriver.Commit().IgnoreResult();
_saveFsDriver.FinalizeObject();
_cacheObserver?.Unregister(_spaceId, _saveDataId);
_isInitialized = false;
}
_saveFsDriver.Dispose();
_baseStorage.Destroy();
base.Dispose();
} }
public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator, public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator,
IHash256GeneratorFactorySelector hashGeneratorFactorySelector) IHash256GeneratorFactorySelector hashGeneratorFactorySelector)
{ {
throw new NotImplementedException(); Result res = baseStorage.GetSize(out long size);
if (res.IsFailure()) return res.Miss();
using var baseSubStorage = new ValueSubStorage(baseStorage, 0, size);
res = _saveFsDriver.Initialize(in baseSubStorage, bufferManager, macGenerator, hashGeneratorFactorySelector);
if (res.IsFailure()) return res.Miss();
_isInitialized = true;
return Result.Success;
} }
public Result Initialize(ref readonly SharedRef<IStorage> baseStorage, IBufferManager bufferManager, public Result Initialize(ref readonly SharedRef<IStorage> baseStorage, IBufferManager bufferManager,
IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector) IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector)
{ {
throw new NotImplementedException(); _baseStorage.SetByCopy(in baseStorage);
return Initialize(_baseStorage.Get, bufferManager, macGenerator, hashGeneratorFactorySelector).Ret();
} }
protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option)
{ {
throw new NotImplementedException(); return _saveFsDriver.CreateFile(in path, size, option).Ret();
} }
protected override Result DoDeleteFile(ref readonly Path path) protected override Result DoDeleteFile(ref readonly Path path)
{ {
throw new NotImplementedException(); return _saveFsDriver.DeleteFile(in path).Ret();
} }
protected override Result DoCreateDirectory(ref readonly Path path) protected override Result DoCreateDirectory(ref readonly Path path)
{ {
throw new NotImplementedException(); return _saveFsDriver.CreateDirectory(in path).Ret();
} }
protected override Result DoDeleteDirectory(ref readonly Path path) protected override Result DoDeleteDirectory(ref readonly Path path)
{ {
throw new NotImplementedException(); return _saveFsDriver.DeleteDirectory(in path).Ret();
} }
protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) protected override Result DoDeleteDirectoryRecursively(ref readonly Path path)
{ {
throw new NotImplementedException(); return _saveFsDriver.DeleteDirectoryRecursively(in path).Ret();
} }
protected override Result DoCleanDirectoryRecursively(ref readonly Path path) protected override Result DoCleanDirectoryRecursively(ref readonly Path path)
{ {
throw new NotImplementedException(); return _saveFsDriver.CleanDirectoryRecursively(in path).Ret();
} }
protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath)
{ {
throw new NotImplementedException(); return _saveFsDriver.RenameFile(in currentPath, in newPath).Ret();
} }
protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath)
{ {
throw new NotImplementedException(); return _saveFsDriver.RenameDirectory(in currentPath, in newPath).Ret();
} }
protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path)
{ {
throw new NotImplementedException(); return _saveFsDriver.GetEntryType(out entryType, in path).Ret();
} }
protected override Result DoOpenFile(ref UniqueRef<IFile> outFile, ref readonly Path path, OpenMode mode) protected override Result DoOpenFile(ref UniqueRef<IFile> outFile, ref readonly Path path, OpenMode mode)
{ {
throw new NotImplementedException(); using var file = new UniqueRef<IFile>();
Result res = _saveFsDriver.OpenFile(ref file.Ref, in path, mode);
if (res.IsFailure()) return res.Miss();
using var wrapperFile = new UniqueRef<ApplicationTemporaryFile>(new ApplicationTemporaryFile(ref file.Ref));
outFile.Set(ref wrapperFile.Ref);
return Result.Success;
} }
protected override Result DoOpenDirectory(ref UniqueRef<IDirectory> outDirectory, ref readonly Path path, protected override Result DoOpenDirectory(ref UniqueRef<IDirectory> outDirectory, ref readonly Path path,
OpenDirectoryMode mode) OpenDirectoryMode mode)
{ {
throw new NotImplementedException(); return _saveFsDriver.OpenDirectory(ref outDirectory, in path, mode).Ret();
} }
protected override Result DoCommit() protected override Result DoCommit()
{ {
throw new NotImplementedException(); return _saveFsDriver.Commit().Ret();
} }
protected override Result DoCommitProvisionally(long counter) protected override Result DoCommitProvisionally(long counter)
{ {
throw new NotImplementedException(); return ResultFs.UnsupportedCommitProvisionallyForApplicationTemporaryFileSystem.Log();
} }
protected override Result DoRollback() protected override Result DoRollback()
{ {
throw new NotImplementedException(); return Result.Success;
} }
protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path)
{ {
throw new NotImplementedException(); return _saveFsDriver.GetFreeSpaceSize(out freeSpace, in path).Ret();
} }
protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path)
{ {
throw new NotImplementedException(); return _saveFsDriver.GetTotalSpaceSize(out totalSpace, in path).Ret();
} }
public override bool IsSaveDataFileSystemCacheEnabled() public override bool IsSaveDataFileSystemCacheEnabled()
{ {
throw new NotImplementedException(); return false;
} }
public override Result RollbackOnlyModified() public override Result RollbackOnlyModified()
{ {
throw new NotImplementedException(); return ResultFs.UnsupportedRollbackOnlyModifiedForApplicationTemporaryFileSystem.Log();
} }
protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute)
{ {
throw new NotImplementedException(); return _saveFsDriver.GetFileSystemAttribute(out outAttribute).Ret();
} }
public override Result WriteExtraData(in SaveDataExtraData extraData) public override Result WriteExtraData(in SaveDataExtraData extraData)
{ {
throw new NotImplementedException(); return _saveFsDriver.WriteExtraData(in Unsafe.As<SaveDataExtraData, IntegritySaveDataFileSystem.ExtraData>(ref Unsafe.AsRef(in extraData))).Ret();
} }
public override Result CommitExtraData(bool updateTimeStamp) public override Result CommitExtraData(bool updateTimeStamp)
{ {
throw new NotImplementedException(); return DoCommit().Ret();
} }
public override Result ReadExtraData(out SaveDataExtraData extraData) public override Result ReadExtraData(out SaveDataExtraData extraData)
{ {
throw new NotImplementedException(); UnsafeHelpers.SkipParamInit(out extraData);
_saveFsDriver.ReadExtraData(out Unsafe.As<SaveDataExtraData, IntegritySaveDataFileSystem.ExtraData>(ref extraData));
return Result.Success;
} }
public override void RegisterExtraDataAccessorObserver(ISaveDataExtraDataAccessorObserver observer, SaveDataSpaceId spaceId, public override void RegisterExtraDataAccessorObserver(ISaveDataExtraDataAccessorObserver observer, SaveDataSpaceId spaceId,
ulong saveDataId) ulong saveDataId)
{ {
throw new NotImplementedException(); _cacheObserver = observer;
_spaceId = spaceId;
_saveDataId = saveDataId;
} }
} }

View file

@ -66,7 +66,7 @@ public class IntegritySaveDataFileSystemDriver : ProxyFileSystemWithRetryingBuff
throw new NotImplementedException(); throw new NotImplementedException();
} }
public void WriteExtraData(in IntegritySaveDataFileSystem.ExtraData extraData) public Result WriteExtraData(in IntegritySaveDataFileSystem.ExtraData extraData)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }