diff --git a/src/LibHac/Common/FixedArrays/Arrays.cs b/src/LibHac/Common/FixedArrays/Arrays.cs index c2b32ef6..64cf3016 100644 --- a/src/LibHac/Common/FixedArrays/Arrays.cs +++ b/src/LibHac/Common/FixedArrays/Arrays.cs @@ -25,14 +25,18 @@ namespace LibHac.Common.FixedArrays; [InlineArray(36)] public struct Array36 { public readonly int Length => 36; private T _0; } [InlineArray(37)] public struct Array37 { public readonly int Length => 37; private T _0; } [InlineArray(38)] public struct Array38 { public readonly int Length => 38; private T _0; } +[InlineArray(44)] public struct Array44 { public readonly int Length => 44; private T _0; } [InlineArray(48)] public struct Array48 { public readonly int Length => 48; private T _0; } [InlineArray(56)] public struct Array56 { public readonly int Length => 56; private T _0; } [InlineArray(60)] public struct Array60 { public readonly int Length => 60; private T _0; } [InlineArray(64)] public struct Array64 { public readonly int Length => 64; private T _0; } [InlineArray(65)] public struct Array65 { public readonly int Length => 65; private T _0; } [InlineArray(68)] public struct Array68 { public readonly int Length => 68; private T _0; } +[InlineArray(80)] public struct Array80 { public readonly int Length => 80; private T _0; } [InlineArray(100)] public struct Array100 { public readonly int Length => 100; private T _0; } +[InlineArray(104)] public struct Array104 { public readonly int Length => 104; private T _0; } [InlineArray(112)] public struct Array112 { public readonly int Length => 112; private T _0; } +[InlineArray(120)] public struct Array120 { public readonly int Length => 120; private T _0; } [InlineArray(128)] public struct Array128 { public readonly int Length => 128; private T _0; } [InlineArray(144)] public struct Array144 { public readonly int Length => 144; private T _0; } [InlineArray(192)] public struct Array192 { public readonly int Length => 192; private T _0; } @@ -43,8 +47,12 @@ namespace LibHac.Common.FixedArrays; [InlineArray(452)] public struct Array452 { public readonly int Length => 452; private T _0; } [InlineArray(464)] public struct Array464 { public readonly int Length => 464; private T _0; } [InlineArray(512)] public struct Array512 { public readonly int Length => 512; private T _0; } +[InlineArray(640)] public struct Array640 { public readonly int Length => 640; private T _0; } [InlineArray(768)] public struct Array768 { public readonly int Length => 768; private T _0; } [InlineArray(769)] public struct Array769 { public readonly int Length => 769; private T _0; } [InlineArray(3000)] public struct Array3000 { public readonly int Length => 3000; private T _0; } +[InlineArray(3438)] public struct Array3438 { public readonly int Length => 3438; private T _0; } +[InlineArray(5366)] public struct Array5366 { public readonly int Length => 5366; private T _0; } +[InlineArray(8000)] public struct Array8000 { public readonly int Length => 8000; private T _0; } [InlineArray(8192)] public struct Array8192 { public readonly int Length => 8192; private T _0; } [InlineArray(16384)] public struct Array16384 { public readonly int Length => 16384; private T _0; } \ No newline at end of file diff --git a/src/LibHac/Crypto/AesGcmDecryptor.cs b/src/LibHac/Crypto/AesGcmDecryptor.cs new file mode 100644 index 00000000..b1a5542f --- /dev/null +++ b/src/LibHac/Crypto/AesGcmDecryptor.cs @@ -0,0 +1,11 @@ +using System; + +namespace LibHac.Crypto; + +public class Aes128GcmDecryptor : IDisposable +{ + public void Dispose() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Crypto/AesGcmEncryptor.cs b/src/LibHac/Crypto/AesGcmEncryptor.cs new file mode 100644 index 00000000..68a2c480 --- /dev/null +++ b/src/LibHac/Crypto/AesGcmEncryptor.cs @@ -0,0 +1,11 @@ +using System; + +namespace LibHac.Crypto; + +public class Aes128GcmEncryptor : IDisposable +{ + public void Dispose() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Common/SaveDataTypes.cs b/src/LibHac/Fs/Common/SaveDataTypes.cs index 23631140..bd635a39 100644 --- a/src/LibHac/Fs/Common/SaveDataTypes.cs +++ b/src/LibHac/Fs/Common/SaveDataTypes.cs @@ -1,4 +1,5 @@ -using System; +#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value +using System; using System.Diagnostics.CodeAnalysis; using LibHac.Common; using LibHac.Common.FixedArrays; diff --git a/src/LibHac/Fs/Dbm/AllocationTable.cs b/src/LibHac/Fs/Dbm/AllocationTable.cs new file mode 100644 index 00000000..6e92a228 --- /dev/null +++ b/src/LibHac/Fs/Dbm/AllocationTable.cs @@ -0,0 +1,195 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; + +namespace LibHac.Fs.Dbm; + +public class AllocationTable : IDisposable +{ + private ValueSubStorage _storage; + private uint _blockCount; + + private struct TableElement + { + public uint Prev; + public uint Next; + + public readonly bool IsChainChild() => throw new NotImplementedException(); + + public readonly bool IsChainParent() => throw new NotImplementedException(); + + public readonly bool IsFreeListEmpty() => throw new NotImplementedException(); + + public readonly bool IsListHead() => throw new NotImplementedException(); + + public readonly bool IsSingleParent() => throw new NotImplementedException(); + + public readonly bool IsTailParent() => throw new NotImplementedException(); + + public void SetChainChild(uint startIndex, uint chainLength) + { + throw new NotImplementedException(); + } + + public void SetChainParent(uint prevSector, uint nextSector, bool isChainParent) + { + throw new NotImplementedException(); + } + + public void SetListFreeHeader() + { + throw new NotImplementedException(); + } + + public void SetListHead(uint nextSectorIndex, bool isChainParent) + { + throw new NotImplementedException(); + } + } + + public AllocationTable() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public static long QuerySize(uint blockCount) + { + throw new NotImplementedException(); + } + + public static Result Format(in ValueSubStorage storage, uint blockCount) + { + throw new NotImplementedException(); + } + + public static Result Expand(in ValueSubStorage storage, uint oldBlockCount, uint newBlockCount) + { + throw new NotImplementedException(); + } + + public void Initialize(in ValueSubStorage storage, uint blockCount) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public uint GetBlockCount() + { + throw new NotImplementedException(); + } + + public Result Invalidate() + { + throw new NotImplementedException(); + } + + public Result Allocate(out uint outIndex, uint blockCount) + { + throw new NotImplementedException(); + } + + public Result Free(uint index) + { + throw new NotImplementedException(); + } + + public Result ReadNext(out uint outNextIndex, out uint outBlockCount, uint index) + { + throw new NotImplementedException(); + } + + public Result ReadPrevious(out uint outPrevIndex, out uint outBlockCount, uint index) + { + throw new NotImplementedException(); + } + + private uint GetReadBlockCount(uint sectorIndex) + { + throw new NotImplementedException(); + } + + public Result CalcTotalBlockCount(out uint outBlockCount, uint startIndex) + { + throw new NotImplementedException(); + } + + public Result LookupTailParentCount(out uint outTailIndex, uint index) + { + throw new NotImplementedException(); + } + + public Result Concat(uint list1Index, uint list2Index) + { + throw new NotImplementedException(); + } + + public Result Split(out uint outIndexAfter, uint index, uint count) + { + throw new NotImplementedException(); + } + + public Result ReadFreeListHead(out uint outIndex) + { + throw new NotImplementedException(); + } + + public Result CalcFreeListLength(out uint outCount) + { + throw new NotImplementedException(); + } + + private uint ConvertIndexToSector(uint index) + { + throw new NotImplementedException(); + } + + private uint ConvertSectorToIndex(uint sector) + { + throw new NotImplementedException(); + } + + private Result ReadBlock(out TableElement outDst, uint sectorIndex, uint blockCount) + { + throw new NotImplementedException(); + } + + private Result WriteBlock(in TableElement source, uint sectorIndex, uint nextSectorIndex) + { + throw new NotImplementedException(); + } + + private Result UpdatePrevious(in TableElement source, uint sectorIndex, uint previousSectorIndex) + { + throw new NotImplementedException(); + } + + private Result UpdateChain(uint headSector, uint parentSector, uint lastSector, uint prevSector, uint nextSector) + { + throw new NotImplementedException(); + } + + private Result ReadFreeList(out TableElement outFreeList) + { + throw new NotImplementedException(); + } + + private Result AllocateFreeSector(out uint outSector, out uint outBlockCount, ref TableElement freeListHeader, + uint blockCount) + { + throw new NotImplementedException(); + } + + private Result UpdateFreeList(in TableElement freeList) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/AllocationTableStorage.cs b/src/LibHac/Fs/Dbm/AllocationTableStorage.cs new file mode 100644 index 00000000..908fde38 --- /dev/null +++ b/src/LibHac/Fs/Dbm/AllocationTableStorage.cs @@ -0,0 +1,99 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; + +namespace LibHac.Fs.Dbm; + +public class AllocationTableStorage : IStorage +{ + private const int MinBlockSize = 2; + + private AllocationTable _allocationTable; + private ValueSubStorage _dataStorage; + private int _startIndex; + private uint _blockSizeShift; + private int _blockOffset; + private int _index; + private uint _blockCount; + private uint _nextIndex; + + public AllocationTableStorage() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected uint GetBlockSizeShift() + { + throw new NotImplementedException(); + } + + public long GetBlockSize() + { + throw new NotImplementedException(); + } + + public long GetBlockSize(uint blockCount) + { + throw new NotImplementedException(); + } + + public Result Initialize(AllocationTable allocationTable, uint blockIndex, long blockSize, in ValueSubStorage dataStorage) + { + throw new NotImplementedException(); + } + + public virtual void FinalizeObject() + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + + public Result AllocateBlock(uint blockCount) + { + throw new NotImplementedException(); + } + + protected Result SeekTo(out uint outIndex, out uint outBlockCount, out long outOffset, long offset) + { + throw new NotImplementedException(); + } + + protected Result SeekToTop() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/BufferedAllocationTableStorage.cs b/src/LibHac/Fs/Dbm/BufferedAllocationTableStorage.cs new file mode 100644 index 00000000..ef1d2224 --- /dev/null +++ b/src/LibHac/Fs/Dbm/BufferedAllocationTableStorage.cs @@ -0,0 +1,112 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using System.Collections.Generic; +using LibHac.Common.FixedArrays; +using Buffer = LibHac.Mem.Buffer; + +namespace LibHac.Fs.Dbm; + +file static class Anonymous +{ + public static bool Overlaps(long offset1, long size1, long offset2, long size2) + { + return offset1 < offset2 + size2 && offset2 < offset1 + size1; + } +} + +public class BufferedAllocationTableStorage : AllocationTableStorage +{ + public struct CacheEntry + { + public Buffer Buffer; + public long Offset; + public long Handle; + } + + public struct CacheEntriesNode + { + public (ulong, ulong) MemoryRange; + public Array16 Entries; + } + + private LinkedList _cacheEntriesList; + private int _enableCount; + private IBufferManager _bufferManager; + + public BufferedAllocationTableStorage() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public Result InitializeBuffered(AllocationTable allocationTable, uint index, long blockSize, + in ValueSubStorage dataStorage, IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public override void FinalizeObject() + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + + private void UpdateCache(long offset, ReadOnlySpan buffer) + { + throw new NotImplementedException(); + } + + private void InvalidateCache(long offset, long size) + { + throw new NotImplementedException(); + } + + private void DeallocateCache(ref CacheEntry cache) + { + throw new NotImplementedException(); + } + + private void AcquireCacheBuffer(out CacheEntry outCache) + { + throw new NotImplementedException(); + } + + private void ExtendCacheLife(LinkedListNode iterator, int index) + { + throw new NotImplementedException(); + } + + public void EnterHoldingCacheSection() + { + throw new NotImplementedException(); + } + + public void LeaveHoldingCacheSection() + { + throw new NotImplementedException(); + } + + private LinkedListNode AllocateCacheEntries() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/DbmPathTool.cs b/src/LibHac/Fs/Dbm/DbmPathTool.cs new file mode 100644 index 00000000..8d796819 --- /dev/null +++ b/src/LibHac/Fs/Dbm/DbmPathTool.cs @@ -0,0 +1,155 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common.FixedArrays; + +namespace LibHac.Fs.Dbm; + +public struct DirectoryName +{ + public Array64 Text; +} + +public struct FileName +{ + public Array64 Text; +} + +file static class Anonymous +{ + public static void CopyAsDirectoryName(ref DirectoryName destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public static void CopyAsFileName(ref FileName destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public static void CopyAsImpl(Span destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public static ulong GetLengthImpl(ReadOnlySpan path) + { + throw new NotImplementedException(); + } +} + +public class PathTool +{ + public static bool IsSeparator(byte c) + { + throw new NotImplementedException(); + } + + public static bool IsCurrentDirectory(ReadOnlySpan path) + { + throw new NotImplementedException(); + } + + public static bool IsParentDirectory(ReadOnlySpan path) + { + throw new NotImplementedException(); + } + + public static bool IsCurrentDirectory(in DirectoryName name, ulong length) + { + throw new NotImplementedException(); + } + + public static bool IsParentDirectory(in DirectoryName name, ulong length) + { + throw new NotImplementedException(); + } + + public static bool IsEqualDirectoryName(in DirectoryName directoryName1, in DirectoryName directoryName2) + { + throw new NotImplementedException(); + } + + public static bool IsEqualFileName(in FileName fileName1, in FileName fileName2) + { + throw new NotImplementedException(); + } + + public static ulong GetDirectoryNameLength(in DirectoryName name) + { + throw new NotImplementedException(); + } + + public static bool GetDirectoryName(ref DirectoryName outName, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public static ulong GetFileNameLength(in FileName name) + { + throw new NotImplementedException(); + } + + public static bool GetFileName(ref FileName outName, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public static bool ConvertDirectoryNameToFileName(ref FileName outFileName, in DirectoryName directoryName) + { + throw new NotImplementedException(); + } + + public static bool ConvertFileNameToDirectoryName(ref DirectoryName outDirectoryName, in FileName fileName) + { + throw new NotImplementedException(); + } + + public ref struct PathParser + { + private ref byte _previousStartPath; + private ref byte _previousEndPath; + private ref byte _nextPath; + private bool _isParseFinished; + + public PathParser() + { + throw new NotImplementedException(); + } + + public Result Initialize(ReadOnlySpan fullPath) + { + throw new NotImplementedException(); + } + + public Result FinalizeObject() + { + throw new NotImplementedException(); + } + + public readonly bool IsParseFinished() + { + throw new NotImplementedException(); + } + + public readonly bool IsDirectoryPath() + { + throw new NotImplementedException(); + } + + public Result GetNextDirectoryName(ref DirectoryName outDirectoryName, out ulong outDirectoryNameLength) + { + throw new NotImplementedException(); + } + + public readonly Result GetAsDirectoryName(ref DirectoryName outName, out ulong outNameLength) + { + throw new NotImplementedException(); + } + + public readonly Result GetAsFileName(ref FileName outName, out ulong outNameLength) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/DirectoryObjectTemplate.cs b/src/LibHac/Fs/Dbm/DirectoryObjectTemplate.cs new file mode 100644 index 00000000..9852324b --- /dev/null +++ b/src/LibHac/Fs/Dbm/DirectoryObjectTemplate.cs @@ -0,0 +1,62 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs.Dbm.Impl; + +namespace LibHac.Fs.Dbm; + +public class DirectoryObjectTemplate + where TDirName : unmanaged + where TFileName : unmanaged +{ + private FileSystemObjectTemplate _fileSystem; + private DirectoryInfo _directoryInfo; + private HierarchicalFileTableTemplate.DirectoryKey _directoryKey; + private HierarchicalFileTableTemplate.FindIndex _findIndex; + + public DirectoryObjectTemplate() + { + throw new NotImplementedException(); + } + + public Result CountFile(out uint outCount) + { + throw new NotImplementedException(); + } + + public Result CountDirectory(out uint outCount) + { + throw new NotImplementedException(); + } + + public Result FindNextDirectory(out TDirName outDirectoryName, out bool outIsFinished) + { + throw new NotImplementedException(); + } + + public Result FindNextFile(out long outFileSize, out TFileName outFileName, out bool outIsFinished) + { + throw new NotImplementedException(); + } + + public Result FindOpen() + { + throw new NotImplementedException(); + } + + internal ref DirectoryInfo GetDirectoryInfo() + { + throw new NotImplementedException(); + } + + public Result Notify(out bool outIsFinished, long id, bool isFile) + { + throw new NotImplementedException(); + } + + internal void Initialize(FileSystemObjectTemplate fileSystem, + in HierarchicalFileTableTemplate.DirectoryKey directoryKey) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/FileObjectTemplate.cs b/src/LibHac/Fs/Dbm/FileObjectTemplate.cs new file mode 100644 index 00000000..632f5004 --- /dev/null +++ b/src/LibHac/Fs/Dbm/FileObjectTemplate.cs @@ -0,0 +1,50 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs.Dbm.Impl; +using IndexType = uint; + +namespace LibHac.Fs.Dbm; + +public class FileObjectTemplate + where TDirName : unmanaged + where TFileName : unmanaged +{ + private FileSystemObjectTemplate _fileSystem; + private uint _blockCount; + private FileInfo _fileInfo; + private HierarchicalFileTableTemplate.FileKey _fileKey; + private IndexType _previousIndex; + private IndexType _currentIndex; + + public FileObjectTemplate() + { + throw new NotImplementedException(); + } + + internal ref FileInfo GetFileInfo() + { + throw new NotImplementedException(); + } + + public long GetSize() + { + throw new NotImplementedException(); + } + + public Result Resize(long newSize) + { + throw new NotImplementedException(); + } + + public Result IterateBegin(out IndexType outIndex, out bool outFinished, IndexType startIndex) + { + throw new NotImplementedException(); + } + + internal void Initialize(FileSystemObjectTemplate fileSystem, + in HierarchicalFileTableTemplate.FileKey key) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/FileSystemControlArea.cs b/src/LibHac/Fs/Dbm/FileSystemControlArea.cs new file mode 100644 index 00000000..9f496ff7 --- /dev/null +++ b/src/LibHac/Fs/Dbm/FileSystemControlArea.cs @@ -0,0 +1,105 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; + +namespace LibHac.Fs.Dbm; + +public class FileSystemControlArea : IDisposable +{ + private ValueSubStorage _storage; + + public FileSystemControlArea() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public void Initialize(in ValueSubStorage storage) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public void ExpandAllocationTableInfo(uint newBlockCount) + { + throw new NotImplementedException(); + } + + private Result WriteStorageInfo(long offset, uint size, uint controlAreaOffset) + { + throw new NotImplementedException(); + } + + private Result ReadStorageInfo(out long outOffset, out uint outSize, uint controlAreaOffset) + { + throw new NotImplementedException(); + } + + private Result WriteAllocationInfo(uint index, uint controlAreaOffset) + { + throw new NotImplementedException(); + } + + private Result ReadAllocationInfo(out uint outIndex, uint controlAreaOffset) + { + throw new NotImplementedException(); + } + + public Result ReadAllocationTableInfo(out long outOffset, out uint outSize) + { + throw new NotImplementedException(); + } + + public Result ReadBlockSize(out long outBlockSize) + { + throw new NotImplementedException(); + } + + public Result ReadDataBodyInfo(out long outOffset, out uint outSize) + { + throw new NotImplementedException(); + } + + public Result WriteAllocationTableInfo(long offset, uint size) + { + throw new NotImplementedException(); + } + + public Result WriteDataBodyInfo(long offset, uint size) + { + throw new NotImplementedException(); + } + + public Result ReadDirectoryEntryInfo(out uint outIndex) + { + throw new NotImplementedException(); + } + + public Result ReadFileEntryInfo(out uint outIndex) + { + throw new NotImplementedException(); + } + + public Result WriteBlockSize(long size) + { + throw new NotImplementedException(); + } + + public Result WriteDirectoryEntryInfo(uint index) + { + throw new NotImplementedException(); + } + + public Result WriteFileEntryInfo(uint index) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/FileSystemObjectTemplate.cs b/src/LibHac/Fs/Dbm/FileSystemObjectTemplate.cs new file mode 100644 index 00000000..6b808e9f --- /dev/null +++ b/src/LibHac/Fs/Dbm/FileSystemObjectTemplate.cs @@ -0,0 +1,91 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs.Dbm.Impl; +using IndexType = uint; + +namespace LibHac.Fs.Dbm; + +public class FileSystemObjectTemplate + where TDirName : unmanaged + where TFileName : unmanaged +{ + private HierarchicalFileTableTemplate _fileTable; + private AllocationTable _allocationTable; + private long _blockSize; + private uint _blockSizeShift; + + public FileSystemObjectTemplate() + { + throw new NotImplementedException(); + } + + public Result Initialize(AllocationTable allocationTable, long blockSize, + BufferedAllocationTableStorage directoryEntries, BufferedAllocationTableStorage fileEntries) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result CreateDirectory(U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result OpenDirectory(out IndexType outIndex, out DirectoryObjectTemplate outDirectory, + U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result OpenDirectory(out DirectoryObjectTemplate outDirectory, U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result CreateFile(out IndexType outIndex, U8Span fullPath, in FileOptionalInfo optionalInfo) + { + throw new NotImplementedException(); + } + + public Result DeleteFile(U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result OpenFile(out IndexType outIndex, ref FileObjectTemplate file, U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result OpenFile(ref FileObjectTemplate file, U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result GetEntryType(out DirectoryEntryType outEntryType, U8Span fullPath) + { + throw new NotImplementedException(); + } + + private uint RoundUpBlockSize(long size) + { + throw new NotImplementedException(); + } + + private Result ResizeFile(ref FileInfo fileInfo, + in HierarchicalFileTableTemplate.DirectoryKey key, long newSize) + { + throw new NotImplementedException(); + } + + private Result GetNextAllocationBlock(out IndexType outNextIndex, out uint outBlockCount, IndexType index) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/FileTableTypes.cs b/src/LibHac/Fs/Dbm/FileTableTypes.cs new file mode 100644 index 00000000..e8d1bd3a --- /dev/null +++ b/src/LibHac/Fs/Dbm/FileTableTypes.cs @@ -0,0 +1,24 @@ +using LibHac.Common.FixedArrays; + +namespace LibHac.Fs.Dbm +{ + public struct FileOptionalInfo + { + public Array8 Data; + } +} + +namespace LibHac.Fs.Dbm.Impl +{ + public struct FileInfo + { + public uint BlockIndex; + public Int64 Size; + public FileOptionalInfo OptionalInfo; + } + + public struct DirectoryInfo + { + public Array12 Data; + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/HierarchicalFileTableTemplate.cs b/src/LibHac/Fs/Dbm/HierarchicalFileTableTemplate.cs new file mode 100644 index 00000000..7ced2249 --- /dev/null +++ b/src/LibHac/Fs/Dbm/HierarchicalFileTableTemplate.cs @@ -0,0 +1,287 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using IndexType = uint; + +namespace LibHac.Fs.Dbm; + +public class HierarchicalFileTableTemplate + where TDirName : unmanaged + where TFileName : unmanaged + where TDirInfo : unmanaged + where TFileInfo : unmanaged +{ + protected const IndexType IndexNone = 0; + private const int AllocationTableStorageReservedCount = 2; + + public struct ScopedHoldingCacheSection : IDisposable + { + private HierarchicalFileTableTemplate _fileTable; + + public ScopedHoldingCacheSection(HierarchicalFileTableTemplate fileTable) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + } + + public struct FindIndex + { + public IndexType NextDirectory; + public IndexType NextFile; + } + + public struct DirectoryKey + { + public IndexType ParentIndex; + public TDirName Name; + + public static bool operator ==(in DirectoryKey left, in DirectoryKey right) + { + throw new NotImplementedException(); + } + + public static bool operator !=(in DirectoryKey left, in DirectoryKey right) + { + throw new NotImplementedException(); + } + } + + public struct FileKey + { + public IndexType ParentIndex; + public TFileName Name; + + public static bool operator ==(in FileKey left, in FileKey right) + { + throw new NotImplementedException(); + } + + public static bool operator !=(in FileKey left, in FileKey right) + { + throw new NotImplementedException(); + } + } + + public struct DirectoryEntry + { + public IndexType IndexNextSibling; + public IndexType IndexDirectory; + public IndexType IndexFile; + public TDirInfo Info; + } + + public struct FileEntry + { + public IndexType IndexNextSibling; + public TFileInfo Info; + } + + public class EntryList : KeyValueListTemplate + where TKey : unmanaged where TEntry : unmanaged + { + public EntryList() + { + throw new NotImplementedException(); + } + + public Result Add(out uint outIndex, in TKey key, in TEntry entry) + { + throw new NotImplementedException(); + } + + public Result Get(out uint outIndex, out TEntry outEntry, in TKey key) + { + throw new NotImplementedException(); + } + + public new Result GetByIndex(out TKey outKey, out TEntry outEntry, uint index) + { + throw new NotImplementedException(); + } + + public new Result Remove(in TKey key) + { + throw new NotImplementedException(); + } + + public Result Rename(in TKey newKey, in TKey oldKey) + { + throw new NotImplementedException(); + } + + protected new Result SetByIndex(uint index, in TEntry entry) + { + throw new NotImplementedException(); + } + } + + private EntryList _directoryList; + private EntryList _fileList; + + public HierarchicalFileTableTemplate() + { + throw new NotImplementedException(); + } + + public static uint QueryDirectoryEntryStorageSize(uint entryCount) + { + throw new NotImplementedException(); + } + + public static uint QueryFileEntryStorageSize(uint entryCount) + { + throw new NotImplementedException(); + } + + public static Result Format(BufferedAllocationTableStorage directoryEntries, + BufferedAllocationTableStorage fileEntries) + { + throw new NotImplementedException(); + } + + public Result Initialize(BufferedAllocationTableStorage directoryEntries, + BufferedAllocationTableStorage fileEntries) + { + throw new NotImplementedException(); + } + + public Result CreateDirectory(U8Span fullPath, in TDirInfo directoryInfo) + { + throw new NotImplementedException(); + } + + public Result CreateFile(U8Span fullPath, in TDirInfo directoryInfo) + { + throw new NotImplementedException(); + } + + public Result DeleteDirectory(U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result DeleteFile(U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result RenameDirectory(out bool outIsFile, out bool outIsSameEntry, out bool outIsParentEntry, + U8Span newFullPath, U8Span oldFullPath) + { + throw new NotImplementedException(); + } + + public Result RenameFile(out bool outIsFile, out bool outIsSameEntry, U8Span newFullPath, U8Span oldFullPath) + { + throw new NotImplementedException(); + } + + public Result OpenFile(out IndexType outIndex, out TFileInfo outFileInfo, U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result OpenFile(out TFileInfo outFileInfo, U8Span fullPath) + { + throw new NotImplementedException(); + } + + public Result FindNextDirectory(out TDirName outDirectoryName, out bool outIsFinished, ref FindIndex iterator) + { + throw new NotImplementedException(); + } + + public Result FindNextFile(out long outFileSize, out TFileName outFileName, out bool outIsFinished, + ref FindIndex iterator) + { + throw new NotImplementedException(); + } + + protected Result FindDirectoryRecursive(out DirectoryKey outParentDirectoryKey, + out DirectoryEntry outParentDirectoryEntry, out DirectoryKey outDirectoryKey, U8Span fullPath) + { + throw new NotImplementedException(); + } + + protected Result FindFileRecursive(out DirectoryKey outParentDirectoryKey, + out DirectoryEntry outParentDirectoryEntry, out FileKey outFileKey, U8Span fullPath) + { + throw new NotImplementedException(); + } + + protected Result GetDirectoryInformationFromKey(out IndexType outIndex, out TDirInfo outDirectoryInfo, + in DirectoryKey key) + { + throw new NotImplementedException(); + } + + protected Result OpenFileFromKey(out IndexType outIndex, out TFileInfo outFileInfo, in FileKey key) + { + throw new NotImplementedException(); + } + + protected Result UpdateFileInformationFromKey(in FileKey key, in TFileInfo fileInfo) + { + throw new NotImplementedException(); + } + + protected Result FindOpenWithKey(ref FindIndex iterator, in DirectoryKey key) + { + throw new NotImplementedException(); + } + + public Result CheckSubEntry(out bool isSubEntry, IndexType baseEntryIndex, IndexType entryIndexToCheck, bool isFile) + { + throw new NotImplementedException(); + } + + protected Result Notify(out bool outIsFinished, ref FindIndex iterator, long id, bool isFile) + { + throw new NotImplementedException(); + } + + private Result FindParentDirectoryRecursive(out FindIndex outParentIndex, out DirectoryKey outParentDirectoryKey, + out DirectoryEntry outParentDirectoryEntry, ref PathTool.PathParser pathParser) + { + throw new NotImplementedException(); + } + + private Result CheckSameEntryExists(out bool outIsFile, IndexType parentIndex, U8Span name, Result resultIfExists) + { + throw new NotImplementedException(); + } + + private Result GetDirectoryEntry(out IndexType outIndex, out DirectoryEntry outEntry, in DirectoryKey key) + { + throw new NotImplementedException(); + } + + private Result GetFileEntry(out IndexType outIndex, out FileEntry outEntry, in FileKey key) + { + throw new NotImplementedException(); + } + + private Result RemoveDirectoryLink(ref DirectoryEntry parentEntry, IndexType parentIndex, + ref DirectoryEntry deleteEntry, IndexType deleteIndex) + { + throw new NotImplementedException(); + } + + private Result RemoveFileLink(ref DirectoryEntry parentEntry, IndexType parentIndex, + ref FileEntry deleteEntry, IndexType deleteIndex) + { + throw new NotImplementedException(); + } + + private Result CheckSubDirectory(in DirectoryKey baseDirectoryKey, in DirectoryKey directoryKeyToCheck, + Result resultIfSubDirectory) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Dbm/KeyValueListTemplate.cs b/src/LibHac/Fs/Dbm/KeyValueListTemplate.cs new file mode 100644 index 00000000..c1f25ae7 --- /dev/null +++ b/src/LibHac/Fs/Dbm/KeyValueListTemplate.cs @@ -0,0 +1,144 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; + +namespace LibHac.Fs.Dbm; + +public class KeyValueListTemplate where TKey : unmanaged where TValue : unmanaged +{ + private BufferedAllocationTableStorage _keyValueStorage; + private uint _maxCount; + + public struct FormatInformation + { + public uint IndexLimitation; + public uint IndexNotFormatted; + + public static ref FormatInformation GetFromStorageElement(ref StorageElement element) + { + throw new NotImplementedException(); + } + } + + public struct StorageElement + { + public TKey Key; + public TValue Value; + public uint NextIndex; + } + + public KeyValueListTemplate() + { + throw new NotImplementedException(); + } + + public static uint QueryEntryCount(long storageSize) + { + throw new NotImplementedException(); + } + + public static uint QueryStorageSize(uint entryCount) + { + throw new NotImplementedException(); + } + + public static Result Format(AllocationTableStorage storage) + { + throw new NotImplementedException(); + } + + public Result Initialize(BufferedAllocationTableStorage keyValueStorage) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result GetMaxCount(out uint outCount) + { + throw new NotImplementedException(); + } + + public Result Remove(in TKey key) + { + throw new NotImplementedException(); + } + + public Result ModifyKey(in TKey newKey, in TKey oldKey) + { + throw new NotImplementedException(); + } + + public void EnterHoldingCacheSection() + { + throw new NotImplementedException(); + } + + public void LeaveHoldingCacheSection() + { + throw new NotImplementedException(); + } + + protected Result AddInternal(out uint outIndex, in TKey key, in TValue value) + { + throw new NotImplementedException(); + } + + protected Result GetInternal(out uint outIndex, out TValue outValue, in TKey key) + { + throw new NotImplementedException(); + } + + protected Result GetByIndex(out TKey outKey, out TValue outValue, uint index) + { + throw new NotImplementedException(); + } + + protected Result SetByIndex(uint index, in TValue value) + { + throw new NotImplementedException(); + } + + private Result ReadKeyValue(out StorageElement outElement, uint index) + { + throw new NotImplementedException(); + } + + private Result ReadKeyValue(Span outElements, uint index, uint count) + { + throw new NotImplementedException(); + } + + private Result ReadKeyValueImpl(ref StorageElement outElement, uint index) + { + throw new NotImplementedException(); + } + + private Result WriteKeyValue(in StorageElement element, uint index) + { + throw new NotImplementedException(); + } + + private Result FindInternal(out uint outIndex, out uint outPreviousIndex, out StorageElement outElement, in TKey key) + { + throw new NotImplementedException(); + } + + private Result AllocateEntry(out uint outEntryIndex) + { + throw new NotImplementedException(); + } + + private Result LinkEntry(out uint outOldNextIndex, uint index, uint nextIndex) + { + throw new NotImplementedException(); + } + + private Result FreeEntry(uint index) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Impl/SaveDataTransferTypes.cs b/src/LibHac/Fs/Impl/SaveDataTransferTypes.cs index 1d4e6750..c082635f 100644 --- a/src/LibHac/Fs/Impl/SaveDataTransferTypes.cs +++ b/src/LibHac/Fs/Impl/SaveDataTransferTypes.cs @@ -1,4 +1,7 @@ -using LibHac.Common.FixedArrays; +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using LibHac.Common.FixedArrays; namespace LibHac.Fs.Impl; @@ -14,7 +17,10 @@ public struct KeySeed public struct InitialDataMac { - public Array16 Value; + private Array2 _value; + + [UnscopedRef] + public Span Value => MemoryMarshal.Cast(_value); } public struct ExportReportInfo diff --git a/src/LibHac/Fs/Save/ExclusiveFileSystem.cs b/src/LibHac/Fs/Save/ExclusiveFileSystem.cs new file mode 100644 index 00000000..f84cf745 --- /dev/null +++ b/src/LibHac/Fs/Save/ExclusiveFileSystem.cs @@ -0,0 +1,317 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs.Fsa; +using LibHac.Os; + +namespace LibHac.Fs.Save; + +public interface IExclusiveObject +{ + long GetId(); + IExclusiveObject GetNext(); + void SetId(long id); + void SetNext(IExclusiveObject nextObject); + + OpenMode GetMode(); + bool IsFile(); + Result NotifyDelete(long id, bool isFile); + void NotifyFileSystemDestructed(); +} + +// ReSharper disable once InconsistentNaming +public abstract class IExclusiveDirectoryBase : IDirectory +{ + public abstract Result NotifyDelete(long id, bool isFile); +} + +// ReSharper disable once InconsistentNaming +public abstract class IExclusiveFileBase : IFile +{ + public abstract OpenMode GetMode(); +} + +// ReSharper disable once InconsistentNaming +public abstract class IExclusiveFileSystemBase : IFileSystem +{ + public abstract Result OpenBaseFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode); + public abstract Result OpenBaseDirectory(ref UniqueRef outDirectory, ref readonly Path path, OpenDirectoryMode mode); + public abstract Result GetFileIdFromPath(out long outId, ref readonly Path path, bool isFile); + public abstract Result CheckSubEntry(out bool isSubEntry, long baseEntryId, long entryIdToCheck, bool isFile); +} + +public class ExclusiveFile : IFile, IExclusiveObject +{ + // Pasting the contents of IExclusiveObject directly in this class because C# doesn't have multiple inheritance. + private IExclusiveObject _next; + private long _id; + + public long GetId() => _id; + public IExclusiveObject GetNext() => _next; + public void SetId(long id) => _id = id; + public void SetNext(IExclusiveObject nextObject) => _next = nextObject; + + // Contents of ExclusiveFile + private ExclusiveFileSystem _fileSystem; + private UniqueRef _baseFile; + private SdkMutex _fileOperationLock; + + public ExclusiveFile(ref UniqueRef baseFile, long id, ExclusiveFileSystem fileSystem, + SdkMutex fileOperationLock) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public OpenMode GetMode() + { + throw new NotImplementedException(); + } + + public bool IsFile() + { + throw new NotImplementedException(); + } + + public Result NotifyDelete(long id, bool isFile) + { + throw new NotImplementedException(); + } + + public void NotifyFileSystemDestructed() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class ExclusiveDirectory : IDirectory, IExclusiveObject +{ + // Pasting the contents of IExclusiveObject directly in this class because C# doesn't have multiple inheritance. + private IExclusiveObject _next; + private long _id; + + public long GetId() => _id; + public IExclusiveObject GetNext() => _next; + public void SetId(long id) => _id = id; + public void SetNext(IExclusiveObject nextObject) => _next = nextObject; + + // Contents of ExclusiveDirectory + private ExclusiveFileSystem _fileSystem; + private UniqueRef _baseDirectory; + private SdkMutex _fileOperationLock; + + public ExclusiveDirectory(ref UniqueRef baseDirectory, long id, + ExclusiveFileSystem fileSystem, SdkMutex fileOperationLock) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public OpenMode GetMode() + { + throw new NotImplementedException(); + } + + public bool IsFile() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long entriesRead, Span entryBuffer) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryCount(out long entryCount) + { + throw new NotImplementedException(); + } + + public Result NotifyDelete(long id, bool isFile) + { + throw new NotImplementedException(); + } + + public void NotifyFileSystemDestructed() + { + throw new NotImplementedException(); + } +} + +public class ExclusiveFileSystem : IFileSystem +{ + private SdkMutex _lockObject; + private IExclusiveObject _openedObjects; + private IExclusiveFileSystemBase _baseFileSystem; + + public ExclusiveFileSystem() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(IExclusiveFileSystemBase baseFileSystem) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenDirectory(ref UniqueRef outDirectory, ref readonly Path path, OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteFile(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCleanDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCommit() + { + throw new NotImplementedException(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) + { + throw new NotImplementedException(); + } + + public bool HasOpenedFiles(int openMode) + { + throw new NotImplementedException(); + } + + public bool HasOpenedEntries(out bool outIsFirstEntryFile) + { + throw new NotImplementedException(); + } + + private Result CheckAccessPolicy(out long outId, ref readonly Path path, int openMode, bool isFile, bool checkSubEntries) + { + throw new NotImplementedException(); + } + + private Result CheckAccessPolicy(out long outId, out bool outDirectoryOpened, ref readonly Path path, int openMode, + bool isFile, bool checkSubEntries) + { + throw new NotImplementedException(); + } + + private bool CheckEntryExistence(ref readonly Path path) + { + throw new NotImplementedException(); + } + + private void LinkObject(IExclusiveObject obj) + { + throw new NotImplementedException(); + } + + private void UnlinkObject(IExclusiveObject obj) + { + throw new NotImplementedException(); + } + + private Result DeleteDirectoryRecursivelyInternal(ref readonly Path path, bool deleteRootDir) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Save/InternalStorageFilePath.cs b/src/LibHac/Fs/Save/InternalStorageFilePath.cs new file mode 100644 index 00000000..f40d8d17 --- /dev/null +++ b/src/LibHac/Fs/Save/InternalStorageFilePath.cs @@ -0,0 +1,34 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; + +namespace LibHac.Fs.Save; + +[NonCopyableDisposable] +public ref struct InternalStorageFilePath +{ + private Array64 _fileName; + private Path _path; + + public InternalStorageFilePath() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(U8Span fileName) + { + throw new NotImplementedException(); + } + + public readonly ref readonly Path GetPath() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Save/SaveDataFileSystemCore.cs b/src/LibHac/Fs/Save/SaveDataFileSystemCore.cs new file mode 100644 index 00000000..660ac333 --- /dev/null +++ b/src/LibHac/Fs/Save/SaveDataFileSystemCore.cs @@ -0,0 +1,151 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs.Fsa; +using LibHac.FsSystem.Save; + +namespace LibHac.Fs.Save; + +public class SaveDataFileSystemCore : IFileSystem +{ + private ExclusiveFileSystem _exclusiveFs; + private SaveDataFileSystemCoreImpl _saveFsImpl; + + public SaveDataFileSystemCore() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static long QueryDataSize(long blockSize, ulong blockCount) + { + throw new NotImplementedException(); + } + + public static long QueryMetaSize(long blockSize, ulong blockCount) + { + throw new NotImplementedException(); + } + + public static Result Format(in ValueSubStorage storageControlArea, in ValueSubStorage storageMeta, + in ValueSubStorage storageData, long blockSize, IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public static Result ExpandControlArea(in ValueSubStorage storageControlArea, long sizeDataNew) + { + throw new NotImplementedException(); + } + + public static Result ExpandMeta(in ValueSubStorage storageMeta, long blockSize, long sizeDataOld, long sizeDataNew) + { + throw new NotImplementedException(); + } + + public Result Initialize(in ValueSubStorage storageControlArea, in ValueSubStorage storageMeta, + in ValueSubStorage storageData, IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenDirectory(ref UniqueRef outDirectory, ref readonly Path path, OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteFile(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCleanDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCommit() + { + throw new NotImplementedException(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) + { + throw new NotImplementedException(); + } + + public bool HasOpenedFiles(int openMode) + { + throw new NotImplementedException(); + } + + public bool HasOpenedEntries(out bool outIsFirstEntryFile) + { + throw new NotImplementedException(); + } + + public Result AcceptVisitor(IInternalStorageFileSystemVisitor visitor) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Save/SaveDataFileSystemCoreImpl.cs b/src/LibHac/Fs/Save/SaveDataFileSystemCoreImpl.cs new file mode 100644 index 00000000..ceaa9480 --- /dev/null +++ b/src/LibHac/Fs/Save/SaveDataFileSystemCoreImpl.cs @@ -0,0 +1,307 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs.Dbm; +using LibHac.Fs.Fsa; +using LibHac.FsSystem.Save; + +namespace LibHac.Fs.Save; + +public class SaveDataFileSystemCoreImpl : IExclusiveFileSystemBase +{ + private ValueSubStorage _allocationTableControlAreaStorage; + private ValueSubStorage _allocationTableMetaStorage; + private FileSystemControlArea _controlArea; + private FileSystemObjectTemplate _fileSystem; + private BufferedAllocationTableStorage _directoryEntries; + private BufferedAllocationTableStorage _fileEntries; + private ValueSubStorage _allocationTableDataStorage; + private long _offset; + private uint _countBody; + private long _blockSize; + + public SaveDataFileSystemCoreImpl() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static long QueryDataSize(long blockSize, ulong blockCount) + { + throw new NotImplementedException(); + } + + public static long QueryMetaSize(long blockSize, ulong blockCount) + { + throw new NotImplementedException(); + } + + private static long QueryAllocationTableStorageSize(uint blockCount) + { + throw new NotImplementedException(); + } + + public static Result Format(in ValueSubStorage storageControlArea, in ValueSubStorage storageMeta, + in ValueSubStorage storageData, long blockSize, IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public static Result ExpandControlArea(in ValueSubStorage storageControlArea, long sizeDataNew) + { + throw new NotImplementedException(); + } + + public static Result ExpandMeta(in ValueSubStorage storageMeta, long blockSize, long sizeDataOld, long sizeDataNew) + { + throw new NotImplementedException(); + } + + public Result Initialize(in ValueSubStorage storageControlArea, in ValueSubStorage storageMeta, + in ValueSubStorage storageData, IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result CheckPathFormat(ref readonly Path path) + { + throw new NotImplementedException(); + } + + public override Result OpenBaseFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + public override Result OpenBaseDirectory(ref UniqueRef outDirectory, ref readonly Path path, + OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenDirectory(ref UniqueRef outDirectory, ref readonly Path path, + OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteFile(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCleanDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCommit() + { + throw new NotImplementedException(); + } + + protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) + { + throw new NotImplementedException(); + } + + private Result CalcFreeListLength(out uint outCount) + { + throw new NotImplementedException(); + } + + public static Result FormatDbmLayer(in ValueSubStorage storageControlArea, in ValueSubStorage storageMeta, + in ValueSubStorage storageData, long blockSize, uint blockCount, IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public override Result GetFileIdFromPath(out long outId, ref readonly Path path, bool isFile) + { + throw new NotImplementedException(); + } + + public override Result CheckSubEntry(out bool isSubEntry, long baseEntryId, long entryIdToCheck, bool isFile) + { + throw new NotImplementedException(); + } + + public Result AcceptVisitor(IInternalStorageFileSystemVisitor visitor) + { + throw new NotImplementedException(); + } +} + +public class SaveDataFileImpl : IExclusiveFileBase +{ + private FileObjectTemplate _fileObject; + private OpenMode _mode; + private AllocationTableStorage _allocationTableStorage; + private AllocationTable _allocationTable; + private ValueSubStorage _baseStorage; + private long _blockSize; + private long _offset; + private long _size; + + internal SaveDataFileImpl() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public override OpenMode GetMode() + { + throw new NotImplementedException(); + } + + private FileObjectTemplate GetFileObject() + { + throw new NotImplementedException(); + } + + private Result InitializeTable() + { + throw new NotImplementedException(); + } + + private Result Initialize(OpenMode mode, AllocationTable allocationTable, long blockSize, + in ValueSubStorage baseStorage, long offset, long size) + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class SaveDataDirectoryImpl : IExclusiveDirectoryBase +{ + private DirectoryObjectTemplate _directoryObject; + private OpenDirectoryMode _mode; + + internal SaveDataDirectoryImpl(OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + private DirectoryObjectTemplate GetDirectoryObject() + { + throw new NotImplementedException(); + } + + private Result Initialize() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long entriesRead, Span entryBuffer) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryCount(out long entryCount) + { + throw new NotImplementedException(); + } + + public override Result NotifyDelete(long id, bool isFile) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/SaveData.cs b/src/LibHac/Fs/SaveData.cs index 702a6a88..241507c1 100644 --- a/src/LibHac/Fs/SaveData.cs +++ b/src/LibHac/Fs/SaveData.cs @@ -1,7 +1,46 @@ -using LibHac.Ncm; +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Account; +using LibHac.Common; +using LibHac.Ncm; namespace LibHac.Fs; +file static class Anonymous +{ + public static Result EnsureSaveDataImpl(FileSystemClient fs, out long outRequiredSize, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result CreateCacheStorageImpl(FileSystemClient fs, out long outRequiredSize, + out CacheStorageTargetMedia outCacheStorageTargetMedia, ushort index, long cacheStorageSize, + long cacheStorageJournalSize) + { + throw new NotImplementedException(); + } + + public static Result ExtendSaveDataImpl(FileSystemClient fs, out long outRequiredSize, SaveDataType saveDataType, + in Uid user, long saveDataSize, long saveDataJournalSize) + { + throw new NotImplementedException(); + } + + public static Result GetSaveDataSizeImpl(FileSystemClient fs, out long outSaveDataSize, + out long saveDataJournalSize, SaveDataType saveDataType, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result ShowLibraryAppletDataErase(FileSystemClient fs, in Uid user, + CacheStorageTargetMedia cacheStorageTargetMedia, long requiredSize, Result errorResult, + SaveDataType saveDataType) + { + throw new NotImplementedException(); + } +} + public static class SaveData { public static readonly ulong SaveIndexerId = 0x8000000000000000; @@ -9,4 +48,100 @@ public static class SaveData public static ProgramId AutoResolveCallerProgramId => new ProgramId(ulong.MaxValue - 1); public static UserId InvalidUserId => default; public static ulong InvalidSystemSaveDataId => 0; + + public static Result MountSaveData(this FileSystemClient fs, U8Span mountName, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result MountSaveData(this FileSystemClient fs, U8Span mountName, ApplicationId applicationId, + in Uid user) + { + throw new NotImplementedException(); + } + + public static Result MountSaveDataReadOnly(this FileSystemClient fs, U8Span mountName, ApplicationId applicationId, + in Uid user) + { + throw new NotImplementedException(); + } + + public static bool IsSaveDataExisting(this FileSystemClient fs, in Uid user) + { + throw new NotImplementedException(); + } + + public static bool IsSaveDataExisting(this FileSystemClient fs, ApplicationId applicationId, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result IsSaveDataExisting(this FileSystemClient fs, out bool outIsExisting, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result IsSaveDataExisting(this FileSystemClient fs, ApplicationId applicationId, + out bool outIsExisting, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result EnsureSaveData(this FileSystemClient fs, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result EnsureDeviceSaveDataUnsafe(this FileSystemClient fs, ApplicationId applicationId, + long saveDataSize, long saveDataJournalSize) + { + throw new NotImplementedException(); + } + + public static void GetSaveDataSizeMax(this FileSystemClient fs, out long outSaveDataSizeMax, + out long outSaveDataJournalSizeMax) + { + throw new NotImplementedException(); + } + + public static void GetDeviceSaveDataSizeMax(this FileSystemClient fs, out long outSaveDataSizeMax, + out long outSaveDataJournalSizeMax) + { + throw new NotImplementedException(); + } + + public static Result ExtendSaveData(this FileSystemClient fs, in Uid user, long saveDataSize, + long saveDataJournalSize) + { + throw new NotImplementedException(); + } + + public static Result ExtendDeviceSaveData(this FileSystemClient fs, long saveDataSize, long saveDataJournalSize) + { + throw new NotImplementedException(); + } + + public static Result GetSaveDataSize(this FileSystemClient fs, out long outSaveDataSize, + out long outSaveDataJournalSize, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result GetDeviceSaveDataSize(this FileSystemClient fs, out long outSaveDataSize, + out long outSaveDataJournalSize) + { + throw new NotImplementedException(); + } + + public static void GetCacheStorageMax(this FileSystemClient fs, out int outCacheStorageIndexMax, + out long outCacheStorageDataAndJournalSizeMax) + { + throw new NotImplementedException(); + } + + public static Result CreateCacheStorage(this FileSystemClient fs, int index, long cacheStorageSize, + long cacheStorageJournalSize) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/src/LibHac/Fs/SaveDataThumbnail.cs b/src/LibHac/Fs/SaveDataThumbnail.cs new file mode 100644 index 00000000..80966a18 --- /dev/null +++ b/src/LibHac/Fs/SaveDataThumbnail.cs @@ -0,0 +1,36 @@ +using System; +using LibHac.Account; + +namespace LibHac.Fs; + +public static class SaveDataThumbnail +{ + public static Result ReadSaveDataThumbnailFile(this FileSystemClientImpl fs, ulong applicationId, in Uid uid, + Span headerBuffer, Span imageDataBuffer) + { + throw new NotImplementedException(); + } + + public static Result ReadSaveDataThumbnailFileHeader(this FileSystemClientImpl fs, ulong applicationId, in Uid uid, + Span headerBuffer) + { + throw new NotImplementedException(); + } + + public static Result WriteSaveDataThumbnailFile(this FileSystemClient fs, ulong applicationId, in Uid uid, + ReadOnlySpan headerBuffer, ReadOnlySpan imageDataBuffer) + { + throw new NotImplementedException(); + } + + public static Result WriteSaveDataThumbnailFileHeader(this FileSystemClient fs, ulong applicationId, in Uid uid, + ReadOnlySpan headerBuffer) + { + throw new NotImplementedException(); + } + + public static Result CorruptSaveDataThumbnailFileForDebug(this FileSystemClient fs, ulong applicationId, in Uid uid) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/SaveDataTransfer.cs b/src/LibHac/Fs/SaveDataTransfer.cs new file mode 100644 index 00000000..329d2c39 --- /dev/null +++ b/src/LibHac/Fs/SaveDataTransfer.cs @@ -0,0 +1,14 @@ +using System; +using LibHac.Account; +using LibHac.Common; + +namespace LibHac.Fs; + +public partial class SaveDataTransferManager +{ + public Result OpenSaveDataImporter(ref UniqueRef outImporter, out long outRequiredSize, + ReadOnlySpan initialData, in Uid user, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/SaveDataTransferForSaveDataRepair.cs b/src/LibHac/Fs/SaveDataTransferForSaveDataRepair.cs new file mode 100644 index 00000000..0a708ea6 --- /dev/null +++ b/src/LibHac/Fs/SaveDataTransferForSaveDataRepair.cs @@ -0,0 +1,27 @@ +using System; +using LibHac.Account; +using LibHac.Common; + +namespace LibHac.Fs; + +public partial class SaveDataTransferManagerForSaveDataRepair +{ + public Result OpenSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialDataBeforeRepair, in InitialDataVersion2 initialDataAfterRepair, in Uid user, + SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialDataBeforeRepair, in Uid user, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterWithKey(ref UniqueRef outExporter, in AesKey key, + in InitialDataVersion2 initialData, in Uid user, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/SaveDataTransferTypes.cs b/src/LibHac/Fs/SaveDataTransferTypes.cs index f65ff69f..4b7f894f 100644 --- a/src/LibHac/Fs/SaveDataTransferTypes.cs +++ b/src/LibHac/Fs/SaveDataTransferTypes.cs @@ -1,4 +1,7 @@ -using LibHac.Common.FixedArrays; +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using LibHac.Common.FixedArrays; namespace LibHac.Fs; @@ -9,7 +12,20 @@ public struct RsaEncryptedKey public struct AesKey { - public Array16 Value; + private Array2 _value; + + [UnscopedRef] + public Span Value => MemoryMarshal.Cast(_value); +} + +public struct AesMac +{ + public Array16 Data; +} + +public struct AesIv +{ + public Array16 Data; } public struct InitialDataVersion2 diff --git a/src/LibHac/Fs/SaveDataTransferVersion2.cs b/src/LibHac/Fs/SaveDataTransferVersion2.cs new file mode 100644 index 00000000..30457dbb --- /dev/null +++ b/src/LibHac/Fs/SaveDataTransferVersion2.cs @@ -0,0 +1,36 @@ +using System; +using LibHac.Account; +using LibHac.Common; + +namespace LibHac.Fs; + +public partial class SaveDataTransferManagerVersion2 +{ + public Result OpenSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialData, in Uid user, SaveDataSpaceId spaceId, bool useSwap) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialData, ulong staticSaveDataId, in Uid user, ulong ownerId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataFullImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialData, in Uid user, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public static SaveDataTag MakeUserAccountSaveDataTag(Ncm.ApplicationId applicationId, in Uid user) + { + throw new NotImplementedException(); + } + + public Result CancelSuspendingImport(Ncm.ApplicationId applicationId, in Uid user) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/SaveDataMover.cs b/src/LibHac/Fs/Shim/SaveDataMover.cs new file mode 100644 index 00000000..753eb07e --- /dev/null +++ b/src/LibHac/Fs/Shim/SaveDataMover.cs @@ -0,0 +1,74 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Sf; + +namespace LibHac.Fs.Shim; + +public interface ISaveDataMover : IDisposable +{ + Result Register(ulong saveDataId); + Result Process(out long outRemainingSize, long sizeToProcess); + Result Cancel(); +} + +file class SaveDataMoverImpl : ISaveDataMover +{ + private SharedRef _baseInterface; + + public SaveDataMoverImpl(SharedRef baseInterface) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Register(ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result Process(out long outRemainingSize, long sizeToProcess) + { + throw new NotImplementedException(); + } + + public Result Cancel() + { + throw new NotImplementedException(); + } +} + +public static class SaveDataMover +{ + public static Result OpenSaveDataMover(this FileSystemClient fs, ref UniqueRef outMover, + SaveDataSpaceId sourceSpaceId, SaveDataSpaceId destinationSpaceId, NativeHandle workBufferHandle, + ulong workBufferSize) + { + throw new NotImplementedException(); + } +} + +public struct SizeCalculatorForSaveDataMover +{ + private long _currentSize; + + public void Add(in SaveDataInfo saveDataInfo) + { + throw new NotImplementedException(); + } + + public long GetTotalSize() + { + throw new NotImplementedException(); + } + + public static Result GetFreeSpaceSize(FileSystemClient fs, out long outFreeSpaceSize, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/SaveDataThumbnail.cs b/src/LibHac/Fs/Shim/SaveDataThumbnail.cs new file mode 100644 index 00000000..0cc4d919 --- /dev/null +++ b/src/LibHac/Fs/Shim/SaveDataThumbnail.cs @@ -0,0 +1,113 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs.Fsa; + +namespace LibHac.Fs.Shim; + +file static class Anonymous +{ + public static Result ReadMeta(Span outBuffer, IFile file) + { + throw new NotImplementedException(); + } + + public static Result ReadAndCheckHash(Span outDataBuffer, IFile file, ReadOnlySpan expectedHash, + ulong offset, ulong size) + { + throw new NotImplementedException(); + } + + public static Result WriteAndCalcHash(Span outHashBuffer, IFile file, ReadOnlySpan data, ulong offset, + ulong size) + { + throw new NotImplementedException(); + } + + public static Result OpenSaveDataThumbnailFileImpl(ref UniqueRef outFile, SaveDataType saveType, + ulong programId, UserId userId) + { + throw new NotImplementedException(); + } + + public static Result OpenSaveDataThumbnailFileImpl(ref UniqueRef outFile, ulong programId, UserId userId) + { + throw new NotImplementedException(); + } +} + +public static class SaveDataThumbnail +{ + public static Result ReadSaveDataThumbnailFile(this FileSystemClientImpl fs, ulong applicationId, UserId userId, + Span headerBuffer, Span imageDataBuffer) + { + throw new NotImplementedException(); + } + + public static Result ReadSaveDataThumbnailFile(this FileSystemClient fs, ulong applicationId, UserId userId, + Span headerBuffer, Span imageDataBuffer) + { + throw new NotImplementedException(); + } + + public static Result ReadSaveDataThumbnailFileHeader(this FileSystemClientImpl fs, ulong applicationId, + UserId userId, Span headerBuffer) + { + throw new NotImplementedException(); + } + + public static Result OpenSaveDataThumbnailFile(this FileSystemClient fs, ref UniqueRef outFile, + ulong applicationId, UserId userId) + { + throw new NotImplementedException(); + } + + public static Result OpenSaveDataThumbnailFile(this FileSystemClient fs, ref UniqueRef outFile, + SaveDataType saveType, ulong applicationId, UserId userId) + { + throw new NotImplementedException(); + } + + public static Result ReadSaveDataThumbnailFileHeader(this FileSystemClient fs, ulong applicationId, + UserId userId, Span headerBuffer) + { + throw new NotImplementedException(); + } + + public static Result WriteSaveDataThumbnailFile(this FileSystemClientImpl fs, ulong applicationId, UserId userId, + ReadOnlySpan headerBuffer, ReadOnlySpan imageDataBuffer) + { + throw new NotImplementedException(); + } + + public static Result WriteSaveDataThumbnailFile(this FileSystemClient fs, ulong applicationId, UserId userId, + ReadOnlySpan headerBuffer, ReadOnlySpan imageDataBuffer) + { + throw new NotImplementedException(); + } + + public static Result WriteSaveDataThumbnailFileHeader(this FileSystemClientImpl fs, ulong applicationId, + UserId userId, ReadOnlySpan headerBuffer) + { + throw new NotImplementedException(); + } + + public static Result WriteSaveDataThumbnailFileHeader(this FileSystemClient fs, ulong applicationId, + UserId userId, ReadOnlySpan headerBuffer) + { + throw new NotImplementedException(); + } + + public static Result CorruptSaveDataThumbnailFileForDebug(this FileSystemClientImpl fs, ulong applicationId, + UserId userId) + { + throw new NotImplementedException(); + } + + public static Result CorruptSaveDataThumbnailFileForDebug(this FileSystemClient fs, ulong applicationId, + UserId userId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/SaveDataTransfer.cs b/src/LibHac/Fs/Shim/SaveDataTransfer.cs new file mode 100644 index 00000000..2dc2aca6 --- /dev/null +++ b/src/LibHac/Fs/Shim/SaveDataTransfer.cs @@ -0,0 +1,151 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.FsSrv.Sf; + +// ReSharper disable once CheckNamespace +namespace LibHac.Fs; + +file static class Anonymous +{ + public static Result QuerySaveDataExportSizeImpl(out long outExportSize, in SaveDataInfo saveDataInfo) + { + throw new NotImplementedException(); + } +} + +public partial class SaveDataTransferManager +{ + private SharedRef _baseInterface; + + // LibHac addition + private FileSystemClient _fsClient; + + public SaveDataTransferManager() + { + throw new NotImplementedException(); + } + + public Result GetChallenge(Span outChallengeBuffer) + { + throw new NotImplementedException(); + } + + public Result SetToken(ReadOnlySpan token) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporter(ref UniqueRef outExporter, SaveDataSpaceId spaceId, + ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref UniqueRef outImporter, out long outRequiredSize, + ReadOnlySpan initialData, in UserId userId, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } +} + +public static class SaveDataTransferSizeCalculator +{ + public static Result QuerySaveDataExportSize(out long outExportSize, in SaveDataInfo saveDataInfo) + { + throw new NotImplementedException(); + } + + public static long QuerySaveDataRequiredSizeForImport(in SaveDataInfo saveDataInfo) + { + throw new NotImplementedException(); + } + + public static Result QuerySaveDataExportSize(out long outExportSize, ReadOnlySpan saveDataInfo) + { + throw new NotImplementedException(); + } + + public static long QuerySaveDataRequiredSizeForImport(ReadOnlySpan saveDataInfo) + { + throw new NotImplementedException(); + } + + public static Result GetFreeSpaceSize(FileSystemClient fs, out long outSize, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } +} + +public class SaveDataExporter : IDisposable +{ + private SharedRef _baseInterface; + private SaveDataInfo _saveDataInfo; + + internal SaveDataExporter(ref readonly SharedRef exporter) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public ref readonly SaveDataInfo GetSaveDataInfo() + { + throw new NotImplementedException(); + } + + public Result PullInitialData(Span buffer) + { + throw new NotImplementedException(); + } + + public Result Pull(out ulong outPulledSize, Span buffer) + { + throw new NotImplementedException(); + } + + public long GetRestSize() + { + throw new NotImplementedException(); + } +} + +public class SaveDataImporter : IDisposable +{ + private SharedRef _baseInterface; + private SaveDataInfo _saveDataInfo; + + internal SaveDataImporter(ref readonly SharedRef importer) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result FinalizeObject() + { + throw new NotImplementedException(); + } + + public ref readonly SaveDataInfo GetSaveDataInfo() + { + throw new NotImplementedException(); + } + + public Result Push(ReadOnlySpan buffer) + { + throw new NotImplementedException(); + } + + public ulong GetRestSize() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/SaveDataTransferForRepair.cs b/src/LibHac/Fs/Shim/SaveDataTransferForRepair.cs new file mode 100644 index 00000000..5fed70c5 --- /dev/null +++ b/src/LibHac/Fs/Shim/SaveDataTransferForRepair.cs @@ -0,0 +1,38 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.FsSrv.Sf; + +// ReSharper disable once CheckNamespace +namespace LibHac.Fs; + +public class SaveDataTransferManagerForRepair +{ + private SharedRef _baseInterface; + + // LibHac addition + private FileSystemClient _fsClient; + + public SaveDataTransferManagerForRepair(FileSystemClient fs) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporter(ref UniqueRef outExporter, SaveDataSpaceId spaceId, + ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialData, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result GetSaveDataAttribute(out SaveDataAttribute outAttribute, in InitialDataVersion2 initialData) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/SaveDataTransferForSaveDataRepair.cs b/src/LibHac/Fs/Shim/SaveDataTransferForSaveDataRepair.cs new file mode 100644 index 00000000..020ef2ac --- /dev/null +++ b/src/LibHac/Fs/Shim/SaveDataTransferForSaveDataRepair.cs @@ -0,0 +1,86 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.FsSrv.Sf; + +// ReSharper disable once CheckNamespace +namespace LibHac.Fs; + +public partial class SaveDataTransferManagerForSaveDataRepair +{ + private SharedRef _baseInterface; + + // LibHac addition + private FileSystemClient _fsClient; + + public struct KeyPackageV0 + { + public Array640 Data; + } + + public SaveDataTransferManagerForSaveDataRepair(FileSystemClient fs) + { + throw new NotImplementedException(); + } + + public Result GetChallenge(out SaveDataTransferManagerVersion2.Challenge outChallenge) + { + throw new NotImplementedException(); + } + + public Result SetKeyPackage(in KeyPackageV0 keyPackage) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporterAndGetEncryptedKey(ref UniqueRef outExporter, + out RsaEncryptedKey outEncryptedKey, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result PrepareOpenSaveDataImporter(out RsaEncryptedKey outEncryptedKey) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialDataBeforeRepair, in InitialDataVersion2 initialDataAfterRepair, in UserId userId, + SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialData, in UserId userId, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenDeviceSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialDataBeforeRepair, in InitialDataVersion2 initialDataAfterRepair, + SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenDeviceSaveDataImporter(ref UniqueRef outImporter, + in InitialDataVersion2 initialDataBeforeRepair, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporterWithKey(ref UniqueRef outExporter, in AesKey key, + SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterWithKey(ref UniqueRef outExporter, in AesKey key, + in InitialDataVersion2 initialData, in UserId userId, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/SaveDataTransferVersion2.cs b/src/LibHac/Fs/Shim/SaveDataTransferVersion2.cs index 82bee87d..b0584834 100644 --- a/src/LibHac/Fs/Shim/SaveDataTransferVersion2.cs +++ b/src/LibHac/Fs/Shim/SaveDataTransferVersion2.cs @@ -18,7 +18,7 @@ namespace LibHac.Fs /// IPC service object. /// /// Based on nnSdk 14.3.0 - public class SaveDataTransferManagerVersion2 : IDisposable + public partial class SaveDataTransferManagerVersion2 : IDisposable { private SharedRef _baseInterface; diff --git a/src/LibHac/Fs/UserAccountSystemSaveData.cs b/src/LibHac/Fs/UserAccountSystemSaveData.cs new file mode 100644 index 00000000..cdea2505 --- /dev/null +++ b/src/LibHac/Fs/UserAccountSystemSaveData.cs @@ -0,0 +1,42 @@ +using System; +using LibHac.Account; +using LibHac.Common; + +namespace LibHac.Fs; + +public static class UserAccountSystemSaveData +{ + public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName, ulong saveDataId, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, in Uid user, long size, + long journalSize, SaveDataFlags flags) + { + throw new NotImplementedException(); + } + + public static Result CreateSystemSaveData(this FileSystemClient fs, ulong saveDataId, in Uid user, ulong ownerId, + long size, long journalSize, SaveDataFlags flags, SaveDataFormatType formatType) + { + throw new NotImplementedException(); + } + + public static Result DeleteSystemSaveData(this FileSystemClient fs, ulong saveDataId, in Uid user) + { + throw new NotImplementedException(); + } + + public static Result GetSystemSaveDataFlags(this FileSystemClient fs, out SaveDataFlags outFlags, ulong saveDataId, + in Uid user) + { + throw new NotImplementedException(); + } + + public static Result SetSystemSaveDataFlags(this FileSystemClient fs, ulong saveDataId, in Uid user, + SaveDataFlags flags) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/ValueSubStorage.cs b/src/LibHac/Fs/ValueSubStorage.cs index 6151d0f8..ea028a65 100644 --- a/src/LibHac/Fs/ValueSubStorage.cs +++ b/src/LibHac/Fs/ValueSubStorage.cs @@ -100,6 +100,23 @@ public struct ValueSubStorage : IDisposable } } + public void Set(in ValueSubStorage other, long offset, long size) + { + if (!Unsafe.AreSame(ref Unsafe.AsRef(in this), ref Unsafe.AsRef(in other))) + { + _baseStorage = other._baseStorage; + _offset = other._offset + offset; + _size = size; + _isResizable = false; + _sharedBaseStorage.SetByCopy(in other._sharedBaseStorage); + + Assert.SdkRequiresLessEqual(0, offset); + Assert.SdkRequiresLessEqual(0, size); + Assert.SdkRequires(other.IsValid()); + Assert.SdkRequiresGreaterEqual(other._size, offset + size); + } + } + private readonly bool IsValid() => _baseStorage is not null; public void SetResizable(bool isResizable) diff --git a/src/LibHac/FsSrv/Impl/SaveDataExporter.cs b/src/LibHac/FsSrv/Impl/SaveDataExporter.cs new file mode 100644 index 00000000..0f7006f2 --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataExporter.cs @@ -0,0 +1,57 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Crypto; +using LibHac.Fs; +using LibHac.FsSrv.Sf; +using LibHac.Sf; +using IFile = LibHac.Fs.Fsa.IFile; + +namespace LibHac.FsSrv.Impl; + +public class SaveDataExporter : ISaveDataExporter +{ + private Box _extraData; + private SaveDataInfo _saveDataInfo; + private ulong _pulledSize; + private ulong _totalSize; + private SharedRef _saveDataFile; + private ulong _currentFileOffset; + private UniqueRef _initialDataEncryptor; + private UniqueRef _encryptor; + private uint _initialDataVersion; + + public SaveDataExporter(Box extraData, in SaveDataInfo saveDataInfo, + ref readonly SharedRef saveDataFile, long fileSize, + ref UniqueRef initialDataEncryptor, ref UniqueRef encryptor, + uint initialDataVersion) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result GetSaveDataInfo(out SaveDataInfo outInfo) + { + throw new NotImplementedException(); + } + + public Result GetRestSize(out ulong outRemainingSize) + { + throw new NotImplementedException(); + } + + public Result Pull(out ulong outBytesRead, OutBuffer buffer) + { + throw new NotImplementedException(); + } + + public Result PullInitialData(OutBuffer initialDataBuffer) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataExtender.cs b/src/LibHac/FsSrv/Impl/SaveDataExtender.cs new file mode 100644 index 00000000..0a05bfbb --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataExtender.cs @@ -0,0 +1,97 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value +using System; +using System.Runtime.CompilerServices; +using LibHac.Fs; +using LibHac.FsSystem; +using LibHac.FsSystem.Save; + +namespace LibHac.FsSrv.Impl; + +public class SaveDataExtender +{ + private enum State + { + Initial = 1, + Extended = 2, + Committed = 3 + } + + private struct Context + { + public uint Magic; + public uint Version; + public State State; + public long AvailableSize; + public long JournalSize; + public long BlockSize; + public long ExtendedSaveDataSize; + } + + private IStorage _contextStorage; + private Context _context; + + public static long QueryContextSize() => Unsafe.SizeOf(); + + public SaveDataExtender() + { + throw new NotImplementedException(); + } + + public Result InitializeContext(in JournalIntegritySaveDataParameters param, long sizeAvailable, long sizeReserved) + { + throw new NotImplementedException(); + } + + public Result WriteContext(IStorage contextStorage) + { + throw new NotImplementedException(); + } + + public Result ReadContext(IStorage contextStorage) + { + throw new NotImplementedException(); + } + + public long GetLogSize() + { + throw new NotImplementedException(); + } + + public long GetAvailableSize() + { + throw new NotImplementedException(); + } + + public long GetJournalSize() + { + throw new NotImplementedException(); + } + + public long GetExtendedSaveDataSize() + { + throw new NotImplementedException(); + } + + private uint GetAvailableBlockCount() + { + throw new NotImplementedException(); + } + + private uint GetJournalBlockCount() + { + throw new NotImplementedException(); + } + + public Result Extend(in ValueSubStorage saveDataStorage, in ValueSubStorage logStorage, IBufferManager bufferManager, + IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) + { + throw new NotImplementedException(); + } + + private void UpdateContextV1ToV2(ref Context context) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataImporter.cs b/src/LibHac/FsSrv/Impl/SaveDataImporter.cs new file mode 100644 index 00000000..5dabf69f --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataImporter.cs @@ -0,0 +1,78 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Crypto; +using LibHac.Fs; +using LibHac.FsSrv.Sf; +using LibHac.Sf; +using IFile = LibHac.Fs.Fsa.IFile; +using IFileSystem = LibHac.Fs.Fsa.IFileSystem; + +namespace LibHac.FsSrv.Impl; + +public class SaveDataMacUpdater : IDisposable +{ + private SharedRef _fileSystem; + + public SaveDataMacUpdater(ref readonly SharedRef fileSystem) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result UpdateMac() + { + throw new NotImplementedException(); + } +} + +public class SaveDataImporter : ISaveDataImporter +{ + private SharedRef _transferInterface; + private SaveDataInfo _saveDataInfo; + private bool _isFinished; + private ulong _pushedSize; + private ulong _totalSize; + private SharedRef _saveDataFile; + private ulong _currentFileOffset; + private UniqueRef _decryptor; + private AesMac _expectedMac; + private UniqueRef _macUpdater; + + public SaveDataImporter(ref readonly SharedRef transferInterface, + in SaveDataInfo saveDataInfo, ref readonly SharedRef file, long fileSize, + ref UniqueRef macUpdater, ref UniqueRef decryptor) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result GetSaveDataInfo(out SaveDataInfo outInfo) + { + throw new NotImplementedException(); + } + + public Result GetRestSize(out ulong outRemainingSize) + { + throw new NotImplementedException(); + } + + public Result Push(InBuffer buffer) + { + throw new NotImplementedException(); + } + + public Result FinalizeImport() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataMover.cs b/src/LibHac/FsSrv/Impl/SaveDataMover.cs new file mode 100644 index 00000000..6e13945a --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataMover.cs @@ -0,0 +1,86 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.FsSrv.Sf; +using LibHac.Os; +using LibHac.Sf; +using LibHac.Util; + +namespace LibHac.FsSrv.Impl; + +public class SaveDataMover : ISaveDataMover +{ + private enum State + { + Initial, + Registered, + Copying, + Finished, + Fatal, + Canceled + } + + private SharedRef _transferInterface; + private Optional _duplicator; + private SaveDataSpaceId _sourceSpaceId; + private Array128 _sourceSaveIds; + private SaveDataSpaceId _destinationSpaceId; + private Array128 _destinationSaveIds; + // private TransferMemory _transferMemory; + private Memory _workBuffer; + // private ulong _transferMemorySize; + private int _saveCount; + private int _currentSaveIndex; + private long _remainingSize; + private State _state; + private SdkMutex _mutex; + + public SaveDataMover(SharedRef transferInterface, SaveDataSpaceId sourceSpaceId, + SaveDataSpaceId destinationSpaceId, NativeHandle transferMemoryHandle, ulong transferMemorySize) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + private Result OpenDuplicator() + { + throw new NotImplementedException(); + } + + private Result Initialize() + { + throw new NotImplementedException(); + } + + public Result Register(ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result Process(out long remainingSize, long sizeToProcess) + { + throw new NotImplementedException(); + } + + private Result FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result Cancel() + { + throw new NotImplementedException(); + } + + private void ChangeStateToFatal() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataProperties.cs b/src/LibHac/FsSrv/Impl/SaveDataProperties.cs index dec1956e..955eecc0 100644 --- a/src/LibHac/FsSrv/Impl/SaveDataProperties.cs +++ b/src/LibHac/FsSrv/Impl/SaveDataProperties.cs @@ -1,4 +1,5 @@ -using LibHac.Diag; +using System; +using LibHac.Diag; using LibHac.Fs; namespace LibHac.FsSrv.Impl; @@ -112,6 +113,16 @@ public static class SaveDataProperties } } + public static bool IsWipingNeededAtCleanUp(in SaveDataInfo info) + { + throw new NotImplementedException(); + } + + public static bool IsValidSpaceIdForSaveDataMover(SaveDataType type, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + public static bool IsReconstructible(SaveDataType type, SaveDataSpaceId spaceId) { switch (spaceId) diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransfer.cs b/src/LibHac/FsSrv/Impl/SaveDataTransfer.cs new file mode 100644 index 00000000..b8628758 --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransfer.cs @@ -0,0 +1,67 @@ +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Fs.Impl; +using LibHac.FsSystem; + +namespace LibHac.FsSrv.Impl; + +public interface IChunkEncryptorFactory : IDisposable +{ + Result Create(ref SharedRef outEncryptor); +} + +public interface IChunkDecryptorFactory : IDisposable +{ + Result Create(ref SharedRef outDecryptor, in AesMac mac); +} + +public struct InitialDataVersion1Detail +{ + public Content DataContent; + public Array16 Mac; + + public struct Content + { + public SaveDataExtraData ExtraData; + public uint Version; + public Array104 Reserved; + } +} + +public struct InitialDataVersion2Detail +{ + public AesGcmStreamHeader GcmStreamHeader; + public Content DataContent; + public AesGcmStreamTail GcmStreamTail; + + public struct Content + { + public uint Signature; + public uint Version; + public SaveDataExtraData ExtraData; + public int DivisionCount; + public long DivisionAlignment; + public Array64 ChunkHashes; + public Array64 ChunkSizes; + public Array64 ChunkMacs; + public long TotalChunkSize; + public InitialDataAad InitialDataAad; + public HashSalt HashSalt; + public Array128 ShortHashes; + public bool IsIntegritySeedEnabled; + public HashAlgorithmType HashAlgorithmType; + public Array3438 Reserved; + } + + public struct Hash + { + public Array32 Data; + } + + public struct ShortHash + { + public Array4 Data; + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferChunkIterator.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferChunkIterator.cs new file mode 100644 index 00000000..e5eb371f --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferChunkIterator.cs @@ -0,0 +1,44 @@ +// ReSharper disable UnusedMember.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.FsSrv.Sf; + +namespace LibHac.FsSrv.Impl; + +public class SaveDataChunkIteratorDiff : ISaveDataChunkIterator +{ + private SaveDataChunkDiffInfo _diffInfo; + private uint _endId; + private bool _isExport; + private uint _currentId; + + public SaveDataChunkIteratorDiff(in SaveDataChunkDiffInfo diffInfo, bool isExport, int count) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + private bool IsEnd() + { + throw new NotImplementedException(); + } + + public Result Next() + { + throw new NotImplementedException(); + } + + public Result IsEnd(out bool isEnd) + { + throw new NotImplementedException(); + } + + public Result GetId(out uint chunkId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferChunkPorter.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferChunkPorter.cs new file mode 100644 index 00000000..e2dbe84c --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferChunkPorter.cs @@ -0,0 +1,93 @@ +// ReSharper disable UnusedMember.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Sf; +using ISaveDataChunkExporter = LibHac.FsSrv.Sf.ISaveDataChunkExporter; +using IStorage = LibHac.Fs.IStorage; + +namespace LibHac.FsSrv.Impl; + +public struct SaveDataChunkDiffInfo +{ + public Array64 IsDifferent; +} + +public class SaveDataChunkExporter : ISaveDataChunkExporter +{ + private SharedRef _aesGcmSource; + private SharedRef _encryptor; + private SaveDataDivisionExporter _parentExporter; + private ushort _chunkId; + private long _totalReadSize; + private bool _isPullable; + + public SaveDataChunkExporter(SaveDataDivisionExporter parentExporter, ushort chunkId, + ref readonly SharedRef encryptor, bool isPullable) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(ref readonly SharedRef baseStorage, bool isCompressed, in AesIv iv) + { + throw new NotImplementedException(); + } + + public Result Pull(out ulong outBytesRead, OutBuffer buffer, ulong size) + { + throw new NotImplementedException(); + } + + public Result PullCore(out ulong outReadSize, Span buffer) + { + throw new NotImplementedException(); + } + + public Result GetRestRawDataSize(out long outRemainingSize) + { + throw new NotImplementedException(); + } + + public Result GetRestRawDataSizeCore(out long outRemainingSize) + { + throw new NotImplementedException(); + } +} + +public class SaveDataChunkImporter : ISaveDataChunkImporter +{ + private AesMac _mac; + private SharedRef _sink; + private SharedRef _decryptor; + private SaveDataDivisionImporter _parentImporter; + private ushort _chunkId; + private bool _isImporterValid; + + public SaveDataChunkImporter(SaveDataDivisionImporter parentImporter, ushort chunkId, + ref readonly SharedRef decryptor, in AesMac mac) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(ref readonly SharedRef storage, long size, bool isCompressionEnabled, bool useLargeBuffer) + { + throw new NotImplementedException(); + } + + public Result Push(ReadOnlySpan source) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferDivisionPorter.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferDivisionPorter.cs new file mode 100644 index 00000000..57f53b64 --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferDivisionPorter.cs @@ -0,0 +1,576 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Fs.Impl; +using LibHac.Os; +using LibHac.Sf; +using LibHac.Util; +using ISaveDataChunkExporter = LibHac.FsSrv.Sf.ISaveDataChunkExporter; +using ISaveDataChunkImporter = LibHac.FsSrv.Sf.ISaveDataChunkImporter; +using ISaveDataChunkIterator = LibHac.FsSrv.Sf.ISaveDataChunkIterator; + +namespace LibHac.FsSrv.Impl; + +file static class Anonymous +{ + public static Result CalculateStorageHash(out InitialDataVersion2Detail.Hash outHash, + out InitialDataVersion2Detail.ShortHash outHashShort1, out InitialDataVersion2Detail.ShortHash outHashShort2, + IStorage storage, Span buffer) + { + throw new NotImplementedException(); + } + + public static Result OpenSaveDataChunkIteratorDiff(ref SharedRef outIterator, + in SaveDataChunkDiffInfo diffInfo, bool isExport, int count) + { + throw new NotImplementedException(); + } + + public static Result OpenSubStorage(ref SharedRef outSubStorage, + ref readonly SharedRef internalStorageAccessor, + ref readonly SharedRef chunkSizeCalculator, int chunkIndex) + { + throw new NotImplementedException(); + } + + public static void InheritPreviousInitialData(ref InitialDataVersion2Detail.Content initialData, + in InitialDataVersion2Detail.Content previousInitialData) + { + throw new NotImplementedException(); + } + + public static Result CalculateChunkHash(out InitialDataVersion2Detail.Hash outHash, + out InitialDataVersion2Detail.ShortHash outHashShort1, out InitialDataVersion2Detail.ShortHash outHashShort2, + ref readonly SharedRef internalStorageAccessor, + ref readonly SharedRef chunkSizeCalculator, int chunkId) + { + throw new NotImplementedException(); + } + + public static Result CalculateChunkHash(out InitialDataVersion2Detail.Hash outHash, + ref readonly SharedRef internalStorageAccessor, + ref readonly SharedRef chunkSizeCalculator, int chunkId) + { + throw new NotImplementedException(); + } + + public static Result EncryptPortContext(Span destination, ReadOnlySpan source, + SaveDataTransferCryptoConfiguration cryptoConfig) + { + throw new NotImplementedException(); + } + + public static byte GetDiffChunkCount(Span isDifferent, int chunkCount, bool getHalfDivisionDiff) + { + throw new NotImplementedException(); + } + + public static byte GetCompressionRate(in InitialDataVersion2Detail.Content initialData) + { + throw new NotImplementedException(); + } + + public static bool IsTheirsHashSaltUsed(in InitialDataVersion2Detail.Content initialData, + in InitialDataVersion2Detail.Content originalInitialData) + { + throw new NotImplementedException(); + } +} + +public struct ExportContextDetail +{ + public AesGcmStreamHeader GcmStreamHeader; + public Content DataContent; + public AesGcmStreamTail GcmStreamTail; + + public struct Content + { + public uint Magic; + public uint Unk; + public bool IsDiffExport; + public Array64 ChunkSizes; + public Array64 ChunkMacs; + public Array64 IsChunkComplete; + public InitialDataVersion2Detail InitialData; + public SaveDataSpaceId SpaceId; + public ulong SaveDataId; + public long CommitId; + public int DivisionCount; + public long DivisionAlignment; + public InitialDataAad InitialDataAad; + public bool IsInitialDataComplete; + public Array64 ChunkIvs; + public AesIv OuterInitialDataIv; + public KeySeed KeySeed; + public InitialDataVersion2Detail.Hash ThumbnailHash; + public Array5366 Reserved; + } +} + +public struct ImportContextDetail +{ + public AesGcmStreamHeader GcmStreamHeader; + public Content DataContent; + public AesGcmStreamTail GcmStreamTail; + + public struct Content + { + public uint Magic; + public uint Unk; + public SaveDataDivisionImporter.Mode Mode; + public InitialDataVersion2Detail InitialData; + public SaveDataSpaceId SpaceId; + public ulong SourceSaveDataId; + public ulong DestinationSaveDataId; + public long SourceZeroCommitId; + public long DestinationZeroCommitId; + public UserId UserId; + public long TimeStamp; + public ImportReportInfo ReportInfo; + public InitialDataVersion2Detail.Hash ThumbnailHash; + public Array8000 Reserved; + } +} + +public class ChunkSizeCalculator : IDisposable +{ + private ulong _divisionAlignment; + private long _chunkSize; + private int _divisionCount; + private int _longChunkCount; + + public ChunkSizeCalculator(long totalSize, ulong divisionAlignment, int divisionCount) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public int GetDivisionCount() => throw new NotImplementedException(); + + public void GetOffsetAndSize(out long outOffset, out long outSize, int chunkId) + { + throw new NotImplementedException(); + } +} + +public class SaveDataDivisionExporter : Prohibitee, Sf.ISaveDataDivisionExporter +{ + private SdkMutex _mutex; + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private Optional _keySeed; + private SharedRef _encryptorFactory; + private InitialDataVersion2Detail.Content _initialData; + private InitialDataVersion2Detail _encryptedInitialData; + private InitialDataAad _initialDataAad; + private SaveDataSpaceId _saveDataSpaceId; + private ulong _saveDataId; + private InitialDataVersion2Detail.Hash _thumbnailHash; + private ApplicationId _applicationId; + private bool _isExportComplete; + private bool _isReportAvailable; + private bool _isDiffExport; + private Array64 _isChunkComplete; + private bool _isInitialDataComplete; + private SaveDataChunkDiffInfo _chunkDiffInfo; + private Array64 _chunkIvs; + private AesIv _outerInitialDataIv; + private SharedRef _internalStorageAccessor; + private SharedRef _chunkSizeCalculator; + private bool _hasOuterInitialDataMac; + private SaveDataTransferCryptoConfiguration.KeyIndex _outerInitialDataMacKeyIndex; + private InitialDataMac _initialDataMac; + private int _outerInitialDataMacKeyGeneration; + private bool _isCompressionEnabled; + private SaveDataTransferCryptoConfiguration.Attributes _attribute; + + public SaveDataDivisionExporter( + SaveDataTransferCryptoConfiguration cryptoConfig, + in Optional keySeed, + ref readonly SharedRef encryptorFactory, + SaveDataSpaceId spaceId, + ulong saveDataId, + SaveDataPorterManager porterManager, + bool isDiffExport, + bool isCompressionEnabled, + SaveDataTransferCryptoConfiguration.Attributes attribute) : base(porterManager) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + private Result InitializeCommon(ISaveDataTransferCoreInterface coreInterface, + in Optional initialData) + { + throw new NotImplementedException(); + } + + public Result InitializeForFullExport(ISaveDataTransferCoreInterface coreInterface) + { + throw new NotImplementedException(); + } + + public Result InitializeForFullExportWithOuterInitialDataMac(ISaveDataTransferCoreInterface coreInterface, + SaveDataTransferCryptoConfiguration.KeyIndex keyIndex, int keyGeneration) + { + throw new NotImplementedException(); + } + + public Result InitializeForDiffExport(ISaveDataTransferCoreInterface coreInterface, + Box initialData, in InitialDataVersion2Detail initialDataEncrypted) + { + throw new NotImplementedException(); + } + + public Result ResumeExport(in ExportContextDetail.Content exportContext) + { + throw new NotImplementedException(); + } + + public Result SetDivisionCountCore(int divisionCount) + { + throw new NotImplementedException(); + } + + public Result SetDivisionCount(int divisionCount) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataDiffChunkIterator(ref SharedRef outIterator) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataChunkExporter(ref SharedRef outExporter, uint chunkId) + { + throw new NotImplementedException(); + } + + public Result ReportAesGcmInfo(ushort chunkId, in AesMac mac, long chunkSize) + { + throw new NotImplementedException(); + } + + public Result ReportInitialDataCompletion() + { + throw new NotImplementedException(); + } + + public Result ReportInitialDataMac(in AesMac mac) + { + throw new NotImplementedException(); + } + + private Result CheckPullCompletion(bool noCheckInitialDataCompletion) + { + throw new NotImplementedException(); + } + + public Result GetKeySeed(out KeySeed outKeySeed) + { + throw new NotImplementedException(); + } + + public Result GetInitialDataMac(out InitialDataMac outInitialDataMac) + { + throw new NotImplementedException(); + } + + public Result GetInitialDataMacKeyGeneration(out int outKeyGeneration) + { + throw new NotImplementedException(); + } + + public Result FinalizeExport() + { + throw new NotImplementedException(); + } + + public Result CancelExport() + { + throw new NotImplementedException(); + } + + public Result SuspendExport(OutBuffer outExportContext) + { + throw new NotImplementedException(); + } + + public Result GetImportInitialDataAad(out InitialDataAad outInitialDataAad) + { + throw new NotImplementedException(); + } + + public Result SetExportInitialDataAad(in InitialDataAad initialDataAad) + { + throw new NotImplementedException(); + } + + private InitialDataMac CalculateInitialDataMac(in InitialDataVersion2Detail.Content initialData) + { + throw new NotImplementedException(); + } + + public Result ReadSaveDataExtraData(OutBuffer outExtraData) + { + throw new NotImplementedException(); + } + + public Result GetReportInfo(out ExportReportInfo outReportInfo) + { + throw new NotImplementedException(); + } + + public override void Invalidate() + { + throw new NotImplementedException(); + } + + private void InvalidateCore() + { + throw new NotImplementedException(); + } + + public override ApplicationId GetApplicationId() + { + throw new NotImplementedException(); + } + + public UniqueLock GetScopedLock() + { + throw new NotImplementedException(); + } + + private ref readonly AesIv GetIv(ushort chunkId) + { + throw new NotImplementedException(); + } + + private bool IsPorterValid() + { + throw new NotImplementedException(); + } +} + +public class SaveDataDivisionImporter : Prohibitee, Sf.ISaveDataDivisionImporter +{ + public enum Mode + { + None, + Swap, + Diff + } + + public enum State + { + NotInitialized, + Initializing, + Initialized, + Paused, + Complete, + Suspended + } + + private SdkMutex _mutex; + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private SharedRef _transferInterface; + private SharedRef _decryptorFactory; + private InitialDataVersion2Detail.Content _initialData; + private InitialDataVersion2Detail.Content _originalInitialData; + private InitialDataVersion2Detail _originalInitialDataEncrypted; + private SaveDataSpaceId _saveDataSpaceId; + private SaveDataCreationInfo2 _creationInfo; + private ulong _sourceSaveDataId; + private ulong _destSaveDataId; + private long _zeroCommitIdSource; + private long _zeroCommitIdDest; + private ulong _timestamp; + private InitialDataVersion2Detail.Hash _thumbnailHash; + private ApplicationId _applicationId; + private State _state; + private bool _isPorterInvalidated; + private Mode _mode; + private Array64 _isChunkComplete; + private SaveDataChunkDiffInfo _chunkDiffInfo; + private SharedRef _internalStorageAccessor; + private SharedRef _chunkSizeCalculator; + private Optional _storageDuplicator; + private ImportReportInfo _reportInfo; + private bool _isCompressionEnabled; + private bool _isLargeBufferEnabled; + + public SaveDataDivisionImporter( + ref readonly SharedRef transferCoreInterface, + in InitialDataVersion2Detail.Content initialData, + in InitialDataVersion2Detail initialDataEncrypted, + SaveDataTransferCryptoConfiguration cryptoConfig, + ref readonly SharedRef decryptorFactory, + SaveDataSpaceId spaceId, + in SaveDataCreationInfo2 creationInfo, + SaveDataPorterManager porterManager, + bool isCompressionEnabled, + bool isLargeBufferEnabled) : base(porterManager) + { + throw new NotImplementedException(); + } + + public SaveDataDivisionImporter( + ref readonly SharedRef transferCoreInterface, + in InitialDataVersion2Detail.Content initialData, + in InitialDataVersion2Detail initialDataEncrypted, + SaveDataTransferCryptoConfiguration cryptoConfig, + ref readonly SharedRef decryptorFactory, + SaveDataSpaceId spaceId, + ulong sourceSaveDataId, + SaveDataPorterManager porterManager, + bool useSwap) : base(porterManager) + { + throw new NotImplementedException(); + } + + public SaveDataDivisionImporter( + ref readonly SharedRef transferCoreInterface, + in InitialDataVersion2Detail.Content initialData, + in InitialDataVersion2Detail initialDataEncrypted, + SaveDataTransferCryptoConfiguration cryptoConfig, + ref readonly SharedRef decryptorFactory, + SaveDataSpaceId spaceId, + ulong sourceSaveDataId, + ulong destSaveDataId, + SaveDataPorterManager porterManager, + Mode mode) : base(porterManager) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public new Result Initialize() + { + throw new NotImplementedException(); + } + + public Result ResumeImport(in ImportContextDetail.Content importContext) + { + throw new NotImplementedException(); + } + + public Result InitializeImport(out long outRemaining, long sizeToProcess) + { + throw new NotImplementedException(); + } + + public Result ReportCompletion(ushort chunkId, bool isComplete) + { + throw new NotImplementedException(); + } + + public Result FinalizeImport() + { + throw new NotImplementedException(); + } + + public Result FinalizeImportWithoutSwap() + { + throw new NotImplementedException(); + } + + private Result FinalizeImport(bool noSwap) + { + throw new NotImplementedException(); + } + + public Result CancelImport() + { + throw new NotImplementedException(); + } + + public Result GetImportContext(OutBuffer outImportContext) + { + throw new NotImplementedException(); + } + + public Result SuspendImport() + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataDiffChunkIterator(ref SharedRef outIterator) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataChunkImporter(ref SharedRef outImporter, uint chunkId) + { + throw new NotImplementedException(); + } + + public Result GetImportInitialDataAad(out InitialDataAad outInitialDataAad) + { + throw new NotImplementedException(); + } + + private Result CreateDstSaveData(bool isSecondarySave, in HashSalt hashSalt) + { + throw new NotImplementedException(); + } + + public Result ReadSaveDataExtraData(OutBuffer outExtraData) + { + throw new NotImplementedException(); + } + + public Result GetReportInfo(out ImportReportInfo outReportInfo) + { + throw new NotImplementedException(); + } + + public override void Invalidate() + { + throw new NotImplementedException(); + } + + private void InvalidateCore() + { + throw new NotImplementedException(); + } + + public override ApplicationId GetApplicationId() + { + throw new NotImplementedException(); + } + + public UniqueLock GetScopedLock() + { + throw new NotImplementedException(); + } + + private bool IsPorterValid() + { + throw new NotImplementedException(); + } + + private bool IsDiffMode() + { + throw new NotImplementedException(); + } + + private bool IsSwapMode() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferForRepair.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferForRepair.cs new file mode 100644 index 00000000..7727cab7 --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferForRepair.cs @@ -0,0 +1,146 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs; +using LibHac.FsSrv.Sf; +using LibHac.Sf; +using ISaveDataDivisionExporter = LibHac.FsSrv.Sf.ISaveDataDivisionExporter; +using ISaveDataDivisionImporter = LibHac.FsSrv.Sf.ISaveDataDivisionImporter; + +namespace LibHac.FsSrv.Impl; + +file class NoEncryptorFactory : IChunkEncryptorFactory +{ + public NoEncryptorFactory() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Create(ref SharedRef outEncryptor) + { + throw new NotImplementedException(); + } + + private class Encryptor : AesGcmSource.IEncryptor + { + public Encryptor() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(ref AesGcmStreamHeader header, in AesIv iv) + { + throw new NotImplementedException(); + } + + public Result Update(Span destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public Result GetMac(out AesMac outMac) + { + throw new NotImplementedException(); + } + } +} + +file class NoDecryptorFactory : IChunkDecryptorFactory +{ + public NoDecryptorFactory() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Create(ref SharedRef outDecryptor, in AesMac mac) + { + throw new NotImplementedException(); + } + + private class Decryptor : AesGcmSink.IDecryptor + { + public Decryptor() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(in AesGcmStreamHeader header) + { + throw new NotImplementedException(); + } + + public Result Update(Span destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public Result Verify() + { + throw new NotImplementedException(); + } + } +} + +public class SaveDataTransferManagerForRepair : ISaveDataTransferManagerForRepair +{ + private SharedRef _saveTransferInterface; + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private SaveDataPorterManager _porterManager; + + public SaveDataTransferManagerForRepair(SaveDataTransferCryptoConfiguration cryptoConfig, + ref readonly SharedRef coreInterface, SaveDataPorterManager porterManager) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + private Result DecryptInitialDataWithExternalKey(out Box outInitialDataContent, + in InitialDataVersion2Detail initialDataEncrypted) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporter(ref SharedRef outExporter, SaveDataSpaceId spaceId, + ulong saveDataId) + { + throw new NotImplementedException(); + } + + private Result CreateImporter(ref SharedRef outImporter, + in InitialDataVersion2Detail.Content initialDataContent, in InitialDataVersion2Detail initialDataEncrypted, + SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref SharedRef outImporter, InBuffer initialData, + SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferManager.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferManager.cs new file mode 100644 index 00000000..3ed6dcfc --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferManager.cs @@ -0,0 +1,108 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.FsSrv.Sf; +using LibHac.Sf; +using IFile = LibHac.Fs.Fsa.IFile; + +namespace LibHac.FsSrv.Impl; + +public class SaveDataTransferManager : IDisposable +{ + private SharedRef _transferCoreInterface; + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private bool _isTokenSet; + private Array16 _challengeData; + private Array16 _transferAesKeySeed; + private Array16 _iv; + private int _openedExporterCount; + private int _openedImporterCount; + + public SaveDataTransferManager(SaveDataTransferCryptoConfiguration cryptoConfig, + ref readonly SharedRef transferCoreInterface) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result GetChallenge(OutBuffer outChallengeBuffer) + { + throw new NotImplementedException(); + } + + public Result SetToken(InBuffer tokenBuffer) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporter(ref SharedRef outExporter, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref SharedRef outImporter, out long outRequiredSize, + InBuffer initialData, in UserId userId, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataConcatenationFile(ref SharedRef outFile, + ref UniqueRef outMacUpdater, in SaveDataInfo saveDataInfo, OpenMode openMode, + bool isTemporaryTransferSave) + { + throw new NotImplementedException(); + } +} + +public class SaveDataInternalFile : IFile +{ + private SharedRef _baseFileSystem; + private SharedRef _baseFile; + + public SaveDataInternalFile(ref readonly SharedRef baseFileSystem, ref readonly SharedRef baseFile) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferManagerForSaveDataRepair.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferManagerForSaveDataRepair.cs new file mode 100644 index 00000000..7038d298 --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferManagerForSaveDataRepair.cs @@ -0,0 +1,269 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local UnusedTypeParameter +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Crypto; +using LibHac.Fs; +using LibHac.Fs.Impl; +using LibHac.FsSrv.Sf; +using LibHac.Sf; +using LibHac.Util; +using AesIv = LibHac.Fs.AesIv; +using AesKey = LibHac.Fs.AesKey; +using ISaveDataDivisionExporter = LibHac.FsSrv.Sf.ISaveDataDivisionExporter; +using ISaveDataDivisionImporter = LibHac.FsSrv.Sf.ISaveDataDivisionImporter; + +namespace LibHac.FsSrv.Impl; + +file class ExternalKeyChunkEncryptorFactory : IChunkEncryptorFactory +{ + private AesKey _key; + + public ExternalKeyChunkEncryptorFactory(in AesKey key) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Create(ref SharedRef outEncryptor) + { + throw new NotImplementedException(); + } + + private class Encryptor : AesGcmSource.IEncryptor + { + private Aes128GcmEncryptor _encryptor; + private AesKey _key; + + public Encryptor(in AesKey key) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(ref AesGcmStreamHeader header, in AesIv iv) + { + throw new NotImplementedException(); + } + + public Result Update(Span destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public Result GetMac(out AesMac outMac) + { + throw new NotImplementedException(); + } + } +} + +file class ExternalKeyChunkDecryptorFactory : IChunkDecryptorFactory +{ + private AesKey _key; + + public ExternalKeyChunkDecryptorFactory(in AesKey key) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Create(ref SharedRef outDecryptor, in AesMac mac) + { + throw new NotImplementedException(); + } + + private class Decryptor : AesGcmSink.IDecryptor + { + private AesKey _key; + private Aes128GcmDecryptor _decryptor; + + public Decryptor(in AesKey key) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(in AesGcmStreamHeader header) + { + throw new NotImplementedException(); + } + + public Result Update(Span destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public Result Verify() + { + throw new NotImplementedException(); + } + } +} + +file static class Anonymous +{ + public static Result CheckInitialDataConsistency(in InitialDataVersion2Detail.Content initialData1, + in InitialDataVersion2Detail.Content initialData2) + { + throw new NotImplementedException(); + } +} + +public interface ISaveDataTransferManagerForSaveDataRepairPolicy +{ + static abstract ulong DecryptAesGcm(Span destination, Span outMac, ReadOnlySpan key, + ReadOnlySpan iv, ReadOnlySpan source, ReadOnlySpan aad); +} + +internal struct SaveDataTransferManagerForSaveDataRepairPolicyV0 : ISaveDataTransferManagerForSaveDataRepairPolicy +{ + public static ulong DecryptAesGcm(Span destination, Span outMac, ReadOnlySpan key, + ReadOnlySpan iv, ReadOnlySpan source, ReadOnlySpan aad) + { + throw new NotImplementedException(); + } +} + +public static class SaveDataTransferManagerForSaveDataRepair +{ + public struct KeyPackageV0 + { + public uint Version; + public Array4 Reserved4; + public byte KeyGeneration; + public Array7 Reserved9; + public AesIv Iv; + public AesMac Mac; + public Array80 Reserved30; + public Content PackageContent; + public Array256 Signature; + + public struct Content + { + public InitialDataMac InitialDataMacBeforeRepair; + public byte KeyGenerationBeforeRepair; + public InitialDataMac InitialDataMacAfterRepair; + public byte KeyGenerationAfterRepair; + public Array2 Keys; + public AesIv Iv; + public AesMac Mac; + public Array8 Reserved70; + public Fs.SaveDataTransferManagerVersion2.Challenge ChallengeData; + public Array120 Reserved88; + } + } +} + +public class SaveDataTransferManagerForSaveDataRepair : ISaveDataTransferManagerForSaveDataRepair + where TPolicy : struct, ISaveDataTransferManagerForSaveDataRepairPolicy +{ + private SharedRef _transferInterface; + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private bool _isKeyPackageSet; + private Fs.SaveDataTransferManagerVersion2.Challenge _challengeData; + private Optional _kek; + private SaveDataTransferManagerForSaveDataRepair.KeyPackageV0.Content _keyPackage; + private SaveDataPorterManager _porterManager; + private bool _canOpenTool; + + public SaveDataTransferManagerForSaveDataRepair(SaveDataTransferCryptoConfiguration cryptoConfig, + ref readonly SharedRef coreInterface, SaveDataPorterManager porterManager, + bool canOpenTool) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result GetChallenge(OutBuffer challenge) + { + throw new NotImplementedException(); + } + + public Result SetKeyPackage(InBuffer keyPackage) + { + throw new NotImplementedException(); + } + + private Result DecryptAndVerifyInitialDataWithExternalKey( + ref InitialDataVersion2Detail.Content outInitialDataDecrypted, + in InitialDataVersion2Detail initialDataEncrypted, SaveDataTransferCryptoConfiguration.KeyIndex keyIndex, + int keyGeneration, in InitialDataMac expectedMac, in AesKey key) + { + throw new NotImplementedException(); + } + + private Result DecryptInitialDataWithExternalKey(ref InitialDataVersion2Detail.Content outInitialDataDecrypted, + in InitialDataVersion2Detail initialDataEncrypted, in AesKey key) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporterAndGetEncryptedKey(ref SharedRef outExporter, + OutBuffer outEncryptedKey, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result PrepareOpenSaveDataImporter(OutBuffer outEncryptedKey) + { + throw new NotImplementedException(); + } + + private Result DecryptAndVerifyKeyPackage(out AesKey outKeyBeforeRepair, out AesKey outKeyAfterRepair) + { + throw new NotImplementedException(); + } + + private Result CreateImporter(ref SharedRef outImporter, + in InitialDataVersion2Detail.Content initialDataContent, in InitialDataVersion2Detail initialDataEncrypted, + in AesKey key, UserId userId, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterForSaveDataAfterRepair(ref SharedRef outImporter, + InBuffer initialDataBeforeRepair, InBuffer initialDataAfterRepair, UserId userId, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterForSaveDataBeforeRepair(ref SharedRef outImporter, + InBuffer initialData, UserId userId, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporterWithKey(ref SharedRef outExporter, InBuffer key, + SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterWithKey(ref SharedRef outImporter, InBuffer key, + InBuffer initialData, UserId userId, ulong saveDataSpaceId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferPorterManager.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferPorterManager.cs new file mode 100644 index 00000000..174aaa1d --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferPorterManager.cs @@ -0,0 +1,96 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using System.Collections.Generic; +using LibHac.Os; + +namespace LibHac.FsSrv.Impl; + +public abstract class Prohibitee : IDisposable +{ + // IntrusiveList + private bool _isRegistered; + private SaveDataPorterManager _porterManager; + + public Prohibitee(SaveDataPorterManager porterManager) + { + throw new NotImplementedException(); + } + + public virtual void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize() + { + throw new NotImplementedException(); + } + + public void Unregister() + { + throw new NotImplementedException(); + } + + public abstract void Invalidate(); + public abstract ApplicationId GetApplicationId(); +} + +public class SaveDataPorterProhibiter : IDisposable +{ + // IntrusiveList + private SaveDataPorterManager _porterManager; + private Ncm.ApplicationId _applicationId; + + public SaveDataPorterProhibiter(SaveDataPorterManager porterManager, Ncm.ApplicationId applicationId) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Ncm.ApplicationId GetApplicationId() + { + throw new NotImplementedException(); + } +} + +public class SaveDataPorterManager +{ + private LinkedList _prohibiteeList; + private LinkedList _porterProhibiterList; + private SdkMutex _mutex; + + public SaveDataPorterManager() + { + throw new NotImplementedException(); + } + + public bool IsProhibited(ref UniqueLock refLock, ApplicationId applicationId) + { + throw new NotImplementedException(); + } + + public bool RegisterPorter(Prohibitee prohibitee, ApplicationId applicationId) + { + throw new NotImplementedException(); + } + + public void UnregisterPorter(Prohibitee prohibitee) + { + throw new NotImplementedException(); + } + + public void RegisterProhibiter(SaveDataPorterProhibiter porterProhibiter) + { + throw new NotImplementedException(); + } + + public void UnregisterProhibiter(SaveDataPorterProhibiter porterProhibiter) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferStream.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferStream.cs new file mode 100644 index 00000000..8001b6ae --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferStream.cs @@ -0,0 +1,259 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.FsSystem; + +namespace LibHac.FsSrv.Impl; + +public interface ISource : IDisposable +{ + Result Pull(out ulong outBytesRead, Span destination); + Result GetRestRawDataSize(out long outSize); + bool IsEnd(); +} + +public interface ISink : IDisposable +{ + Result Push(ReadOnlySpan data); + Result FinalizeObject(); +} + +public interface IStream : ISource, ISink; + +public class StorageStream : IStream +{ + private SharedRef _baseStorage; + private long _size; + private long _position; + + public StorageStream(ref readonly SharedRef storage) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Pull(out ulong outBytesRead, Span destination) + { + throw new NotImplementedException(); + } + + public Result GetRestRawDataSize(out long outSize) + { + throw new NotImplementedException(); + } + + public bool IsEnd() + { + throw new NotImplementedException(); + } + + public Result Push(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public Result FinalizeObject() + { + throw new NotImplementedException(); + } +} + +public class CompressionSource : ISource +{ + public CompressionSource(ref readonly SharedRef source) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + private bool IsInitialized() + { + throw new NotImplementedException(); + } + + public Result Initialize() + { + throw new NotImplementedException(); + } + + public Result Pull(out ulong outBytesRead, Span destination) + { + throw new NotImplementedException(); + } + + public Result GetRestRawDataSize(out long outSize) + { + throw new NotImplementedException(); + } + + public bool IsEnd() + { + throw new NotImplementedException(); + } +} + +public class DecompressionSink : ISink +{ + public DecompressionSink(ref readonly SharedRef sink) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + private bool IsInitialized() + { + throw new NotImplementedException(); + } + + public Result Initialize() + { + throw new NotImplementedException(); + } + + public Result FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result Push(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + private Result DecompressAndPushImpl(ReadOnlySpan source, bool isEndData) + { + throw new NotImplementedException(); + } +} + +public struct AesGcmStreamHeader +{ + public uint Signature; + public short Version; + public short KeyGeneration; + public Array8 Field8; + public Array16 Iv; +} + +public struct AesGcmStreamTail +{ + public Array16 Mac; +} + +public class AesGcmSource : ISource +{ + public interface IEncryptor : IDisposable + { + Result Initialize(ref AesGcmStreamHeader header, in AesIv iv); + Result Update(Span destination, ReadOnlySpan source); + Result GetMac(out AesMac outMac); + } + + private long _restHeaderSize; + private AesGcmStreamHeader _header; + private SharedRef _baseSource; + private IEncryptor _encryptor; + private AesIv _aesIv; + private bool _isDataFinished; + private long _restMacSize; + private AesMac _aesMac; + + public AesGcmSource(ref readonly SharedRef source, ref readonly SharedRef encryptor, in AesIv iv) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize() + { + throw new NotImplementedException(); + } + + public Result Pull(out ulong outBytesRead, Span destination) + { + throw new NotImplementedException(); + } + + public Result GetRestRawDataSize(out long outSize) + { + throw new NotImplementedException(); + } + + public bool IsEnd() + { + throw new NotImplementedException(); + } + + public Result GetMac(out AesMac outMac) + { + throw new NotImplementedException(); + } +} + +public class AesGcmSink : ISink +{ + public interface IDecryptor : IDisposable + { + Result Initialize(in AesGcmStreamHeader header); + Result Update(Span destination, ReadOnlySpan source); + Result Verify(); + } + + private long _restHeaderSize; + private AesGcmStreamHeader _header; + private SharedRef _baseSink; + private SharedRef _decryptor; + private long _restSize; + private AesMac _mac; + private PooledBuffer _pooledBuffer; + + public AesGcmSink(ref readonly SharedRef sink, long size, ref readonly SharedRef decryptor, + bool useLargeBuffer) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Push(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public Result FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result GetMac(out AesMac outMac) + { + throw new NotImplementedException(); + } + + public bool IsEnd() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferUtility.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferUtility.cs new file mode 100644 index 00000000..a14bead8 --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferUtility.cs @@ -0,0 +1,297 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.FsSystem; +using LibHac.Util; + +namespace LibHac.FsSrv.Impl; + +public struct IntegrityParam +{ + public HashAlgorithmType HashAlgorithmType; + public bool IsIntegritySeedEnabled; + public HashSalt IntegritySeed; +} + +public static partial class SaveDataTransferUtilityGlobalMethods +{ + internal static int GetIndexById(ushort id) + { + throw new NotImplementedException(); + } + + internal static SaveDataCreationInfo2 InheritSaveDataCreationInfo2(in InitialDataVersion2Detail.Content initialData) + { + throw new NotImplementedException(); + } +} + +public class StorageDuplicator : IDisposable +{ + private SharedRef _sourceFileStorage; + private SharedRef _destinationFileStorage; + private SharedRef _destinationFileSystem; + private long _offset; + private long _restSize; + + public StorageDuplicator(ref readonly SharedRef sourceFileStorage, + ref readonly SharedRef destinationFileStorage, + ref readonly SharedRef destinationFileSystem) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize() + { + throw new NotImplementedException(); + } + + public Result FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result ProcessDuplication(out long outRestSize, Span workBuffer, long sizeToProcess) + { + throw new NotImplementedException(); + } + + public Result ProcessDuplication(out long outRestSize, long sizeToProcess) + { + throw new NotImplementedException(); + } +} + +public class SaveDataInternalStorageAccessor : IDisposable +{ + public class InternalFile : InternalFileWithDigest + { + public InternalFile(ref readonly SharedRef file) : base(in file, in file, blockSize: 1, digestSize: 1) + { + throw new NotImplementedException(); + } + } + + public class InternalFileWithDigest : IDisposable + { + private SharedRef _file; + private SharedRef _digestFile; + private long _blockSize; + private long _digestSize; + + public InternalFileWithDigest(ref readonly SharedRef file, ref readonly SharedRef digestFile, + long blockSize, long digestSize) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public long GetBlockSize() + { + throw new NotImplementedException(); + } + + public SharedRef GetFile() + { + throw new NotImplementedException(); + } + + public SharedRef GetDigestFile() + { + throw new NotImplementedException(); + } + + public long GetFileSize() + { + throw new NotImplementedException(); + } + + public long GetDigestFileSize() + { + throw new NotImplementedException(); + } + + public long GetDigestSize() + { + throw new NotImplementedException(); + } + } + + public class PaddingFile : IFile + { + private long _paddingSize; + + public PaddingFile(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + } + + private SaveDataSpaceId _spaceId; + private ulong _saveDataId; + private Array5> _internalFileWithDigestArray; + private SharedRef _internalStorageFs; + private SharedRef _concatenationStorage; + private SharedRef _concatenationDigestStorage; + private bool _isValid; + + public SaveDataInternalStorageAccessor(SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result InitializeInternalFs(ISaveDataTransferCoreInterface coreInterface, bool isTemporaryTransferSave) + { + throw new NotImplementedException(); + } + + public Result Initialize(ISaveDataTransferCoreInterface coreInterface, bool isTemporaryTransferSave, in Optional hashSalt) + { + throw new NotImplementedException(); + } + + public Result InitializeForTest(in Array5> files) + { + throw new NotImplementedException(); + } + + public bool IsValid() + { + throw new NotImplementedException(); + } + + public Result Invalidate() + { + throw new NotImplementedException(); + } + + public SharedRef GetSaveDataInternalFileSystem() + { + throw new NotImplementedException(); + } + + public Result CommitSaveDataInternalFileSystem(bool isTemporaryTransferSave) + { + throw new NotImplementedException(); + } + + public Result OpenConcatenationStorage(ref SharedRef outStorage) + { + throw new NotImplementedException(); + } + + public Result CalculateThumbnailHash(ref InitialDataVersion2Detail.Hash outHash) + { + throw new NotImplementedException(); + } + + public Result OpenConcatenationSubStorage(ref SharedRef outStorage, long offset, long size) + { + throw new NotImplementedException(); + } + + public Result OpenConcatenationDigestStorage(ref SharedRef outStorage) + { + throw new NotImplementedException(); + } + + public Result OpenConcatenationDigestSubStorage(ref SharedRef outStorage, long offset, long size) + { + throw new NotImplementedException(); + } + + public Result GetIntegrityParam(ref IntegrityParam outParam) + { + throw new NotImplementedException(); + } + + public Result ReadSaveDataExtraData(ref SaveDataExtraData outExtraData) + { + throw new NotImplementedException(); + } + + public Result WriteSaveDataExtraData(in SaveDataExtraData extraData) + { + throw new NotImplementedException(); + } + + public Result ConvertToDigestOffsetAndSize(out long outDigestOffset, out long outDigestSize, long offset, long size) + { + throw new NotImplementedException(); + } +} + +public static partial class SaveDataTransferUtilityGlobalMethods +{ + public static Result OpenSaveDataInternalStorageAccessor(this FileSystemServer fsSrv, + ref SharedRef outAccessor, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public static Result CommitConcatenatedSaveDataStorage(this FileSystemServer fsSrv, IFileSystem fileSystem, + bool isTemporaryTransferSave) + { + throw new NotImplementedException(); + } + + public static Result CalculateFileHash(this FileSystemServer fsSrv, ref InitialDataVersion2Detail.Hash outHash, + ref readonly SharedRef file) + { + throw new NotImplementedException(); + } + + public static Result CheckThumbnailUpdate(this FileSystemServer fsSrv, + in InitialDataVersion2Detail.Hash expectedHash, in InitialDataVersion2Detail.Hash hash) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/SaveDataTransferVersion2.cs b/src/LibHac/FsSrv/Impl/SaveDataTransferVersion2.cs new file mode 100644 index 00000000..55773e99 --- /dev/null +++ b/src/LibHac/FsSrv/Impl/SaveDataTransferVersion2.cs @@ -0,0 +1,260 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Fs.Impl; +using LibHac.FsSrv.Sf; +using LibHac.Sf; +using ISaveDataDivisionExporter = LibHac.FsSrv.Sf.ISaveDataDivisionExporter; +using ISaveDataDivisionImporter = LibHac.FsSrv.Sf.ISaveDataDivisionImporter; + +namespace LibHac.FsSrv.Impl; + +public struct KeySeedPackageV0 +{ + public uint Version; + public Array4 Reserved4; + public byte KeyGeneration; + public Array7 Reserved9; + public AesIv Iv; + public AesMac Mac; + public Array80 Reserved30; + public Array256 Signature; + public Content PackageContent; + + public struct Content + { + public Array16 Unknown; + public KeySeed TransferKeySeed; + public InitialDataMac TransferInitialDataMac; + public Fs.SaveDataTransferManagerVersion2.Challenge Challenge; + public Array64 Reserved; + } +} + +file static class Anonymous +{ + public static Result DecryptoAndVerifyPortContext(Span destination, ReadOnlySpan source, + SaveDataTransferCryptoConfiguration cryptoConfig) + { + throw new NotImplementedException(); + } +} + +file class KeySeedChunkEncryptorFactory : IChunkEncryptorFactory +{ + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private KeySeedPackageV0.Content _keySeedPackage; + private SaveDataTransferCryptoConfiguration.Attributes _attribute; + + public KeySeedChunkEncryptorFactory(SaveDataTransferCryptoConfiguration cryptoConfig, + in KeySeedPackageV0.Content keySeedPackage, SaveDataTransferCryptoConfiguration.Attributes attribute) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Create(ref SharedRef outEncryptor) + { + throw new NotImplementedException(); + } + + private class Encryptor : AesGcmSource.IEncryptor + { + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private KeySeedPackageV0.Content _keySeedPackage; + private SaveDataTransferCryptoConfiguration.Attributes _attribute; + private SharedRef _encryptor; + + public Encryptor(SaveDataTransferCryptoConfiguration cryptoConfig, in KeySeedPackageV0.Content keySeedPackage, + SaveDataTransferCryptoConfiguration.Attributes attribute) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(ref AesGcmStreamHeader header, in AesIv iv) + { + throw new NotImplementedException(); + } + + public Result Update(Span destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public Result GetMac(out AesMac outMac) + { + throw new NotImplementedException(); + } + } +} + +file class KeySeedChunkDecryptorFactory : IChunkDecryptorFactory +{ + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private KeySeedPackageV0.Content _keySeedPackage; + private SaveDataTransferCryptoConfiguration.Attributes _attribute; + + public KeySeedChunkDecryptorFactory(SaveDataTransferCryptoConfiguration cryptoConfig, + in KeySeedPackageV0.Content keySeedPackage, SaveDataTransferCryptoConfiguration.Attributes attribute) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Create(ref SharedRef outDecryptor, in AesMac mac) + { + throw new NotImplementedException(); + } + + private class Decryptor : AesGcmSink.IDecryptor + { + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private KeySeedPackageV0.Content _keySeedPackage; + private SharedRef _decryptor; + private SaveDataTransferCryptoConfiguration.Attributes _attribute; + private AesMac _mac; + + public Decryptor(SaveDataTransferCryptoConfiguration cryptoConfig, in KeySeedPackageV0.Content keySeedPackage, + SaveDataTransferCryptoConfiguration.Attributes attribute, in AesMac mac) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(in AesGcmStreamHeader header) + { + throw new NotImplementedException(); + } + + public Result Update(Span destination, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public Result Verify() + { + throw new NotImplementedException(); + } + } +} + +public class SaveDataTransferManagerVersion2 : ISaveDataTransferManagerWithDivision +{ + private SharedRef _transferInterface; + private SaveDataTransferCryptoConfiguration _cryptoConfig; + private bool _isKeySeedPackageSet; + private Array16 _challengeData; + private KeySeedPackageV0.Content _keySeedPackage; + private SaveDataPorterManager _porterManager; + private SaveDataTransferCryptoConfiguration.Attributes _attribute; + + public SaveDataTransferManagerVersion2(SaveDataTransferCryptoConfiguration cryptoConfig, + ref readonly SharedRef transferInterface, SaveDataPorterManager porterManager) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result GetChallenge(OutBuffer challenge) + { + throw new NotImplementedException(); + } + + public Result SetKeySeedPackage(InBuffer keySeedPackage) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporter(ref SharedRef outExporter, SaveDataSpaceId spaceId, + ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporterForDiffExport(ref SharedRef outExporter, + InBuffer initialData, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataExporterByContext(ref SharedRef outExporter, + InBuffer exportContext) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterDeprecated(ref SharedRef outImporter, + InBuffer initialData, in UserId userId, SaveDataSpaceId spaceId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterForDiffImport(ref SharedRef outImporter, + InBuffer initialData, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterForDuplicateDiffImport(ref SharedRef outImporter, + InBuffer initialData, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporter(ref SharedRef outImporter, InBuffer initialData, + in UserId userId, SaveDataSpaceId spaceId, bool useSwap) + { + throw new NotImplementedException(); + } + + public Result OpenSaveDataImporterByContext(ref SharedRef outImporter, + InBuffer importContext) + { + throw new NotImplementedException(); + } + + public Result CancelSuspendingImport(Ncm.ApplicationId applicationId, in UserId userId) + { + throw new NotImplementedException(); + } + + public Result CancelSuspendingImportByAttribute(in SaveDataAttribute attribute) + { + throw new NotImplementedException(); + } + + public Result SwapSecondary(in SaveDataAttribute attribute, bool doSwap, long primaryCommitId) + { + throw new NotImplementedException(); + } + + private Result DecryptAndVerifyInitialData(out Box outInitialDataContent, + in InitialDataVersion2Detail initialDataEncrypted) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/NcaFileSystemService.cs b/src/LibHac/FsSrv/NcaFileSystemService.cs index 4ae94b87..85d394a2 100644 --- a/src/LibHac/FsSrv/NcaFileSystemService.cs +++ b/src/LibHac/FsSrv/NcaFileSystemService.cs @@ -1,4 +1,6 @@ -using System; +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; using LibHac.Common; using LibHac.Fs; using LibHac.FsSrv.Impl; diff --git a/src/LibHac/FsSrv/SaveDataFileSystemService.cs b/src/LibHac/FsSrv/SaveDataFileSystemService.cs index 8e18d5cd..2c5e92e1 100644 --- a/src/LibHac/FsSrv/SaveDataFileSystemService.cs +++ b/src/LibHac/FsSrv/SaveDataFileSystemService.cs @@ -2437,7 +2437,7 @@ internal class SaveDataFileSystemService : ISaveDataTransferCoreInterface, ISave throw new NotImplementedException(); } - public Result OpenSaveDataMover(ref SharedRef saveMover, SaveDataSpaceId sourceSpaceId, + public Result OpenSaveDataMover(ref SharedRef saveMover, SaveDataSpaceId sourceSpaceId, SaveDataSpaceId destinationSpaceId, NativeHandle workBufferHandle, ulong workBufferSize) { throw new NotImplementedException(); diff --git a/src/LibHac/FsSrv/SaveDataTransferCryptoConfiguration.cs b/src/LibHac/FsSrv/SaveDataTransferCryptoConfiguration.cs index 17b44f1c..26c5ace4 100644 --- a/src/LibHac/FsSrv/SaveDataTransferCryptoConfiguration.cs +++ b/src/LibHac/FsSrv/SaveDataTransferCryptoConfiguration.cs @@ -1,5 +1,6 @@ using System; using LibHac.Common.FixedArrays; +using LibHac.Fs; using LibHac.FsSystem; namespace LibHac.FsSrv; @@ -32,4 +33,18 @@ public class SaveDataTransferCryptoConfiguration SaveDataRepairInitialDataMacBeforeRepair, SaveDataRepairInitialDataMacAfterRepair } + + public enum Attributes { } + + public interface IEncryptor : IDisposable + { + Result Update(Span destination, ReadOnlySpan source); + Result GetMac(out AesMac outMac); + } + + public interface IDecryptor : IDisposable + { + Result Update(Span destination, ReadOnlySpan source); + Result Verify(out bool outIsValid); + } } \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs index 55495058..8356d348 100644 --- a/src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs +++ b/src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs @@ -5,6 +5,6 @@ namespace LibHac.FsSrv.Sf; public interface ISaveDataChunkExporter : IDisposable { - public Result Pull(out ulong bytesRead, OutBuffer buffer, ulong size); - public Result GetRestRawDataSize(out long remainingSize); + public Result Pull(out ulong outBytesRead, OutBuffer buffer, ulong size); + public Result GetRestRawDataSize(out long outRemainingSize); } \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataDivisionExporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataDivisionExporter.cs index 44dca74a..d6019e91 100644 --- a/src/LibHac/FsSrv/Sf/ISaveDataDivisionExporter.cs +++ b/src/LibHac/FsSrv/Sf/ISaveDataDivisionExporter.cs @@ -8,16 +8,16 @@ namespace LibHac.FsSrv.Sf; public interface ISaveDataDivisionExporter : IDisposable { public Result SetDivisionCount(int divisionCount); - public Result ReadSaveDataExtraData(OutBuffer extraData); + public Result ReadSaveDataExtraData(OutBuffer outExtraData); public Result OpenSaveDataDiffChunkIterator(ref SharedRef outIterator); public Result OpenSaveDataChunkExporter(ref SharedRef outExporter, uint chunkId); public Result CancelExport(); - public Result SuspendExport(OutBuffer exportContext); - public Result GetKeySeed(out KeySeed keySeed); - public Result GetInitialDataMac(out InitialDataMac initialDataMac); + public Result SuspendExport(OutBuffer outExportContext); + public Result GetKeySeed(out KeySeed outKeySeed); + public Result GetInitialDataMac(out InitialDataMac outInitialDataMac); public Result FinalizeExport(); - public Result GetInitialDataMacKeyGeneration(out int keyGeneration); - public Result GetImportInitialDataAad(out InitialDataAad initialDataAad); + public Result GetInitialDataMacKeyGeneration(out int outKeyGeneration); + public Result GetImportInitialDataAad(out InitialDataAad outInitialDataAad); public Result SetExportInitialDataAad(in InitialDataAad initialDataAad); - public Result GetReportInfo(out ExportReportInfo reportInfo); + public Result GetReportInfo(out ExportReportInfo outReportInfo); } \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataDivisionImporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataDivisionImporter.cs index 2d7303fd..c9196b31 100644 --- a/src/LibHac/FsSrv/Sf/ISaveDataDivisionImporter.cs +++ b/src/LibHac/FsSrv/Sf/ISaveDataDivisionImporter.cs @@ -7,15 +7,15 @@ namespace LibHac.FsSrv.Sf; public interface ISaveDataDivisionImporter : IDisposable { - public Result ReadSaveDataExtraData(OutBuffer extraData); + public Result ReadSaveDataExtraData(OutBuffer outExtraData); public Result OpenSaveDataDiffChunkIterator(ref SharedRef outIterator); - public Result InitializeImport(out long remaining, long sizeToProcess); + public Result InitializeImport(out long outRemaining, long sizeToProcess); public Result FinalizeImport(); public Result CancelImport(); - public Result GetImportContext(OutBuffer context); + public Result GetImportContext(OutBuffer outImportContext); public Result SuspendImport(); public Result FinalizeImportWithoutSwap(); public Result OpenSaveDataChunkImporter(ref SharedRef outImporter, uint chunkId); - public Result GetImportInitialDataAad(out InitialDataAad initialDataAad); - public Result GetReportInfo(out ImportReportInfo reportInfo); + public Result GetImportInitialDataAad(out InitialDataAad outInitialDataAad); + public Result GetReportInfo(out ImportReportInfo outReportInfo); } \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataExporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataExporter.cs index 6b5a98b5..b6b22708 100644 --- a/src/LibHac/FsSrv/Sf/ISaveDataExporter.cs +++ b/src/LibHac/FsSrv/Sf/ISaveDataExporter.cs @@ -6,8 +6,8 @@ namespace LibHac.FsSrv.Sf; public interface ISaveDataExporter : IDisposable { - public Result GetSaveDataInfo(out SaveDataInfo info); - public Result GetRestSize(out ulong remainingSize); - public Result Pull(out ulong bytesRead, OutBuffer buffer); - public Result PullInitialData(OutBuffer initialData); + public Result GetSaveDataInfo(out SaveDataInfo outInfo); + public Result GetRestSize(out ulong outRemainingSize); + public Result Pull(out ulong outBytesRead, OutBuffer buffer); + public Result PullInitialData(OutBuffer initialDataBuffer); } \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataImporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataImporter.cs index f710ebe4..5c1b7328 100644 --- a/src/LibHac/FsSrv/Sf/ISaveDataImporter.cs +++ b/src/LibHac/FsSrv/Sf/ISaveDataImporter.cs @@ -6,8 +6,8 @@ namespace LibHac.FsSrv.Sf; public interface ISaveDataImporter : IDisposable { - public Result GetSaveDataInfo(out SaveDataInfo info); - public Result GetRestSize(out ulong remainingSize); + public Result GetSaveDataInfo(out SaveDataInfo outInfo); + public Result GetRestSize(out ulong outRemainingSize); public Result Push(InBuffer buffer); // Can't name the method "Finalize" because it's basically a reserved method in .NET public Result FinalizeImport(); diff --git a/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForSaveDataRepair.cs b/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForSaveDataRepair.cs index 0565b01e..a7edf5e0 100644 --- a/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForSaveDataRepair.cs +++ b/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForSaveDataRepair.cs @@ -9,10 +9,10 @@ public interface ISaveDataTransferManagerForSaveDataRepair : IDisposable { public Result GetChallenge(OutBuffer challenge); public Result SetKeyPackage(InBuffer keyPackage); - public Result OpenSaveDataExporterAndGetEncryptedKey(ref SharedRef outExporter, out RsaEncryptedKey key, SaveDataSpaceId spaceId, ulong saveDataId); - public Result PrepareOpenSaveDataImporter(out RsaEncryptedKey key); - public Result OpenSaveDataImporterForSaveDataAfterRepair(ref SharedRef outImporter, InBuffer initialDataBeforeRepair, InBuffer initialDataAfterRepair, in UserId userId, SaveDataSpaceId spaceId); - public Result OpenSaveDataImporterForSaveDataBeforeRepair(ref SharedRef outImporter, InBuffer initialData, in UserId userId, SaveDataSpaceId spaceId); - public Result OpenSaveDataExporterWithKey(ref SharedRef outExporter, in AesKey key, SaveDataSpaceId spaceId, ulong saveDataId); - public Result OpenSaveDataImporterWithKey(ref SharedRef outImporter, in AesKey key, InBuffer initialData, in UserId userId, ulong saveDataSpaceId); + public Result OpenSaveDataExporterAndGetEncryptedKey(ref SharedRef outExporter, OutBuffer outEncryptedKey, SaveDataSpaceId spaceId, ulong saveDataId); + public Result PrepareOpenSaveDataImporter(OutBuffer outEncryptedKey); + public Result OpenSaveDataImporterForSaveDataAfterRepair(ref SharedRef outImporter, InBuffer initialDataBeforeRepair, InBuffer initialDataAfterRepair, UserId userId, SaveDataSpaceId spaceId); + public Result OpenSaveDataImporterForSaveDataBeforeRepair(ref SharedRef outImporter, InBuffer initialData, UserId userId, SaveDataSpaceId spaceId); + public Result OpenSaveDataExporterWithKey(ref SharedRef outExporter, InBuffer key, SaveDataSpaceId spaceId, ulong saveDataId); + public Result OpenSaveDataImporterWithKey(ref SharedRef outImporter, InBuffer key, InBuffer initialData, UserId userId, ulong saveDataSpaceId); } \ No newline at end of file diff --git a/src/LibHac/FsSystem/ApplicationTemporaryFileSystem.cs b/src/LibHac/FsSystem/ApplicationTemporaryFileSystem.cs index 4f484185..11254455 100644 --- a/src/LibHac/FsSystem/ApplicationTemporaryFileSystem.cs +++ b/src/LibHac/FsSystem/ApplicationTemporaryFileSystem.cs @@ -1,12 +1,90 @@ -using System; +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; using LibHac.Common; using LibHac.Fs; using LibHac.Fs.Fsa; +using LibHac.FsSystem.Save; namespace LibHac.FsSystem; -public class ApplicationTemporaryFileSystem : IFileSystem, ISaveDataExtraDataAccessor +file class ApplicationTemporaryFile : IFile { + private UniqueRef _file; + + public ApplicationTemporaryFile(ref UniqueRef file) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class ApplicationTemporaryFileSystem : IFileSystem, ICacheableSaveDataFileSystem, ISaveDataExtraDataAccessor +{ + private SharedRef _baseStorage; + private IntegritySaveDataFileSystemDriver _saveFsDriver; + private bool _isInitialized; + private ISaveDataExtraDataAccessorObserver _cacheObserver; + private ulong _saveDataId; + private SaveDataSpaceId _spaceId; + + public ApplicationTemporaryFileSystem() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + public Result Initialize(ref readonly SharedRef baseStorage, IBufferManager bufferManager, + IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) { throw new NotImplementedException(); @@ -68,6 +146,41 @@ public class ApplicationTemporaryFileSystem : IFileSystem, ISaveDataExtraDataAcc throw new NotImplementedException(); } + protected override Result DoCommitProvisionally(long counter) + { + throw new NotImplementedException(); + } + + protected override Result DoRollback() + { + throw new NotImplementedException(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + public bool IsSaveDataFileSystemCacheEnabled() + { + throw new NotImplementedException(); + } + + public Result RollbackOnlyModified() + { + throw new NotImplementedException(); + } + + protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) + { + throw new NotImplementedException(); + } + public Result WriteExtraData(in SaveDataExtraData extraData) { throw new NotImplementedException(); diff --git a/src/LibHac/FsSystem/Bitmap.cs b/src/LibHac/FsSystem/Bitmap.cs new file mode 100644 index 00000000..0366607e --- /dev/null +++ b/src/LibHac/FsSystem/Bitmap.cs @@ -0,0 +1,91 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs; + +namespace LibHac.FsSystem; + +public class Bitmap : IDisposable +{ + private const int IterateCacheSize = 0x80; + private const uint BlockSize = 8; + private const uint BitmapSizeAlignment = 0x20; + + public struct Iterator + { + public uint Index; + } + + private uint _bitCount; + private SubStorage _storage; + + public Bitmap() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public static long QuerySize(uint bitCount) + { + throw new NotImplementedException(); + } + + public void Initialize(uint bitCount, SubStorage bitmapStorage) + { + throw new NotImplementedException(); + } + + public static Result Format(uint bitCount, SubStorage storage) + { + throw new NotImplementedException(); + } + + public static Result Expand(uint bitCountOld, uint bitCountNew, SubStorage storage) + { + throw new NotImplementedException(); + } + + public Result IterateBegin(ref Iterator it, uint index) + { + throw new NotImplementedException(); + } + + private Result ReadBlock(Span buffer, uint index) + { + throw new NotImplementedException(); + } + + public Result IterateNext(out uint outZeroCount, out uint outOneCount, ref Iterator it) + { + throw new NotImplementedException(); + } + + public Result LimitedIterateNext(out uint outZeroCount, out uint outOneCount, ref Iterator it, uint maxZeroCount, uint maxOneCount) + { + throw new NotImplementedException(); + } + + public Result Reverse(uint index, uint count) + { + throw new NotImplementedException(); + } + + public Result Clear() + { + throw new NotImplementedException(); + } + + private Result GetBitmap32(out uint outValue, uint index) + { + throw new NotImplementedException(); + } + + private Result GetBit(out bool outValue, uint index) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/BitmapUtils.cs b/src/LibHac/FsSystem/BitmapUtils.cs index 95ce63af..038b5dbf 100644 --- a/src/LibHac/FsSystem/BitmapUtils.cs +++ b/src/LibHac/FsSystem/BitmapUtils.cs @@ -1,4 +1,7 @@ -using LibHac.Diag; +using System; +using System.Buffers.Binary; +using LibHac.Diag; +using LibHac.Util; namespace LibHac.FsSystem; @@ -10,6 +13,26 @@ public static class BitmapUtils Assert.SdkRequiresGreater(value, 0u); const int intBitCount = 32; - return intBitCount - 1 - Util.BitUtil.CountLeadingZeros(value); + return intBitCount - 1 - BitUtil.CountLeadingZeros(value); + } + + internal static uint ReadU32(ReadOnlySpan buffer, int offset) + { + return BinaryPrimitives.ReadUInt32LittleEndian(buffer.Slice(offset)); + } + + internal static void WriteU32(Span buffer, int offset, uint value) + { + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), value); + } + + internal static int CountLeadingZeros(uint value) + { + return BitUtil.CountLeadingZeros(value); + } + + internal static int CountLeadingOnes(uint value) + { + return CountLeadingZeros(~value); } } \ No newline at end of file diff --git a/src/LibHac/FsSystem/DuplexBitmap.cs b/src/LibHac/FsSystem/DuplexBitmap.cs new file mode 100644 index 00000000..c37f8b19 --- /dev/null +++ b/src/LibHac/FsSystem/DuplexBitmap.cs @@ -0,0 +1,116 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs; + +namespace LibHac.FsSystem; + +public class DuplexBitmap : IDisposable +{ + public struct Iterator + { + public uint Index; + public uint IndexEnd; + } + + public static long QuerySize(uint bitCount) + { + throw new NotImplementedException(); + } + + public static Result Format(uint size, in ValueSubStorage storage, in ValueSubStorage storageOriginal) + { + throw new NotImplementedException(); + } + + public static Result Expand(uint bitCountOld, uint bitCountNew, in ValueSubStorage storage, in ValueSubStorage storageOriginal) + { + throw new NotImplementedException(); + } + + public DuplexBitmap() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public void Initialize(uint bitCount, in ValueSubStorage storage, in ValueSubStorage storageOriginal) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public void IterateBegin(out Iterator outIterator, uint index, ulong count) + { + throw new NotImplementedException(); + } + + public Result IterateNext(out ulong outCountZero, out ulong outCountOne, ref Iterator iter) + { + throw new NotImplementedException(); + } + + public Result IterateOriginalNext(out ulong outCountZero, out ulong outCountOne, ref Iterator iter) + { + throw new NotImplementedException(); + } + + public Result ReadBitmap32(out uint outBitmap, uint index) + { + throw new NotImplementedException(); + } + + public Result ReadOriginalBitmap32(out uint outBitmap, uint index) + { + throw new NotImplementedException(); + } + + public void IterateOriginalBegin(out Iterator outIterator, uint index, ulong count) + { + throw new NotImplementedException(); + } + + public Result MarkModified(uint index, ulong count) + { + throw new NotImplementedException(); + } + + public Result Flush() + { + throw new NotImplementedException(); + } + + public Result Invalidate() + { + throw new NotImplementedException(); + } + + private Result ReadBlock(Span outBuf, out uint outReadSize, ulong maxBytes, uint index, SubStorage storage) + { + throw new NotImplementedException(); + } + + private Result FindBitCount(out ulong outTotalCount, out Iterator outIterator, Span outBuf, + out uint outReadIndex, out uint outRead, bool countZeros, SubStorage storage) + { + throw new NotImplementedException(); + } + + private Result IterateNextImpl(out ulong outCountZero, out ulong outCountOne, ref Iterator iter, SubStorage storage) + { + throw new NotImplementedException(); + } + + private Result ReadBitmap32Impl(out uint outBitmap, uint index, SubStorage storage) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/DuplexBitmapHolder.cs b/src/LibHac/FsSystem/DuplexBitmapHolder.cs new file mode 100644 index 00000000..11d76c3d --- /dev/null +++ b/src/LibHac/FsSystem/DuplexBitmapHolder.cs @@ -0,0 +1,58 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs; + +namespace LibHac.FsSystem; + +public class DuplexBitmapHolder : IDisposable +{ + private DuplexBitmap _bitmap; + private ValueSubStorage _updateStorage; + private ValueSubStorage _originalStorage; + private uint _blockCount; + + public DuplexBitmapHolder() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public uint GetBlockCount() => throw new NotImplementedException(); + public ref readonly ValueSubStorage GetOriginalStorage() => throw new NotImplementedException(); + public ref readonly ValueSubStorage GetUpdateStorage() => throw new NotImplementedException(); + + public static Result Format(uint size, SubStorage storage, SubStorage storageOriginal) + { + throw new NotImplementedException(); + } + + public static Result Expand(uint bitCountOld, uint bitCountNew, in ValueSubStorage storage, in ValueSubStorage storageOriginal) + { + throw new NotImplementedException(); + } + + public void Initialize(uint blockCount, in ValueSubStorage storage1, in ValueSubStorage storage2) + { + throw new NotImplementedException(); + } + + public void InitializeForRead(uint blockCount, in ValueSubStorage storage1, in ValueSubStorage storage2) + { + throw new NotImplementedException(); + } + + public void RemountForWrite() + { + throw new NotImplementedException(); + } + + private void SwapDuplexBitmapForHierarchicalDuplexStorage(ref DuplexBitmapHolder outBitmap) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/DuplexStorage.cs b/src/LibHac/FsSystem/DuplexStorage.cs new file mode 100644 index 00000000..32149ec5 --- /dev/null +++ b/src/LibHac/FsSystem/DuplexStorage.cs @@ -0,0 +1,89 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common.FixedArrays; +using LibHac.Fs; + +namespace LibHac.FsSystem; + +public class DuplexStorage : IStorage +{ + private DuplexBitmap _duplexBitmap; + private Array2 _storages; + private long _countShiftBlock; + private long _sizeBlock; + private IBufferManager _bufferManager; + private bool _isReadOnly; + + public DuplexStorage() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public long GetBlockSize() + { + throw new NotImplementedException(); + } + + public void SetReadOnly(bool isReadOnly) + { + throw new NotImplementedException(); + } + + public void Initialize(DuplexBitmap bitmap, in ValueSubStorage storageData1, in ValueSubStorage storageData2, + long sizeBlock, IBufferManager buffer) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + + private Result ReadDuplexBits(out uint outOriginalBits, out uint outModifiedBits, long offset, ulong bitCount) + { + throw new NotImplementedException(); + } + + private Result UpdateModifiedBits(long offset, long offsetEnd) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/HierarchicalDuplexStorage.cs b/src/LibHac/FsSystem/HierarchicalDuplexStorage.cs new file mode 100644 index 00000000..3e136ffb --- /dev/null +++ b/src/LibHac/FsSystem/HierarchicalDuplexStorage.cs @@ -0,0 +1,221 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Os; + +namespace LibHac.FsSystem; + +file static class Anonymous +{ + public static bool IsFutureVersion(uint version) + { + throw new NotImplementedException(); + } +} + +public struct HierarchicalDuplexInformation +{ + public struct Entry + { + public Fs.Int64 Offset; + public Fs.Int64 Size; + public int OrderBlock; + } + + public Array3 Info; +} + +public struct HierarchicalDuplexMetaInformation +{ + public uint Magic; + public uint Version; + public HierarchicalDuplexInformation InfoDuplex; +} + +public struct HierarchicalDuplexSizeSet +{ + public Array3 Sizes; +} + +public class HierarchicalDuplexStorageControlArea : IDisposable +{ + private ValueSubStorage _storage; + private HierarchicalDuplexMetaInformation _meta; + + public HierarchicalDuplexStorageControlArea() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + private static Result CreateMetaInformation(ref HierarchicalDuplexMetaInformation meta, long blockSize, long sizeData) + { + throw new NotImplementedException(); + } + + public static Result QuerySize(ref HierarchicalDuplexSizeSet outSizeSet, long blockSize, long sizeData) + { + throw new NotImplementedException(); + } + + public static Result Format(ref ValueSubStorage storageMeta, long blockSize, long sizeData) + { + throw new NotImplementedException(); + } + + public static Result Expand(ref ValueSubStorage storageMeta, long blockSize, long sizeData) + { + throw new NotImplementedException(); + } + + public ref readonly HierarchicalDuplexMetaInformation GetMeta() => throw new NotImplementedException(); + + public Result Initialize(in ValueSubStorage storage) + { + throw new NotImplementedException(); + } + + public Result FinalizeObject() + { + throw new NotImplementedException(); + } +} + +public class HierarchicalDuplexStorage : IStorage +{ + private DuplexStorage _duplexStorageMaster; + private DuplexStorage _duplexStorageL1; + private DuplexStorage _duplexStorageData; + + private DuplexBitmapHolder _masterBitmapHolderWrite; + private DuplexBitmapHolder _masterBitmapHolderRead; + private DuplexBitmapHolder _bitmapHolder3; + private DuplexBitmapHolder _bitmapHolderL1; + + private ValueSubStorage _trimmedStorageL1A; + private ValueSubStorage _trimmedStorageL1B; + private ValueSubStorage _trimmedStorageDataA; + private ValueSubStorage _trimmedStorageDataB; + + private TruncatedSubStorage[] _storages; + private BlockCacheBufferedStorage[] _bufferedStorages; + + private long _sizeData; + private IBufferManager _bufferManager; + private SdkRecursiveMutex _mutex; + private bool _isWritten; + + public HierarchicalDuplexStorage() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static Result Format( + in HierarchicalDuplexInformation infoDuplex, + in ValueSubStorage storageMasterA, + in ValueSubStorage storageMasterB, + in ValueSubStorage storageL1A, + in ValueSubStorage storageL1B, + IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public static Result Expand( + in HierarchicalDuplexInformation infoDuplexOld, + in HierarchicalDuplexInformation infoDuplexNew, + in ValueSubStorage storageMasterA, + in ValueSubStorage storageMasterB, + in ValueSubStorage storageL1A, + in ValueSubStorage storageL1B, + IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public Result Initialize(in HierarchicalDuplexInformation infoDuplex, + in ValueSubStorage storageMasterA, + in ValueSubStorage storageMasterB, + in ValueSubStorage storageL1A, + in ValueSubStorage storageL1B, + in ValueSubStorage storageDataA, + in ValueSubStorage storageDataB, + bool isStorageAOriginal, + IBufferManager bufferManager, + SdkRecursiveMutex mutex) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public void ClearCommitFlag() + { + throw new NotImplementedException(); + } + + public Result SwapDuplexBitmap() + { + throw new NotImplementedException(); + } + + public bool NeedCommit() + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + + public void Remount() + { + throw new NotImplementedException(); + } + + private static Result CopyStorage(in ValueSubStorage destStorage, in ValueSubStorage sourceStorage, long size) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/IMacGenerator.cs b/src/LibHac/FsSystem/IMacGenerator.cs new file mode 100644 index 00000000..61be3e69 --- /dev/null +++ b/src/LibHac/FsSystem/IMacGenerator.cs @@ -0,0 +1,8 @@ +using System; + +namespace LibHac.FsSystem; + +public interface IMacGenerator +{ + Result Generate(Span macDestBuffer, ReadOnlySpan data); +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/JournalStorage.cs b/src/LibHac/FsSystem/JournalStorage.cs new file mode 100644 index 00000000..366edf49 --- /dev/null +++ b/src/LibHac/FsSystem/JournalStorage.cs @@ -0,0 +1,192 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value +using System; +using LibHac.Common.FixedArrays; +using LibHac.Fs; + +namespace LibHac.FsSystem; + +internal struct JournalStorageControlArea +{ + public uint Magic; + public uint Version; + public long TotalSize; + public long JournalSize; + public long SizeBlock; + public MappingTableControlArea MappingTableControlArea; + public Array464 Reserved; +} + +public class JournalStorage : IStorage +{ + private JournalStorageControlArea _controlArea; + private MappingTable _mappingTable; + private ValueSubStorage _dataStorage; + private bool _isMappingTableFrozen; + + public JournalStorage() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static void QueryMappingMetaSize(out long outTableSize, out long outBitmapSizeUpdatedPhysical, + out long outBitmapSizeUpdatedVirtual, out long outBitmapSizeUnassigned, long sizeArea, long sizeReserved, + long sizeBlock) + { + throw new NotImplementedException(); + } + + public static Result Format( + in ValueSubStorage storageJournalControlArea, + in ValueSubStorage storageJournalTable, + in ValueSubStorage storageBitmapPhysical, + in ValueSubStorage storageBitmapVirtual, + in ValueSubStorage storageBitmapUnassigned, + long sizeArea, + long sizeReservedArea, + long sizeBlock) + { + throw new NotImplementedException(); + } + + public static Result Expand( + in ValueSubStorage storageJournalControlArea, + in ValueSubStorage storageJournalTable, + in ValueSubStorage storageBitmapPhysical, + in ValueSubStorage storageBitmapVirtual, + in ValueSubStorage storageBitmapUnassigned, + long sizeAreaNew, + long sizeReservedAreaNew) + { + throw new NotImplementedException(); + } + + public long GetBlockSize() + { + throw new NotImplementedException(); + } + + public long GetDataAreaSize() + { + throw new NotImplementedException(); + } + + public long GetReservedAreaSize() + { + throw new NotImplementedException(); + } + + public ValueSubStorage CreateDataStorage() + { + throw new NotImplementedException(); + } + + public bool IsMappingTableFrozen() + { + throw new NotImplementedException(); + } + + public void SetMappingTableFrozen(bool isFrozen) + { + throw new NotImplementedException(); + } + + private long AlignAddress(long address) + { + throw new NotImplementedException(); + } + + private long AlignDown64(long address, long blockSize) + { + throw new NotImplementedException(); + } + + private long AlignUpAddress(long address) + { + throw new NotImplementedException(); + } + + private long AlignUp64(long address, long blockSize) + { + throw new NotImplementedException(); + } + + public Result Initialize( + in ValueSubStorage storageJournalControlArea, + in ValueSubStorage storageJournalTable, + in ValueSubStorage storageJournalBitmapPhysical, + in ValueSubStorage storageJournalBitmapVirtual, + in ValueSubStorage storageJournalBitmapUnassigned, + in ValueSubStorage storageData) + { + throw new NotImplementedException(); + } + + private Result GetPhysicalAddress(out long outValue, uint index) + { + throw new NotImplementedException(); + } + + private Result MarkUpdate(long offset, long size) + { + throw new NotImplementedException(); + } + + public Result Commit() + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + + private delegate Result IterateMappingTableFunc(long offset, long size, ref IterateMappingTableClosure closure); + + private ref struct IterateMappingTableClosure + { + public ReadOnlySpan InBuffer; + public Span OutBuffer; + public JournalStorage JournalStorage; + public OperationId OperationId; + } + + private Result IterateMappingTable(long offset, long size, IterateMappingTableFunc func, + ref IterateMappingTableClosure closure) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/MappingTable.cs b/src/LibHac/FsSystem/MappingTable.cs new file mode 100644 index 00000000..c474166b --- /dev/null +++ b/src/LibHac/FsSystem/MappingTable.cs @@ -0,0 +1,221 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using System.Runtime.InteropServices; +using LibHac.Common.FixedArrays; +using LibHac.Fs; + +namespace LibHac.FsSystem; + +[StructLayout(LayoutKind.Sequential)] +public struct MappingTableControlArea +{ + public uint Version; + public uint AvailableBlockCount; + public uint ReservedBlockCount; + public Array4 Reserved; +} + +public class MappingTable : IDisposable +{ + private struct MappingEntry + { + public uint PhysicalIndex; + public uint VirtualIndex; + } + + public struct Iterator + { + public uint VirtualIndex; + public uint PhysicalIndex; + public uint CountContinue; + public uint CountRemain; + + public Iterator() + { + throw new NotImplementedException(); + } + + public readonly uint GetBlockCount() + { + throw new NotImplementedException(); + } + + public readonly uint GetPhysicalIndex() + { + throw new NotImplementedException(); + } + } + + private uint _version; + private uint _mappingEntryCount; + private uint _journalBlockCount; + + private ValueSubStorage _tableStorage; + private ValueSubStorage _bitmapUpdatedPhysicalStorage; + private ValueSubStorage _bitmapUpdatedVirtualStorage; + private ValueSubStorage _bitmapUnassignedStorage; + + private Bitmap _bitmapUpdatedPhysical; + private Bitmap _bitmapUpdatedVirtual; + private Bitmap _bitmapUnassigned; + + public MappingTable() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + private uint GetTotalBlockCount() + { + throw new NotImplementedException(); + } + + private static uint GetValidIndex(uint index) + { + throw new NotImplementedException(); + } + + private static bool IsPhysicalIndex(uint index) + { + throw new NotImplementedException(); + } + + private static uint PhysicalIndex(uint virtualIndex) + { + throw new NotImplementedException(); + } + + public static uint MakeIndex(long value) + { + throw new NotImplementedException(); + } + + public static void QueryMappingMetaSize(out long outTableSize, out long outBitmapSizeUpdatedPhysical, + out long outBitmapSizeUpdatedVirtual, out long outBitmapSizeUnassigned, uint availableBlocks, + uint journalBlocks) + { + throw new NotImplementedException(); + } + + public static Result Format(SubStorage storageMappingControlArea, SubStorage storageTable, + SubStorage storageBitmapPhysical, SubStorage storageBitmapVirtual, SubStorage storageBitmapUnassigned, + uint blockCountAvailableArea, uint blockCountReservedArea) + { + throw new NotImplementedException(); + } + + public static Result Expand(SubStorage storageMappingControlArea, SubStorage storageTable, + SubStorage storageBitmapPhysical, SubStorage storageBitmapVirtual, SubStorage storageBitmapUnassigned, + uint blockCountAreaNew, uint blockCountReservedAreaNew) + { + throw new NotImplementedException(); + } + + public Result Initialize(SubStorage storageMappingControlArea, SubStorage storageTable, + SubStorage storageBitmapPhysical, SubStorage storageBitmapVirtual, SubStorage storageBitmapUnassigned) + { + throw new NotImplementedException(); + } + + private Result CheckPhysicalIndex(uint index) + { + throw new NotImplementedException(); + } + + private Result CheckVirtualIndex(uint index) + { + throw new NotImplementedException(); + } + + private Result ReadMappingEntry(out MappingEntry outValue, uint index) + { + throw new NotImplementedException(); + } + + private Result ReadMappingEntries(Span buffer, uint index, int count) + { + throw new NotImplementedException(); + } + + private Result WriteMappingEntry(in MappingEntry entry, uint index) + { + throw new NotImplementedException(); + } + + private Result WriteMappingEntries(ReadOnlySpan entries, uint index) + { + throw new NotImplementedException(); + } + + public Result GetPhysicalIndex(out uint outValue, uint index) + { + throw new NotImplementedException(); + } + + private Result MarkAssignment(out uint outIndexDst, out uint outCountAssign, uint index, uint count) + { + throw new NotImplementedException(); + } + + private Result MarkUpdateRecursively(out bool outNeedCopyHead, out uint outHeadSrc, out uint outHeadDst, + out bool outNeedCopyTail, out uint outTailSrc, out uint outTailDst, uint index, uint count) + { + throw new NotImplementedException(); + } + + public Result MarkUpdate(out bool outNeedCopyHead, out uint outHeadSrc, out uint outHeadDst, + out bool outNeedCopyTail, out uint outTailSrc, out uint outTailDst, uint index, uint count) + { + throw new NotImplementedException(); + } + + public Result MakeIterator(out Iterator outIterator, uint index, uint count) + { + throw new NotImplementedException(); + } + + public Result UpdateIterator(ref Iterator it) + { + throw new NotImplementedException(); + } + + public Result InvalidateCache() + { + throw new NotImplementedException(); + } + + private Result UpdateMapTable(uint physicalIndex, uint virtualIndex, uint countContinue) + { + throw new NotImplementedException(); + } + + private Result AddUnassignedListIteratively(bool useVirtualIndex) + { + throw new NotImplementedException(); + } + + private Result AddUnassignedList(uint index, uint count, bool useVirtualIndex) + { + throw new NotImplementedException(); + } + + public Result Commit() + { + throw new NotImplementedException(); + } + + public Result Rollback() + { + throw new NotImplementedException(); + } + + private Result GetUnassignedCount(out uint outCount) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/ProxyStorage.cs b/src/LibHac/FsSystem/ProxyStorage.cs new file mode 100644 index 00000000..b42f128a --- /dev/null +++ b/src/LibHac/FsSystem/ProxyStorage.cs @@ -0,0 +1,60 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs; +using LibHac.Os; + +namespace LibHac.FsSystem; + +public class ProxyStorage : IStorage +{ + private SharedRef _storage; + private Result _resultOnInvalidated; + private ReaderWriterLock _rwLock; + + public ProxyStorage(ref readonly SharedRef baseStorage, Result resultOnInvalidated) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public void Invalidate() + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/RemapStorage.cs b/src/LibHac/FsSystem/RemapStorage.cs new file mode 100644 index 00000000..e848f82a --- /dev/null +++ b/src/LibHac/FsSystem/RemapStorage.cs @@ -0,0 +1,361 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Os; + +namespace LibHac.FsSystem; + +public class RemapStorage : IStorage +{ + private struct ControlArea + { + public uint Magic; + public int Version; + public int CountMapEntries; + public int SegmentCount; + public int SegmentBits; + public Array44 Reserved; + } + + private ControlArea _controlArea; + private ValueSubStorage _controlAreaStorage; + private ValueSubStorage _mapEntryStorage; + private MapEntryCache _mapEntryCache; + private Array4 _storageEntries; + private bool _isInitialized; + private bool _isDirty; + + public RemapStorage() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static long QueryMetaSize() + { + throw new NotImplementedException(); + } + + public static long QueryEntryTableSize(int countMapUpdate) + { + throw new NotImplementedException(); + } + + public static long GetMapUpdateCountLowerBound(long sizeEntry) + { + throw new NotImplementedException(); + } + + public static long GetMapUpdateCountUpperBound(long sizeEntry) + { + throw new NotImplementedException(); + } + + public static Result Format(ref ValueSubStorage storageMeta, int countMaxMaps) + { + throw new NotImplementedException(); + } + + public Result Initialize(in ValueSubStorage storageMeta, in ValueSubStorage storageEntry, long alignmentSmall, + long alignmentLarge) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result RegisterMap(out long outOffsetVirtual, long size, long alignment, int storageType) + { + throw new NotImplementedException(); + } + + public long GetEntryTableSize() + { + throw new NotImplementedException(); + } + + public long GetMapUpdateCount() + { + throw new NotImplementedException(); + } + + public long GetMapSizeMax() + { + throw new NotImplementedException(); + } + + public long GetAlignmentSmall() + { + throw new NotImplementedException(); + } + + public long GetAlignmentLarge() + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + + [NonCopyableDisposable] + private struct StorageEntry + { + private long _offsetPhysicalNextSmall; + private long _offsetPhysicalNextLarge; + private ValueSubStorage _storage; + private bool _isRegistered; + + public StorageEntry(in StorageEntry other) + { + throw new NotImplementedException(); + } + + public StorageEntry() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public void Initialize(long offsetPhysicalNextSmall, long offsetPhysicalNextLarge, long alignmentSmall, + long alignmentLarge) + { + throw new NotImplementedException(); + } + + public void Set(in StorageEntry other) + { + throw new NotImplementedException(); + } + + public readonly bool IsRegistered() + { + throw new NotImplementedException(); + } + + public long GetOffsetPhysicalNextLarge() + { + throw new NotImplementedException(); + } + + public long GetOffsetPhysicalNextSmall() + { + throw new NotImplementedException(); + } + + public void SetOffsetPhysicalNextLarge(long offset) + { + throw new NotImplementedException(); + } + + public void SetOffsetPhysicalNextSmall(long offset) + { + throw new NotImplementedException(); + } + + public ref ValueSubStorage GetStorage() + { + throw new NotImplementedException(); + } + + public void SetStorage(in ValueSubStorage storage) + { + throw new NotImplementedException(); + } + } + + private Result InitializeStorageEntries() + { + throw new NotImplementedException(); + } + + private Result ReadMapEntry(out MapEntry outEntry, int index) + { + throw new NotImplementedException(); + } + + private Result WriteMapEntry(in MapEntry entry, int index) + { + throw new NotImplementedException(); + } + + private long MakeVirtualOffset(long higherBits, long lowerBits) + { + throw new NotImplementedException(); + } + + private long GetVirtualOffsetLowerBitsMask() + { + throw new NotImplementedException(); + } + + private long GetVirtualOffsetHigherBitsMask() + { + throw new NotImplementedException(); + } + + private long GetMapEntriesCountMax() + { + throw new NotImplementedException(); + } + + private Result RegisterMapCore(long offset, long sizeNew, long sizeOld, long alignment, int storageType) + { + throw new NotImplementedException(); + } + + private Result MakeMapEntry(out MapEntry outMapEntry, ref StorageEntry storageEntry, ref ControlArea controlArea, + long offset, long size, long alignment, int storageType) + { + throw new NotImplementedException(); + } + + private Result AddMapEntries(ReadOnlySpan mapEntries) + { + throw new NotImplementedException(); + } + + private delegate Result IterateMappingEntriesFunc(IStorage storage, long offset, long sizeAccess, long sizeAccessed, + ref IterateMappingEntriesClosure closure); + + private ref struct IterateMappingEntriesClosure + { + public ReadOnlySpan InBuffer; + public Span OutBuffer; + public OperationId OperationId; + } + + private Result IterateMappingEntries(long offset, long size, IterateMappingEntriesFunc func, + ref IterateMappingEntriesClosure closure) + { + throw new NotImplementedException(); + } + + private ref MapEntryCache GetCache(long offset) + { + throw new NotImplementedException(); + } + + private void ClearAllCaches() + { + throw new NotImplementedException(); + } + + private struct MapEntry + { + public long OffsetVirtual; + public long OffsetPhysical; + public long Size; + public int Alignment; + public int StorageType; + } + + private struct MapEntryHolder + { + public MapEntry Entry; + public int Index; + } + + private struct MapIterator + { + private RemapStorage _remapStorage; + private MapEntry _entry; + private int _indexMapEntryCache; + private int _storageType; + private Result _lastResult; + + public MapIterator(RemapStorage remapStorage, long offset) + { + throw new NotImplementedException(); + } + + public bool MoveNext(long maxOffset) + { + throw new NotImplementedException(); + } + + public readonly ref readonly MapEntry GetMapEntry() + { + throw new NotImplementedException(); + } + + public readonly IStorage GetStorage() + { + throw new NotImplementedException(); + } + + public readonly Result GetLastResult() + { + throw new NotImplementedException(); + } + } + + private class MapEntryCache + { + private Array20 _entries; + private int _startIndex; + private SdkMutex _mutex; + + public MapEntryCache() + { + throw new NotImplementedException(); + } + + public bool SetMapEntry(in MapEntry entry, int index) + { + throw new NotImplementedException(); + } + + public bool GetMapEntry(out MapEntry outMapEntry, out int outIndexMapEntry, long offset) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/IntegritySaveDataFileSystem.cs b/src/LibHac/FsSystem/Save/IntegritySaveDataFileSystem.cs new file mode 100644 index 00000000..41aa0415 --- /dev/null +++ b/src/LibHac/FsSystem/Save/IntegritySaveDataFileSystem.cs @@ -0,0 +1,446 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.Fs.Save; +using LibHac.Os; + +namespace LibHac.FsSystem.Save; + +public struct IntegritySaveDataParameters +{ + public uint BlockCount; + public long BlockSize; +} + +file static class Anonymous +{ + public static Result GetHashAlgorithmTypeImpl(out HashAlgorithmType outType, in IntegritySaveDataFileSystem.FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static HashAlgorithmType GetHashAlgorithmTypeImpl(uint version) + { + throw new NotImplementedException(); + } + + public static Result CheckVersion(uint version) + { + throw new NotImplementedException(); + } + + public static bool IsDataEncryptionEnabled(in IntegritySaveDataFileSystem.FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static bool IsDataEncryptionEnabled(uint version) + { + throw new NotImplementedException(); + } + + public static Result InitializeEncryptedStorage(ref ValueSubStorage outStorage, + ref UniqueRef encryptionStorage, ref UniqueRef alignmentMatchingEncryptionStorage, + in ValueSubStorage baseStorage, in IntegritySaveDataFileSystem.FileSystemLayoutHeader layoutHeader, + ReadOnlySpan key1, ReadOnlySpan key2, long blockSize) + { + throw new NotImplementedException(); + } +} + +public class IntegritySaveDataFileSystem : IFileSystem +{ + public struct ExtraData { } + + public struct FileSystemLayoutHeader { } + + public struct MasterHeader { } + + public static Result GetHashAlgorithmType(out HashAlgorithmType outType, in FileSystemLayoutHeader layoutHeader) + { + throw new NotImplementedException(); + } + + public static HashAlgorithmType GetHashAlgorithmType(uint version) + { + throw new NotImplementedException(); + } + + public class ControlAreaHolder : IDisposable + { + private byte[] _header; + private UniqueRef _storage; + private ulong _bufferSize; + + public ControlAreaHolder() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Reset(in MasterHeader header) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public void Commit(ref MasterHeader header) + { + throw new NotImplementedException(); + } + + public ref ExtraData GetExtraData() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetIntegrityControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetSaveDataControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetLayeredHashIntegrityMetaControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetMasterHashStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetIntegrityMetaMasterHashStorage() + { + throw new NotImplementedException(); + } + } + + private ControlAreaHolder _controlArea; + private ValueSubStorage _masterHeaderStorage; + private BufferedStorage _bufferedFileSystemStorage; + private BufferedStorage _bufferedMetaStorage; + private ValueSubStorage _fileSystemStorage; + private IntegritySaveDataStorage _integrityStorage; + private HierarchicalIntegrityVerificationStorage _integrityMetaStorage; + private SaveDataFileSystemCore _saveFileSystemCore; + private IBufferManager _bufferManager; + private long _masterHeaderCacheHandle; + private SdkRecursiveMutex _mutex; + private bool _isInitialized; + private bool _isExtraDataModified; + private bool _isFirstControlAreaMounted; + private IMacGenerator _macGenerator; + private IHash256GeneratorFactorySelector _hashGeneratorFactorySelector; + private ValueSubStorage _saveDataImageFileStorage; + private UniqueRef _encryptedStorage; + private UniqueRef _alignmentMatchingEncryptedStorage; + + public IntegritySaveDataFileSystem() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + private SdkRecursiveMutex GetLocker() + { + throw new NotImplementedException(); + } + + public static void SetGenerateRandomFunction(FileSystemClient fs, RandomDataGenerator randomFunction) + { + throw new NotImplementedException(); + } + + public static void SetVersionSupported(FileSystemClient fs, uint versionMin, uint versionMax) + { + throw new NotImplementedException(); + } + + private Result CommitFileSystemCore() + { + throw new NotImplementedException(); + } + + private static Result FormatFileSystemLayoutHeader(out FileSystemLayoutHeader outFileSystemLayoutHeader, + long blockSize, uint blockCount, HashAlgorithmType hashAlgorithmType, uint minimumVersion) + { + throw new NotImplementedException(); + } + + private Result GetMasterHeader(ref MasterHeader masterHeader) + { + throw new NotImplementedException(); + } + + private void StoreMasterHeader() + { + throw new NotImplementedException(); + } + + public static Result Format(in ValueSubStorage saveFileStorage, long blockSize, uint blockCount, + FileSystemBufferManagerSet buffers, IBufferManager bufferManager, SdkRecursiveMutex mutex, + IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + RandomDataGenerator encryptionKeyGenerator, uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static Result VerifyMasterHeader( + in ValueSubStorage saveImageStorage, + IBufferManager bufferManager, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + public static Result ReadExtraData( + out ExtraData outData, + in ValueSubStorage saveImageStorage, + IBufferManager bufferManager, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + public static Result QuerySize(out long outSize, long blockSize, int blockCount, uint minimumVersion) + { + throw new NotImplementedException(); + } + + private static Result Sign(Span outBuffer, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + private static Result Verify(IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + ReadOnlySpan data, ReadOnlySpan signature) + { + throw new NotImplementedException(); + } + + private static bool VerifyMasterHeaderContent(ref MasterHeader header, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + private static Result ReadMasterControlArea( + out MasterHeader outHeader, + out bool outIsFirstControlAreaMounted, + long headerBufferSize, + in ValueSubStorage baseStorage, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + private Result MountSaveData(in FileSystemLayoutHeader layoutHeader, in SubStorage saveImageStorage, long blockSize, + FileSystemBufferManagerSet integrityCacheBufferSet, IBufferManager cacheBuffer, SdkRecursiveMutex mutex) + { + throw new NotImplementedException(); + } + + private Result MountIntegritySaveData(in FileSystemLayoutHeader layoutHeader, + FileSystemBufferManagerSet integrityCacheBufferSet, IBufferManager cacheBuffer, SdkRecursiveMutex mutex) + { + throw new NotImplementedException(); + } + + public Result Initialize( + in SubStorage saveImageStorage, + FileSystemBufferManagerSet integrityCacheBufferSet, + IBufferManager cacheBuffer, + SdkRecursiveMutex mutex, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result WriteExtraData(in ExtraData extraData) + { + throw new NotImplementedException(); + } + + public Result ReadExtraData(out ExtraData outExtraData) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenDirectory(ref UniqueRef outDirectory, ref readonly Path path, OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteFile(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCleanDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCommit() + { + throw new NotImplementedException(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) + { + throw new NotImplementedException(); + } +} + +public class IntegritySaveDataFile : IFile +{ + private UniqueRef _file; + private IntegritySaveDataFileSystem _fileSystem; + + internal IntegritySaveDataFile(ref UniqueRef file, IntegritySaveDataFileSystem fileSystem) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class IntegritySaveDataDirectory : IDirectory +{ + private IntegritySaveDataFileSystem _fileSystem; + private UniqueRef _directory; + + internal IntegritySaveDataDirectory(ref UniqueRef directory, IntegritySaveDataFileSystem fileSystem) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long entriesRead, Span entryBuffer) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryCount(out long entryCount) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/IntegritySaveDataFileSystemDriver.cs b/src/LibHac/FsSystem/Save/IntegritySaveDataFileSystemDriver.cs new file mode 100644 index 00000000..751443df --- /dev/null +++ b/src/LibHac/FsSystem/Save/IntegritySaveDataFileSystemDriver.cs @@ -0,0 +1,73 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs; +using LibHac.Os; + +namespace LibHac.FsSystem.Save; + +public class IntegritySaveDataFileSystemDriver : ProxyFileSystemWithRetryingBufferAllocation +{ + private ValueSubStorage _baseStorage; + private SdkRecursiveMutex _mutex; + private IBufferManager _bufferManager; + private FileSystemBufferManagerSet _bufferManagerSet; + private IntegritySaveDataFileSystem _fileSystem; + + public IntegritySaveDataFileSystemDriver() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + + public static Result QueryTotalSize(out long outSizeTotal, long sizeBlock, uint blockCount, uint version) + { + throw new NotImplementedException(); + } + + public static IntegritySaveDataParameters SetUpSaveDataParameters(long blockSize, long dataSize) + { + throw new NotImplementedException(); + } + + public static Result Format(in ValueSubStorage saveFileStorage, long blockSize, uint blockCount, + IBufferManager bufferManager, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, RandomDataGenerator encryptionKeyGenerator, + uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static Result ReadExtraData(out IntegritySaveDataFileSystem.ExtraData outExtraData, + in ValueSubStorage saveFileStorage, IBufferManager bufferManager, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + public Result Initialize(in ValueSubStorage saveFileStorage, IBufferManager bufferManager, + IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public void ReadExtraData(out IntegritySaveDataFileSystem.ExtraData outExtraData) + { + throw new NotImplementedException(); + } + + public void WriteExtraData(in IntegritySaveDataFileSystem.ExtraData extraData) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/IntegritySaveDataStorage.cs b/src/LibHac/FsSystem/Save/IntegritySaveDataStorage.cs new file mode 100644 index 00000000..42bbfb62 --- /dev/null +++ b/src/LibHac/FsSystem/Save/IntegritySaveDataStorage.cs @@ -0,0 +1,94 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs; +using LibHac.Os; + +namespace LibHac.FsSystem.Save; + +public class IntegritySaveDataStorage : IStorage +{ + private HierarchicalIntegrityVerificationStorage _integrityStorage; + private bool _isModified; + + public IntegritySaveDataStorage() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static Result QuerySize(out HierarchicalIntegrityVerificationSizeSet outIntegritySizeSet, long blockSize, + long metaSize) + { + throw new NotImplementedException(); + } + + public static Result Format(in ValueSubStorage storageIntegrityControlArea, in ValueSubStorage storageMasterHash, + in HierarchicalIntegrityVerificationMetaInformation metaIntegrity) + { + throw new NotImplementedException(); + } + + public Result Initialize( + in ValueSubStorage storageMasterHash, + in ValueSubStorage storageIntegrityLayeredHashL1, + in ValueSubStorage storageIntegrityLayeredHashL2, + in ValueSubStorage storageIntegrityLayeredHashL3, + in ValueSubStorage storageIntegritySaveData, + in HierarchicalIntegrityVerificationInformation info, + FileSystemBufferManagerSet buffers, + IHash256GeneratorFactory hashGeneratorFactory, + SdkRecursiveMutex mutex) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public bool IsModified() + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + + public Result Commit() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/JournalIntegritySaveDataFileSystem.cs b/src/LibHac/FsSystem/Save/JournalIntegritySaveDataFileSystem.cs new file mode 100644 index 00000000..e764fff4 --- /dev/null +++ b/src/LibHac/FsSystem/Save/JournalIntegritySaveDataFileSystem.cs @@ -0,0 +1,766 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.Fs.Save; +using LibHac.Os; +using LibHac.Util; + +namespace LibHac.FsSystem.Save; + +public struct JournalIntegritySaveDataParameters +{ + public uint CountDataBlock; + public uint CountJournalBlock; + public long BlockSize; + public int CountExpandMax; + public uint Version; + public bool IsMetaSetVerificationEnabled; +} + +file static class Anonymous +{ + public static Result CheckVersion(uint version) + { + throw new NotImplementedException(); + } + + public static bool IsSaveDataMetaVerificationEnabled(in JournalIntegritySaveDataFileSystem.FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static bool IsDataEncryptionEnabled(in JournalIntegritySaveDataFileSystem.FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static bool IsDataEncryptionEnabled(uint version) + { + throw new NotImplementedException(); + } + + public static bool IsMetaSetVerificationEnabledImpl(in JournalIntegritySaveDataFileSystem.FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static bool IsMetaSetVerificationEnabledImpl(uint version) + { + throw new NotImplementedException(); + } + + public static bool IsHashSaltEnabledImpl(in JournalIntegritySaveDataFileSystem.FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static bool IsHashSaltEnabledImpl(uint version) + { + throw new NotImplementedException(); + } + + public static Result GetHashAlgorithmTypeImpl(out HashAlgorithmType outType, in JournalIntegritySaveDataFileSystem.FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static HashAlgorithmType GetHashAlgorithmTypeImpl(uint version) + { + throw new NotImplementedException(); + } + + public static int GetMetaRemapEntryCount(uint version, bool isMetaSetVerificationEnabled) + { + throw new NotImplementedException(); + } + + public static long GetRemappedFileSystemEntryTableSize(uint version, int countExpandMax) + { + throw new NotImplementedException(); + } + + public static long GetRemappedMetaEntryTableSize(uint version, int countExpandMax) + { + throw new NotImplementedException(); + } + + public static long GetRemappedSaveDataMetaAndJournalMetaEntryTableSize(uint version, int countExpandMax) + { + throw new NotImplementedException(); + } + + public static int GetExpandCountMaxFromRemappedFileSystem(uint version, int mapUpdateCount) + { + throw new NotImplementedException(); + } + + public static int GetExpandCountMaxFromRemappedMeta(uint version, bool isMetaSetVerificationEnabled, int mapUpdateCount) + { + throw new NotImplementedException(); + } + + public static int GetExpandCountMaxFromSaveDataMetaAndJournalMetaRemappedMeta(uint version, int mapUpdateCount) + { + throw new NotImplementedException(); + } + + public static Result InitializeEncryptedStorage(ref ValueSubStorage outStorage, + ref UniqueRef encryptionStorage, ref UniqueRef alignmentMatchingEncryptionStorage, + in ValueSubStorage baseStorage, in JournalIntegritySaveDataFileSystem.FileSystemLayoutHeader layoutHeader, + ReadOnlySpan key1, ReadOnlySpan key2, long blockSize) + { + throw new NotImplementedException(); + } + + public static Result GenerateStorageHash256(Span outValue, in ValueSubStorage storage, + IHash256GeneratorFactory hashGeneratorFactory) + { + throw new NotImplementedException(); + } +} + +public class JournalIntegritySaveDataFileSystem : IFileSystem +{ + public struct ExtraData { } + + public struct FileSystemLayoutHeader { } + + public struct MasterHeader + { + public struct CommitData + { + public long Counter; + } + + public struct CommitData2 { } + } + + public class ControlAreaHolder : IDisposable + { + private byte[] _header; + private UniqueRef _storage; + private ulong _bufferSize; + private ulong _bitmapSize; + private int _version; + private HashAlgorithmType _hashAlgorithmType; + private bool _hashSaltEnabled; + private bool _metaSetVerificationEnabled; + + public ControlAreaHolder() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Reset(in MasterHeader header) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public void Commit(ref MasterHeader header) + { + throw new NotImplementedException(); + } + + public HashAlgorithmType GetHashAlgorithmType() + { + throw new NotImplementedException(); + } + + public int GetVersion() + { + throw new NotImplementedException(); + } + + public bool IsHashSaltEnabled() + { + throw new NotImplementedException(); + } + + public bool IsMetaSetVerificationEnabled() + { + throw new NotImplementedException(); + } + + public ref MasterHeader.CommitData GetCommitData() + { + throw new NotImplementedException(); + } + + public ref MasterHeader.CommitData2 GetCommitData2() + { + throw new NotImplementedException(); + } + + public ref ExtraData GetExtraData() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetDuplexControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetFileSystemRemapControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetMetaRemapControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetIntegrityControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetJournalControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetSaveDataControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetLayeredHashIntegrityMetaControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetSaveDataMetaAndJournalMetaRemapControlAreaStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetMasterHashStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetL1BitmapStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetIntegrityMetaMasterHashStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetFileSystemRemapMetaHashStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetMetaRemapMetaHashStorage() + { + throw new NotImplementedException(); + } + + public ref readonly ValueSubStorage GetSaveDataMetaAndJournalMetaRemapMetaHashStorage() + { + throw new NotImplementedException(); + } + } + + private ControlAreaHolder _controlArea; + private ValueSubStorage _masterHeaderStorage; + private BufferedStorage _bufferedFileSystemStorage; + private BufferedStorage _bufferedMetaStorage; + private RemapStorage _remappedFileSystemStorage; + private RemapStorage _remappedMetaStorage; + private HierarchicalDuplexStorage _duplexStorage; + private JournalIntegritySaveDataStorage _journalIntegrityStorage; + private HierarchicalIntegrityVerificationStorage _metaIntegrityStorage; + private SaveDataFileSystemCore _saveFileSystemCore; + private IBufferManager _bufferManager; + private long _masterHeaderCacheHandle; + private SdkRecursiveMutex _mutex; + private bool _isInitialized; + private bool _isFirstControlAreaMounted; + private bool _isProvisionallyCommitted; + private bool _isExtraDataModified; + private IMacGenerator _macGenerator; + private IHash256GeneratorFactorySelector _hashGeneratorFactorySelector; + private uint _version; + private ValueSubStorage _saveDataImageFileStorage; + private UniqueRef _encryptedStorage; + private UniqueRef _alignmentMatchingEncryptedStorage; + private UniqueRef _bufferedMetaSetStorage; + private UniqueRef _remappedSaveDataMetaAndJournalMetaStorage; + + public JournalIntegritySaveDataFileSystem() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + private SdkRecursiveMutex GetLocker() + { + throw new NotImplementedException(); + } + + public static void SetGenerateRandomFunction(RandomDataGenerator func) + { + throw new NotImplementedException(); + } + + private Result CommitFileSystemCore(IMacGenerator macGenerator, long counterForBundledCommit) + { + throw new NotImplementedException(); + } + + private Result FormatFileSystemLayoutHeader( + out FileSystemLayoutHeader outFileSystemLayoutHeader, + uint version, + long remappedFileSystemTableSize, + long remappedMetaTableSize, + long remappedSaveDataMetaAndJournalMetaEntryTableSize, + long blockSize, + uint countAvailableBlock, + uint countJournalBlock, + bool isHashSaltEnabled, + HashAlgorithmType hashAlgorithmType) + { + throw new NotImplementedException(); + } + + private void StoreMasterHeader() + { + throw new NotImplementedException(); + } + + private Result GetMasterHeader(ref MasterHeader masterHeader, uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static Result Format( + in ValueSubStorage saveImageStorage, + long sizeBlock, + uint countDataBlock, + uint countJournalBlock, + int countExpandMax, + FileSystemBufferManagerSet buffers, + IBufferManager bufferManager, + SdkRecursiveMutex locker, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + Optional hashSalt, + RandomDataGenerator encryptionKeyGenerator, + uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static Result Expand( + in ValueSubStorage saveImageStorage, + uint countDataBlock, + uint countJournalBlock, + IBufferManager bufferManager, + SdkRecursiveMutex locker, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static Result VerifyMasterHeader( + in ValueSubStorage saveImageStorage, + IBufferManager bufferManager, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static Result ReadExtraData( + out ExtraData outData, + in ValueSubStorage saveImageStorage, + IBufferManager bufferManager, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + uint minimumVersion) + { + throw new NotImplementedException(); + } + + public void ExtractParameters( + out long outBlockSize, + out uint outCountDataBlock, + out uint outCountJournalBlock, + out int outCountExpandMax, + out uint outVersion, + out bool outIsMetaSetVerificationEnabled) + { + throw new NotImplementedException(); + } + + private static Result ExpandMeta( + out bool outNeedsCommit, + in ValueSubStorage storageMetaRemapMeta, + in ValueSubStorage storageRemappedFileSystem, + in ValueSubStorage storageControlArea, + in FileSystemLayoutHeader layoutHeaderOld, + in FileSystemLayoutHeader layoutHeaderNew, + long blockSize, + IBufferManager bufferManager, + IHash256GeneratorFactory hashGeneratorFactory, + SdkRecursiveMutex mutex) + { + throw new NotImplementedException(); + } + + public static Result QuerySize(out long outSizeTotal, long sizeBlock, int countAvailableBlock, + int countJournalBlock, int countExpandMax, uint minimumVersion) + { + throw new NotImplementedException(); + } + + private static Result Sign(Span outBuffer, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + private static Result Verify(IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + ReadOnlySpan data, ReadOnlySpan signature) + { + throw new NotImplementedException(); + } + + private static bool VerifyMasterHeaderContent(ref MasterHeader header, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + private static Result ReadMasterControlArea( + out MasterHeader outHeader, + out bool outIsProvisionallyCommitted, + out bool outIsFirstControlAreaMounted, + long headerBufferSize, + in ValueSubStorage baseStorage, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + uint minimumVersion) + { + throw new NotImplementedException(); + } + + private static Result UpdateMasterControlAreaMac(in ValueSubStorage saveImageStorage, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) + { + throw new NotImplementedException(); + } + + private Result MountSaveData(in FileSystemLayoutHeader layoutHeader, in SubStorage saveImageStorage, long blockSize, + FileSystemBufferManagerSet integrityCacheBufferSet, IBufferManager bufferManager, SdkRecursiveMutex mutex) + { + throw new NotImplementedException(); + } + + private Result MountIntegritySaveData(in FileSystemLayoutHeader layoutHeader, long blockSize, + FileSystemBufferManagerSet integrityCacheBufferSet, IBufferManager bufferManager, SdkRecursiveMutex mutex) + { + throw new NotImplementedException(); + } + + private Result RemountSaveData() + { + throw new NotImplementedException(); + } + + public Result Initialize( + in SubStorage saveImageStorage, + FileSystemBufferManagerSet integrityCacheBufferSet, + IBufferManager duplicateCacheBuffer, + SdkRecursiveMutex mutex, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + uint minimumVersion) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + private Result RollbackFileSystemCore(bool rollbackProvisionalCommits) + { + throw new NotImplementedException(); + } + + public static Result UpdateMac(in SubStorage saveImageStorage, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static Result RecoverMasterHeader(in SubStorage saveImageStorage, IBufferManager bufferManager, + IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static bool IsMetaSetVerificationEnabled(in FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static bool IsMetaSetVerificationEnabled(uint version) + { + throw new NotImplementedException(); + } + + public static bool IsHashSaltEnabled(in FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static bool IsHashSaltEnabled(uint version) + { + throw new NotImplementedException(); + } + + public static Result GetHashAlgorithmType(out HashAlgorithmType outType, in FileSystemLayoutHeader header) + { + throw new NotImplementedException(); + } + + public static HashAlgorithmType GetHashAlgorithmType(uint version) + { + throw new NotImplementedException(); + } + + public static void SetVersionSupported(FileSystemClient fs, uint versionMin, uint versionMax) + { + throw new NotImplementedException(); + } + + public Result WriteExtraData(in ExtraData extraData) + { + throw new NotImplementedException(); + } + + public Result ReadExtraData(out ExtraData outExtraData) + { + throw new NotImplementedException(); + } + + private static Result UpdateRemapMetaHashStorage(in ValueSubStorage remapMetaStorage, + in ValueSubStorage remapMetaHashStorage, IHash256GeneratorFactory hashGeneratorFactory) + { + throw new NotImplementedException(); + } + + private static Result VerifyRemapMetaHashStorage(in ValueSubStorage remapMetaStorage, + in ValueSubStorage remapMetaHashStorage, IHash256GeneratorFactory hashGeneratorFactory) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenDirectory(ref UniqueRef outDirectory, ref readonly Path path, OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteFile(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCleanDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) + { + throw new NotImplementedException(); + } + + protected override Result DoCommit() + { + throw new NotImplementedException(); + } + + protected override Result DoCommitProvisionally(long counter) + { + throw new NotImplementedException(); + } + + protected override Result DoRollback() + { + throw new NotImplementedException(); + } + + public long GetCounterForBundledCommit() + { + throw new NotImplementedException(); + } + + public Result UpdateMacAndCommit(IMacGenerator macGenerator) + { + throw new NotImplementedException(); + } + + public Result RollbackOnlyModified() + { + throw new NotImplementedException(); + } + + public Result AcceptVisitor(IInternalStorageFileSystemVisitor visitor) + { + throw new NotImplementedException(); + } +} + +public class IntegrityFilteredFile : IFile +{ + private UniqueRef _file; + private JournalIntegritySaveDataFileSystem _fileSystem; + + internal IntegrityFilteredFile(ref UniqueRef file, JournalIntegritySaveDataFileSystem fileSystem) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class IntegrityFilteredDirectory : IDirectory +{ + private UniqueRef _directory; + private JournalIntegritySaveDataFileSystem _fileSystem; + + internal IntegrityFilteredDirectory(ref UniqueRef directory, JournalIntegritySaveDataFileSystem fileSystem) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long entriesRead, Span entryBuffer) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryCount(out long entryCount) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/JournalIntegritySaveDataFileSystemDriver.cs b/src/LibHac/FsSystem/Save/JournalIntegritySaveDataFileSystemDriver.cs new file mode 100644 index 00000000..4fc3ecc1 --- /dev/null +++ b/src/LibHac/FsSystem/Save/JournalIntegritySaveDataFileSystemDriver.cs @@ -0,0 +1,152 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs; +using LibHac.Os; +using LibHac.Util; + +namespace LibHac.FsSystem.Save; + +public class JournalIntegritySaveDataFileSystemDriver : ProxyFileSystemWithRetryingBufferAllocation, IInternalStorageFileSystem +{ + private ValueSubStorage _baseStorage; + private SdkRecursiveMutex _mutex; + private IBufferManager _bufferManager; + private FileSystemBufferManagerSet _bufferManagerSet; + private JournalIntegritySaveDataFileSystem _fileSystem; + + public JournalIntegritySaveDataFileSystemDriver() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static Result QueryDataBlockCount(out uint outCountDataBlock, long blockSize, long availableSize, + long journalSize, int countExpandMax, uint version) + { + throw new NotImplementedException(); + } + + public static Result QueryTotalSize(out long outSizeTotal, long blockSize, uint countAvailableBlock, + uint countJournalBlock, int countExpandMax, uint version) + { + throw new NotImplementedException(); + } + + public static Result Format( + in ValueSubStorage saveFileStorage, + long blockSize, + uint blockCount, + uint journalBlockCount, + int countExpandMax, + IBufferManager bufferManager, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + Optional hashSalt, + RandomDataGenerator encryptionKeyGenerator, + uint version) + { + throw new NotImplementedException(); + } + + public static long QueryExpandLogSize(long blockSize, uint availableBlockCount, uint journalBlockCount) + { + throw new NotImplementedException(); + } + + public static Result OperateExpand( + in ValueSubStorage baseStorage, + in ValueSubStorage logStorage, + long blockSize, + uint availableBlockCount, + uint journalBlockCount, + IBufferManager bufferManager, + IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + uint minimumVersion) + { + throw new NotImplementedException(); + } + + public static Result CommitExpand( + in ValueSubStorage baseStorage, + in ValueSubStorage logStorage, + long blockSize, + IBufferManager bufferManager) + { + throw new NotImplementedException(); + } + + public static Result ReadExtraData(out JournalIntegritySaveDataFileSystem.ExtraData outData, + in ValueSubStorage saveImageStorage, IBufferManager bufferManager, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) + { + throw new NotImplementedException(); + } + + public Result Initialize(in ValueSubStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result WriteExtraData(in JournalIntegritySaveDataFileSystem.ExtraData extraData) + { + throw new NotImplementedException(); + } + + public Result ReadExtraData(out JournalIntegritySaveDataFileSystem.ExtraData outExtraData) + { + throw new NotImplementedException(); + } + + public Result RollbackOnlyModified() + { + throw new NotImplementedException(); + } + + public static Result UpdateMac(in ValueSubStorage saveDataStorage, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) + { + throw new NotImplementedException(); + } + + public long GetCounterForBundledCommit() + { + throw new NotImplementedException(); + } + + public Result CommitFileSystem() + { + throw new NotImplementedException(); + } + + public void ExtractParameters(out JournalIntegritySaveDataParameters outParams) + { + throw new NotImplementedException(); + } + + public static JournalIntegritySaveDataParameters SetUpSaveDataParameters(long blockSize, long dataSize, long journalSize) + { + throw new NotImplementedException(); + } + + public Result AcceptVisitor(IInternalStorageFileSystemVisitor visitor) + { + throw new NotImplementedException(); + } + + public Result UpdateMac(IMacGenerator macGenerator) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/JournalIntegritySaveDataStorage.cs b/src/LibHac/FsSystem/Save/JournalIntegritySaveDataStorage.cs new file mode 100644 index 00000000..21dffd19 --- /dev/null +++ b/src/LibHac/FsSystem/Save/JournalIntegritySaveDataStorage.cs @@ -0,0 +1,179 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Fs; +using LibHac.Os; + +namespace LibHac.FsSystem.Save; + +public class JournalIntegritySaveDataStorage : IStorage +{ + private JournalStorage _journalStorage; + private HierarchicalIntegrityVerificationStorage _integrityStorage; + + public JournalIntegritySaveDataStorage() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static Result QuerySize( + out long outSizeJournalTable, + out long outSizeJournalBitmapUpdatedPhysical, + out long outSizeJournalBitmapUpdatedVirtual, + out long outSizeJournalBitmapUnassigned, + out HierarchicalIntegrityVerificationSizeSet outIntegritySizeSet, + long sizeBlock, + long dataSize, + long journalSize) + { + throw new NotImplementedException(); + } + + public static Result Format( + in ValueSubStorage storageJournalControlArea, + in ValueSubStorage storageJournalTable, + in ValueSubStorage storageJournalBitmapPhysical, + in ValueSubStorage storageJournalBitmapVirtual, + in ValueSubStorage storageJournalBitmapUnassigned, + in ValueSubStorage storageIntegrityControlArea, + in ValueSubStorage storageMasterHash, + in HierarchicalIntegrityVerificationInformation metaIntegrity, + long sizeBlock, + long sizeData, + long sizeReservedArea) + { + throw new NotImplementedException(); + } + + public static Result Expand( + in ValueSubStorage storageJournalControlArea, + in ValueSubStorage storageJournalTable, + in ValueSubStorage storageJournalBitmapPhysical, + in ValueSubStorage storageJournalBitmapVirtual, + in ValueSubStorage storageJournalBitmapUnassigned, + in ValueSubStorage storageIntegrityControlArea, + in HierarchicalIntegrityVerificationInformation metaNew, + long sizeUsableAreaNew, + long sizeReservedAreaNew) + { + throw new NotImplementedException(); + } + + public Result Initialize( + in ValueSubStorage storageJournalControlArea, + in ValueSubStorage storageJournalTable, + in ValueSubStorage storageJournalBitmapPhysical, + in ValueSubStorage storageJournalBitmapVirtual, + in ValueSubStorage storageJournalBitmapUnassigned, + in ValueSubStorage storageMasterHash, + in ValueSubStorage storageIntegrityLayeredHashL1, + in ValueSubStorage storageIntegrityLayeredHashL2, + in ValueSubStorage storageIntegrityLayeredHashL3, + in ValueSubStorage storageIntegritySaveData, + in HierarchicalIntegrityVerificationInformation integrityInfo, + FileSystemBufferManagerSet buffers, + IHash256GeneratorFactory hashGeneratorFactory, + bool isHashSaltEnabled, + SdkRecursiveMutex mutex) + { + throw new NotImplementedException(); + } + + public Result Initialize( + in ValueSubStorage storageJournalControlArea, + in ValueSubStorage storageJournalTable, + in ValueSubStorage storageJournalBitmapPhysical, + in ValueSubStorage storageJournalBitmapVirtual, + in ValueSubStorage storageJournalBitmapUnassigned, + in ValueSubStorage storageMasterHash, + in ValueSubStorage storageIntegrityLayeredHashL1, + in ValueSubStorage storageIntegrityLayeredHashL2, + in ValueSubStorage storageIntegrityLayeredHashL3, + in ValueSubStorage storageIntegritySaveData, + in HierarchicalIntegrityVerificationInformation integrityInfo, + FileSystemBufferManagerSet buffers, + IHash256GeneratorFactory hashGeneratorFactory, + bool isHashSaltEnabled, + SdkRecursiveMutex mutex, + Semaphore readSemaphore, + Semaphore writeSemaphore) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public long GetBlockSize() + { + throw new NotImplementedException(); + } + + public long GetDataAreaSize() + { + throw new NotImplementedException(); + } + + public long GetReservedAreaSize() + { + throw new NotImplementedException(); + } + + public FileSystemBufferManagerSet GetBufferManagerSet() + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } + + public Result Commit() + { + throw new NotImplementedException(); + } + + public Result OnRollback() + { + throw new NotImplementedException(); + } + + public Result AcceptVisitor(IInternalStorageFileSystemVisitor visitor) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/ProxyFileSystemWithRetryingBufferAllocation.cs b/src/LibHac/FsSystem/Save/ProxyFileSystemWithRetryingBufferAllocation.cs new file mode 100644 index 00000000..ef4cde50 --- /dev/null +++ b/src/LibHac/FsSystem/Save/ProxyFileSystemWithRetryingBufferAllocation.cs @@ -0,0 +1,199 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs; +using LibHac.Fs.Fsa; + +namespace LibHac.FsSystem.Save; + +public class ProxyFileSystemWithRetryingBufferAllocationFile : IFile +{ + private IFile _file; + + public ProxyFileSystemWithRetryingBufferAllocationFile() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public void Initialize(ref UniqueRef file) + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class ProxyFileSystemWithRetryingBufferAllocationDirectory : IDirectory +{ + private IDirectory _directory; + + public ProxyFileSystemWithRetryingBufferAllocationDirectory() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public void Initialize(ref UniqueRef directory) + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long entriesRead, Span entryBuffer) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryCount(out long entryCount) + { + throw new NotImplementedException(); + } +} + +public class ProxyFileSystemWithRetryingBufferAllocation : IFileSystem +{ + private IFileSystem _fileSystem; + + public ProxyFileSystemWithRetryingBufferAllocation() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public void Initialize(IFileSystem baseFileSystem) + { + throw new NotImplementedException(); + } + + public void Finalize(IFileSystem fileSystem) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenDirectory(ref UniqueRef outDirectory, ref readonly Path path, OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteFile(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCleanDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCommit() + { + throw new NotImplementedException(); + } + + protected override Result DoCommitProvisionally(long counter) + { + throw new NotImplementedException(); + } + + protected override Result DoRollback() + { + throw new NotImplementedException(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/SaveDataInternalStorageFile.cs b/src/LibHac/FsSystem/Save/SaveDataInternalStorageFile.cs new file mode 100644 index 00000000..f7683bd0 --- /dev/null +++ b/src/LibHac/FsSystem/Save/SaveDataInternalStorageFile.cs @@ -0,0 +1,134 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Fs.Fsa; + +namespace LibHac.FsSystem.Save; + +file class Sha2SaltHashFile : IFile +{ + public Sha2SaltHashFile() + { + throw new NotImplementedException(); + } + + public Result Initialize(IStorage storage, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + in HashSalt hashSalt) + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +file class SaveDataInternalStorageFileAccessor : IInternalStorageFileSystemVisitor +{ + public delegate Result MemoryFunction(ReadOnlySpan buffer); + + public delegate Result FileFunction(IFile file); + + public SaveDataInternalStorageFileAccessor(U8Span name, OpenMode mode, FileFunction fileFunction, + MemoryFunction memoryFunction, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + in HashSalt hashSalt) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Visit(U8Span name, IStorage storage) + { + throw new NotImplementedException(); + } + + public Result Visit(U8Span name, ReadOnlySpan buffer) + { + throw new NotImplementedException(); + } +} + +public class SaveDataInternalStorageFile : IFile +{ + private IInternalStorageFileSystem _fileSystem; + private OpenMode _openMode; + private Array64 _name; + private IHash256GeneratorFactorySelector _hashGeneratorFactorySelector; + private HashSalt _hashSalt; + + public SaveDataInternalStorageFile(IInternalStorageFileSystem fileSystem, U8Span name, OpenMode openMode, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, HashSalt hashSalt) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/SaveDataInternalStorageFileSystem.cs b/src/LibHac/FsSystem/Save/SaveDataInternalStorageFileSystem.cs new file mode 100644 index 00000000..55bbff36 --- /dev/null +++ b/src/LibHac/FsSystem/Save/SaveDataInternalStorageFileSystem.cs @@ -0,0 +1,302 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Fs.Fsa; + +namespace LibHac.FsSystem.Save; + +public interface IInternalStorageFileSystemVisitor : IDisposable +{ + Result Visit(U8Span name, ReadOnlySpan buffer); + Result Visit(U8Span name, IStorage storage); +} + +// ReSharper disable once InconsistentNaming +public interface InternalStorageFileSystemHolder +{ + IInternalStorageFileSystem GetInternalStorageFileSystem(); +} + +public interface IInternalStorageFileSystem +{ + Result AcceptVisitor(IInternalStorageFileSystemVisitor visitor); + Result WriteExtraData(in JournalIntegritySaveDataFileSystem.ExtraData extraData); + Result ReadExtraData(out JournalIntegritySaveDataFileSystem.ExtraData outExtraData); + Result CommitFileSystem(); + Result UpdateMac(IMacGenerator macGenerator); +} + +file class SaveDataInternalStorageFileSystemAccessor : IInternalStorageFileSystemVisitor +{ + private bool _isOperationDone; + private Func _updateMacFunc; + + public SaveDataInternalStorageFileSystemAccessor(Func updateMacFunc) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Visit(U8Span name, ReadOnlySpan buffer) + { + throw new NotImplementedException(); + } + + public Result Visit(U8Span name, IStorage storage) + { + throw new NotImplementedException(); + } +} + +file class SaveDataInternalStorageFreeBitmap : IInternalStorageFileSystemVisitor +{ + private Func _freeBitmapFunc; + + public SaveDataInternalStorageFreeBitmap(Func freeBitmapFunc) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Visit(U8Span name, ReadOnlySpan buffer) + { + throw new NotImplementedException(); + } + + public Result Visit(U8Span name, IStorage storage) + { + throw new NotImplementedException(); + } +} + +file class SaveDataExtraDataInternalStorageFile : IFile +{ + private IInternalStorageFileSystem _fileSystem; + private OpenMode _mode; + private Array64 _name; + + public SaveDataExtraDataInternalStorageFile(IInternalStorageFileSystem fileSystem, U8Span name, OpenMode mode) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +file class MemoryFile : IFile +{ + private byte[] _buffer; + private int _size; + private OpenMode _mode; + + public MemoryFile(byte[] buffer, OpenMode mode) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class SaveDataInternalStorageFileSystem : IFileSystem, ICacheableSaveDataFileSystem, ISaveDataExtraDataAccessor +{ + private IInternalStorageFileSystem _internalStorageFileSystem; + private IMacGenerator _normalMacGenerator; + private IMacGenerator _temporaryMacGenerator; + private IHash256GeneratorFactorySelector _hashGeneratorFactorySelector; + private Array32 _fileNameSha2Salt; + + public SaveDataInternalStorageFileSystem() + { + throw new NotImplementedException(); + } + + public Result Initialize(IInternalStorageFileSystem internalStorageFileSystem, IMacGenerator normalMacGenerator, + IMacGenerator temporaryMacGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteFile(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCleanDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenDirectory(ref UniqueRef outDirectory, ref readonly Path path, OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoCommit() + { + throw new NotImplementedException(); + } + + protected override Result DoCommitProvisionally(long counter) + { + throw new NotImplementedException(); + } + + protected override Result DoRollback() + { + throw new NotImplementedException(); + } + + protected override Result DoQueryEntry(Span outBuffer, ReadOnlySpan inBuffer, QueryId queryId, + ref readonly Path path) + { + throw new NotImplementedException(); + } + + public Result WriteExtraData(in SaveDataExtraData extraData) + { + throw new NotImplementedException(); + } + + public Result CommitExtraData(bool updateTimeStamp) + { + throw new NotImplementedException(); + } + + public Result ReadExtraData(out SaveDataExtraData extraData) + { + throw new NotImplementedException(); + } + + public void RegisterExtraDataAccessorObserver(ISaveDataExtraDataAccessorObserver observer, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public bool IsSaveDataFileSystemCacheEnabled() + { + throw new NotImplementedException(); + } + + public Result RollbackOnlyModified() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/Save/SaveDataInternalStorageUtility.cs b/src/LibHac/FsSystem/Save/SaveDataInternalStorageUtility.cs new file mode 100644 index 00000000..55766174 --- /dev/null +++ b/src/LibHac/FsSystem/Save/SaveDataInternalStorageUtility.cs @@ -0,0 +1,43 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs; + +namespace LibHac.FsSystem.Save; + +public class SaveDataInternalStorageFinder : IInternalStorageFileSystemVisitor +{ + private U8String _name; + private bool _isFound; + + public SaveDataInternalStorageFinder(U8Span name) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public Result Visit(U8Span name, IStorage storage) + { + throw new NotImplementedException(); + } + + public Result Visit(U8Span name, ReadOnlySpan buffer) + { + throw new NotImplementedException(); + } + + public bool IsFound() + { + throw new NotImplementedException(); + } + + private void VisitImpl(ReadOnlySpan name) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/SaveDataFileSystem.cs b/src/LibHac/FsSystem/SaveDataFileSystem.cs new file mode 100644 index 00000000..b019ca10 --- /dev/null +++ b/src/LibHac/FsSystem/SaveDataFileSystem.cs @@ -0,0 +1,239 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.FsSystem.Save; +using LibHac.Os; + +namespace LibHac.FsSystem; + +file class SaveDataFile : IFile +{ + private UniqueRef _file; + + public SaveDataFile(ref UniqueRef file) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class SaveDataFileSystem : ISaveDataFileSystem, InternalStorageFileSystemHolder +{ + private SharedRef _baseStorage; + private JournalIntegritySaveDataFileSystemDriver _saveFsDriver; + private ISaveDataExtraDataAccessorObserver _cacheObserver; + private ulong _saveDataId; + private SaveDataSpaceId _spaceId; + private ISaveDataCommitTimeStampGetter _commitTimeStampGetter; + private RandomDataGenerator _randomGeneratorForCommit; + private SdkMutex _mutex; + private bool _canCommitProvisionally; + + public SaveDataFileSystem() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + public static Result ExtractParameters(out JournalIntegritySaveDataParameters outParam, IStorage saveStorage, + IBufferManager bufferManager, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) + { + throw new NotImplementedException(); + } + + public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion, bool canCommitProvisionally) + { + throw new NotImplementedException(); + } + + public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator, + IHash256GeneratorFactorySelector hashGeneratorFactorySelector, ISaveDataCommitTimeStampGetter timeStampGetter, + RandomDataGenerator randomGenerator, uint minimumVersion, bool canCommitProvisionally) + { + throw new NotImplementedException(); + } + + public Result Initialize(ref readonly SharedRef baseStorage, IBufferManager bufferManager, + IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion, + bool canCommitProvisionally) + { + throw new NotImplementedException(); + } + + public Result Initialize(ref readonly SharedRef baseStorage, IBufferManager bufferManager, + IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, + ISaveDataCommitTimeStampGetter timeStampGetter, RandomDataGenerator randomGenerator, uint minimumVersion, + bool canCommitProvisionally) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteFile(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCreateDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectory(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoDeleteDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoCleanDirectoryRecursively(ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath) + { + throw new NotImplementedException(); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenFile(ref UniqueRef outFile, ref readonly Path path, OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoOpenDirectory(ref UniqueRef outDirectory, ref readonly Path path, OpenDirectoryMode mode) + { + throw new NotImplementedException(); + } + + private Result DoCommit(bool updateTimeStamp) + { + throw new NotImplementedException(); + } + + protected override Result DoCommit() + { + throw new NotImplementedException(); + } + + protected override Result DoCommitProvisionally(long counter) + { + throw new NotImplementedException(); + } + + protected override Result DoRollback() + { + throw new NotImplementedException(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path) + { + throw new NotImplementedException(); + } + + protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute) + { + throw new NotImplementedException(); + } + + public override Result WriteExtraData(in SaveDataExtraData extraData) + { + throw new NotImplementedException(); + } + + public override Result CommitExtraData(bool updateTimeStamp) + { + throw new NotImplementedException(); + } + + public override Result ReadExtraData(out SaveDataExtraData extraData) + { + throw new NotImplementedException(); + } + + public override void RegisterExtraDataAccessorObserver(ISaveDataExtraDataAccessorObserver observer, SaveDataSpaceId spaceId, ulong saveDataId) + { + throw new NotImplementedException(); + } + + public override bool IsSaveDataFileSystemCacheEnabled() + { + throw new NotImplementedException(); + } + + public override Result RollbackOnlyModified() + { + throw new NotImplementedException(); + } + + public IInternalStorageFileSystem GetInternalStorageFileSystem() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSystem/ZeroBitmapFile.cs b/src/LibHac/FsSystem/ZeroBitmapFile.cs new file mode 100644 index 00000000..c24c3724 --- /dev/null +++ b/src/LibHac/FsSystem/ZeroBitmapFile.cs @@ -0,0 +1,104 @@ +// ReSharper disable UnusedMember.Local UnusedType.Local +#pragma warning disable CS0169 // Field is never used +using System; +using LibHac.Common; +using LibHac.Fs; +using LibHac.Fs.Fsa; + +namespace LibHac.FsSystem; + +public class ZeroBitmapFile : IFile +{ + private UniqueRef _baseFile; + private byte[] _bitmap; + private long _blockSize; + private long _bitmapSize; + private OpenMode _mode; + + public ZeroBitmapFile() + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + throw new NotImplementedException(); + } + + private bool IsFree(long offset) + { + throw new NotImplementedException(); + } + + private void Clear(long offset) + { + throw new NotImplementedException(); + } + + public Result Initialize(ref UniqueRef baseFile, byte[] bitmap, long bitmapSize, long blockSize, + OpenMode mode) + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoFlush() + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } + + protected override Result DoGetSize(out long size) + { + throw new NotImplementedException(); + } + + protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +public class ZeroBitmapHashStorageFile : ZeroBitmapFile +{ + private IntegrityVerificationStorage.BlockHash _hash; + + public ZeroBitmapHashStorageFile() + { + throw new NotImplementedException(); + } + + public Result Initialize(ref UniqueRef baseFile, byte[] bitmap, long bitmapSize, long blockSize, + OpenMode mode, in IntegrityVerificationStorage.BlockHash blockHash) + { + throw new NotImplementedException(); + } + + protected override Result DoRead(out long bytesRead, long offset, Span destination, in ReadOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source, in WriteOption option) + { + throw new NotImplementedException(); + } + + protected override Result DoSetSize(long size) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/Tools/Fs/SwitchFs.cs b/src/LibHac/Tools/Fs/SwitchFs.cs index 5dfe3c94..dd7217d0 100644 --- a/src/LibHac/Tools/Fs/SwitchFs.cs +++ b/src/LibHac/Tools/Fs/SwitchFs.cs @@ -12,10 +12,10 @@ using LibHac.Ncm; using LibHac.Ns; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; -using LibHac.Tools.FsSystem.Save; using LibHac.Tools.Ncm; using LibHac.Util; using KeyType = LibHac.Common.Keys.KeyType; +using SaveDataFileSystem = LibHac.Tools.FsSystem.Save.SaveDataFileSystem; namespace LibHac.Tools.Fs; diff --git a/src/hactoolnet/ProcessSave.cs b/src/hactoolnet/ProcessSave.cs index 14bdc8e9..57280454 100644 --- a/src/hactoolnet/ProcessSave.cs +++ b/src/hactoolnet/ProcessSave.cs @@ -14,6 +14,7 @@ using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.Save; using static hactoolnet.Print; using Path = System.IO.Path; +using SaveDataFileSystem = LibHac.Tools.FsSystem.Save.SaveDataFileSystem; namespace hactoolnet; diff --git a/src/hactoolnet/ProcessSwitchFs.cs b/src/hactoolnet/ProcessSwitchFs.cs index 4a2aa3a8..cc815b98 100644 --- a/src/hactoolnet/ProcessSwitchFs.cs +++ b/src/hactoolnet/ProcessSwitchFs.cs @@ -12,8 +12,8 @@ using LibHac.Ns; using LibHac.Tools.Fs; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; -using LibHac.Tools.FsSystem.Save; using Path = System.IO.Path; +using SaveDataFileSystem = LibHac.Tools.FsSystem.Save.SaveDataFileSystem; namespace hactoolnet; diff --git a/tests/LibHac.Tests/Fs/TypeLayoutTests.cs b/tests/LibHac.Tests/Fs/TypeLayoutTests.cs index efe876ab..77079e00 100644 --- a/tests/LibHac.Tests/Fs/TypeLayoutTests.cs +++ b/tests/LibHac.Tests/Fs/TypeLayoutTests.cs @@ -376,7 +376,7 @@ public class TypeLayoutTests Assert.Equal(0x10, Unsafe.SizeOf()); - Assert.Equal(0x00, GetOffset(in s, in s.Value)); + Assert.Equal(0x00, GetOffset(in s, in s.Value[0])); } [Fact] @@ -406,7 +406,7 @@ public class TypeLayoutTests Assert.Equal(0x10, Unsafe.SizeOf()); - Assert.Equal(0x00, GetOffset(in s, in s.Value)); + Assert.Equal(0x00, GetOffset(in s, in s.Value[0])); } [Fact] diff --git a/tests/LibHac.Tests/FsSrv/TypeLayoutTests.cs b/tests/LibHac.Tests/FsSrv/TypeLayoutTests.cs index 36b95b5e..5490d6cd 100644 --- a/tests/LibHac.Tests/FsSrv/TypeLayoutTests.cs +++ b/tests/LibHac.Tests/FsSrv/TypeLayoutTests.cs @@ -94,4 +94,207 @@ public class TypeLayoutTests Assert.Equal(0x19, GetOffset(in s, in s.State)); Assert.Equal(0x1A, GetOffset(in s, in s.Reserved)); } + + [Fact] + public static void InitialDataVersion1Detail_Layout() + { + var s = new InitialDataVersion1Detail(); + + Assert.Equal(0x280, Unsafe.SizeOf()); + + Assert.Equal(0x000, GetOffset(in s, in s.DataContent)); + Assert.Equal(0x270, GetOffset(in s, in s.Mac)); + } + + [Fact] + public static void InitialDataVersion1Detail_Content_Layout() + { + var s = new InitialDataVersion1Detail.Content(); + + Assert.Equal(0x270, Unsafe.SizeOf()); + + Assert.Equal(0x000, GetOffset(in s, in s.ExtraData)); + Assert.Equal(0x200, GetOffset(in s, in s.Version)); + Assert.Equal(0x204, GetOffset(in s, in s.Reserved)); + } + + [Fact] + public static void InitialDataVersion2Detail_Layout() + { + var s = new InitialDataVersion2Detail(); + + Assert.Equal(0x2000, Unsafe.SizeOf()); + + Assert.Equal(0x0000, GetOffset(in s, in s.GcmStreamHeader)); + Assert.Equal(0x0020, GetOffset(in s, in s.DataContent)); + Assert.Equal(0x1FF0, GetOffset(in s, in s.GcmStreamTail)); + } + + [Fact] + public static void InitialDataVersion2Detail_Content_Layout() + { + var s = new InitialDataVersion2Detail.Content(); + + Assert.Equal(0x1FD0, Unsafe.SizeOf()); + + Assert.Equal(0x0000, GetOffset(in s, in s.Signature)); + Assert.Equal(0x0004, GetOffset(in s, in s.Version)); + Assert.Equal(0x0008, GetOffset(in s, in s.ExtraData)); + Assert.Equal(0x0208, GetOffset(in s, in s.DivisionCount)); + Assert.Equal(0x0210, GetOffset(in s, in s.DivisionAlignment)); + Assert.Equal(0x0218, GetOffset(in s, in s.ChunkHashes)); + Assert.Equal(0x0A18, GetOffset(in s, in s.ChunkSizes)); + Assert.Equal(0x0C18, GetOffset(in s, in s.ChunkMacs)); + Assert.Equal(0x1018, GetOffset(in s, in s.TotalChunkSize)); + Assert.Equal(0x1020, GetOffset(in s, in s.InitialDataAad)); + Assert.Equal(0x1040, GetOffset(in s, in s.HashSalt)); + Assert.Equal(0x1060, GetOffset(in s, in s.ShortHashes)); + Assert.Equal(0x1260, GetOffset(in s, in s.IsIntegritySeedEnabled)); + Assert.Equal(0x1261, GetOffset(in s, in s.HashAlgorithmType)); + Assert.Equal(0x1262, GetOffset(in s, in s.Reserved)); + } + + [Fact] + public static void SaveDataTransferManagerForSaveDataRepair_KeyPackageV0_Layout() + { + var s = new SaveDataTransferManagerForSaveDataRepair.KeyPackageV0(); + + Assert.Equal(0x280, Unsafe.SizeOf()); + + Assert.Equal(0x000, GetOffset(in s, in s.Version)); + Assert.Equal(0x004, GetOffset(in s, in s.Reserved4)); + Assert.Equal(0x008, GetOffset(in s, in s.KeyGeneration)); + Assert.Equal(0x009, GetOffset(in s, in s.Reserved9)); + Assert.Equal(0x010, GetOffset(in s, in s.Iv)); + Assert.Equal(0x020, GetOffset(in s, in s.Mac)); + Assert.Equal(0x030, GetOffset(in s, in s.Reserved30)); + Assert.Equal(0x080, GetOffset(in s, in s.PackageContent)); + Assert.Equal(0x180, GetOffset(in s, in s.Signature)); + } + + [Fact] + public static void SaveDataTransferManagerForSaveDataRepair_KeyPackageV0_Content_Layout() + { + var s = new SaveDataTransferManagerForSaveDataRepair.KeyPackageV0.Content(); + + Assert.Equal(0x100, Unsafe.SizeOf()); + + Assert.Equal(0x00, GetOffset(in s, in s.InitialDataMacBeforeRepair)); + Assert.Equal(0x10, GetOffset(in s, in s.KeyGenerationBeforeRepair)); + Assert.Equal(0x18, GetOffset(in s, in s.InitialDataMacAfterRepair)); + Assert.Equal(0x28, GetOffset(in s, in s.KeyGenerationAfterRepair)); + Assert.Equal(0x30, GetOffset(in s, in s.Keys)); + Assert.Equal(0x50, GetOffset(in s, in s.Iv)); + Assert.Equal(0x60, GetOffset(in s, in s.Mac)); + Assert.Equal(0x70, GetOffset(in s, in s.Reserved70)); + Assert.Equal(0x78, GetOffset(in s, in s.ChallengeData)); + Assert.Equal(0x88, GetOffset(in s, in s.Reserved88)); + } + + [Fact] + public static void KeySeedPackageV0_Layout() + { + var s = new KeySeedPackageV0(); + + Assert.Equal(0x200, Unsafe.SizeOf()); + + Assert.Equal(0x000, GetOffset(in s, in s.Version)); + Assert.Equal(0x004, GetOffset(in s, in s.Reserved4)); + Assert.Equal(0x008, GetOffset(in s, in s.KeyGeneration)); + Assert.Equal(0x009, GetOffset(in s, in s.Reserved9)); + Assert.Equal(0x010, GetOffset(in s, in s.Iv)); + Assert.Equal(0x020, GetOffset(in s, in s.Mac)); + Assert.Equal(0x030, GetOffset(in s, in s.Reserved30)); + Assert.Equal(0x080, GetOffset(in s, in s.Signature)); + Assert.Equal(0x180, GetOffset(in s, in s.PackageContent)); + } + + [Fact] + public static void KeySeedPackageV0_Content_Layout() + { + var s = new KeySeedPackageV0.Content(); + + Assert.Equal(0x80, Unsafe.SizeOf()); + + Assert.Equal(0x00, GetOffset(in s, in s.Unknown)); + Assert.Equal(0x10, GetOffset(in s, in s.TransferKeySeed)); + Assert.Equal(0x20, GetOffset(in s, in s.TransferInitialDataMac)); + Assert.Equal(0x30, GetOffset(in s, in s.Challenge)); + Assert.Equal(0x40, GetOffset(in s, in s.Reserved)); + } + + [Fact] + public static void ExportContextDetail_Layout() + { + var s = new ExportContextDetail(); + + Assert.Equal(0x4000, Unsafe.SizeOf()); + + Assert.Equal(0x0000, GetOffset(in s, in s.GcmStreamHeader)); + Assert.Equal(0x0020, GetOffset(in s, in s.DataContent)); + Assert.Equal(0x3FF0, GetOffset(in s, in s.GcmStreamTail)); + } + + [Fact] + public static void ExportContextDetail_Content_Layout() + { + var s = new ExportContextDetail.Content(); + + Assert.Equal(0x3FD0, Unsafe.SizeOf()); + + Assert.Equal(0x0000, GetOffset(in s, in s.Magic)); + Assert.Equal(0x0004, GetOffset(in s, in s.Unk)); + Assert.Equal(0x0008, GetOffset(in s, in s.IsDiffExport)); + Assert.Equal(0x0010, GetOffset(in s, in s.ChunkSizes)); + Assert.Equal(0x0210, GetOffset(in s, in s.ChunkMacs)); + Assert.Equal(0x0610, GetOffset(in s, in s.IsChunkComplete)); + Assert.Equal(0x0650, GetOffset(in s, in s.InitialData)); + Assert.Equal(0x2650, GetOffset(in s, in s.SpaceId)); + Assert.Equal(0x2658, GetOffset(in s, in s.SaveDataId)); + Assert.Equal(0x2660, GetOffset(in s, in s.CommitId)); + Assert.Equal(0x2668, GetOffset(in s, in s.DivisionCount)); + Assert.Equal(0x2670, GetOffset(in s, in s.DivisionAlignment)); + Assert.Equal(0x2678, GetOffset(in s, in s.InitialDataAad)); + Assert.Equal(0x2698, GetOffset(in s, in s.IsInitialDataComplete)); + Assert.Equal(0x2699, GetOffset(in s, in s.ChunkIvs)); + Assert.Equal(0x2A99, GetOffset(in s, in s.OuterInitialDataIv)); + Assert.Equal(0x2AA9, GetOffset(in s, in s.KeySeed)); + Assert.Equal(0x2AB9, GetOffset(in s, in s.ThumbnailHash)); + Assert.Equal(0x2AD9, GetOffset(in s, in s.Reserved)); + } + + [Fact] + public static void ImportContextDetail_Layout() + { + var s = new ImportContextDetail(); + + Assert.Equal(0x4000, Unsafe.SizeOf()); + + Assert.Equal(0x0000, GetOffset(in s, in s.GcmStreamHeader)); + Assert.Equal(0x0020, GetOffset(in s, in s.DataContent)); + Assert.Equal(0x3FF0, GetOffset(in s, in s.GcmStreamTail)); + } + + [Fact] + public static void ImportContextDetail_Content_Layout() + { + var s = new ImportContextDetail.Content(); + + Assert.Equal(0x3FD0, Unsafe.SizeOf()); + + Assert.Equal(0x0000, GetOffset(in s, in s.Magic)); + Assert.Equal(0x0004, GetOffset(in s, in s.Unk)); + Assert.Equal(0x0008, GetOffset(in s, in s.Mode)); + Assert.Equal(0x0010, GetOffset(in s, in s.InitialData)); + Assert.Equal(0x2010, GetOffset(in s, in s.SpaceId)); + Assert.Equal(0x2018, GetOffset(in s, in s.SourceSaveDataId)); + Assert.Equal(0x2020, GetOffset(in s, in s.DestinationSaveDataId)); + Assert.Equal(0x2028, GetOffset(in s, in s.SourceZeroCommitId)); + Assert.Equal(0x2030, GetOffset(in s, in s.DestinationZeroCommitId)); + Assert.Equal(0x2038, GetOffset(in s, in s.UserId)); + Assert.Equal(0x2048, GetOffset(in s, in s.TimeStamp)); + Assert.Equal(0x2050, GetOffset(in s, in s.ReportInfo)); + Assert.Equal(0x2070, GetOffset(in s, in s.ThumbnailHash)); + Assert.Equal(0x2090, GetOffset(in s, in s.Reserved)); + } } \ No newline at end of file diff --git a/tests/LibHac.Tests/FsSystem/TypeLayoutTests.cs b/tests/LibHac.Tests/FsSystem/TypeLayoutTests.cs index 252adb38..ccc6e91f 100644 --- a/tests/LibHac.Tests/FsSystem/TypeLayoutTests.cs +++ b/tests/LibHac.Tests/FsSystem/TypeLayoutTests.cs @@ -378,4 +378,17 @@ public class TypeLayoutTests Assert.Equal(0x18, GetOffset(in s, in s.HashTargetOffset)); Assert.Equal(0x20, GetOffset(in s, in s.Hash)); } + + [Fact] + public static void MappingTable_Header_Layout() + { + MappingTableControlArea s = default; + + Assert.Equal(0x10, Unsafe.SizeOf()); + + Assert.Equal(0x00, GetOffset(in s, in s.Version)); + Assert.Equal(0x04, GetOffset(in s, in s.AvailableBlockCount)); + Assert.Equal(0x08, GetOffset(in s, in s.ReservedBlockCount)); + Assert.Equal(0x0C, GetOffset(in s, in s.Reserved)); + } } \ No newline at end of file