Remove old SubStorage

This commit is contained in:
Alex Barney 2020-06-30 16:55:25 -07:00
parent f02c84e8dd
commit e9c38dc7ba
15 changed files with 55 additions and 159 deletions

View File

@ -3,7 +3,7 @@ using LibHac.Diag;
namespace LibHac.Fs namespace LibHac.Fs
{ {
public class SubStorage2 : IStorage public class SubStorage : IStorage
{ {
private ReferenceCountedDisposable<IStorage> SharedBaseStorage { get; set; } private ReferenceCountedDisposable<IStorage> SharedBaseStorage { get; set; }
private IStorage BaseStorage { get; } private IStorage BaseStorage { get; }
@ -11,7 +11,7 @@ namespace LibHac.Fs
private long Size { get; set; } private long Size { get; set; }
private bool IsResizable { get; set; } private bool IsResizable { get; set; }
public SubStorage2(IStorage baseStorage, long offset, long size) public SubStorage(IStorage baseStorage, long offset, long size)
{ {
BaseStorage = baseStorage; BaseStorage = baseStorage;
Offset = offset; Offset = offset;
@ -23,7 +23,7 @@ namespace LibHac.Fs
Assert.AssertTrue(Size >= 0); Assert.AssertTrue(Size >= 0);
} }
public SubStorage2(ReferenceCountedDisposable<IStorage> sharedBaseStorage, long offset, long size) public SubStorage(ReferenceCountedDisposable<IStorage> sharedBaseStorage, long offset, long size)
{ {
SharedBaseStorage = sharedBaseStorage.AddReference(); SharedBaseStorage = sharedBaseStorage.AddReference();
BaseStorage = SharedBaseStorage.Target; BaseStorage = SharedBaseStorage.Target;
@ -36,7 +36,7 @@ namespace LibHac.Fs
Assert.AssertTrue(Size >= 0); Assert.AssertTrue(Size >= 0);
} }
public SubStorage2(SubStorage2 subStorage, long offset, long size) public SubStorage(SubStorage subStorage, long offset, long size)
{ {
BaseStorage = subStorage.BaseStorage; BaseStorage = subStorage.BaseStorage;
Offset = subStorage.Offset + offset; Offset = subStorage.Offset + offset;

View File

@ -26,7 +26,7 @@ namespace LibHac.FsService.Creators
Result rc = GameCard.GetCardInfo(out GameCardInfo cardInfo, handle); Result rc = GameCard.GetCardInfo(out GameCardInfo cardInfo, handle);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
storage = new SubStorage2(baseStorage, 0, cardInfo.SecureAreaOffset); storage = new SubStorage(baseStorage, 0, cardInfo.SecureAreaOffset);
return Result.Success; return Result.Success;
} }
@ -53,7 +53,7 @@ namespace LibHac.FsService.Creators
rc = GameCard.GetCardInfo(out GameCardInfo cardInfo, handle); rc = GameCard.GetCardInfo(out GameCardInfo cardInfo, handle);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
storage = new SubStorage2(baseStorage, cardInfo.SecureAreaOffset, cardInfo.SecureAreaSize); storage = new SubStorage(baseStorage, cardInfo.SecureAreaOffset, cardInfo.SecureAreaSize);
return Result.Success; return Result.Success;
} }

View File

@ -21,7 +21,7 @@ namespace LibHac.FsSystem
public int Generation; public int Generation;
} }
public Aes128CtrExStorage(IStorage baseStorage, SubStorage2 nodeStorage, SubStorage2 entryStorage, public Aes128CtrExStorage(IStorage baseStorage, SubStorage nodeStorage, SubStorage entryStorage,
int entryCount, byte[] key, byte[] counter, bool leaveOpen) int entryCount, byte[] key, byte[] counter, bool leaveOpen)
: base(baseStorage, key, counter, leaveOpen) : base(baseStorage, key, counter, leaveOpen)
{ {

View File

@ -19,8 +19,8 @@ namespace LibHac.FsSystem
private static int NodeHeaderSize => Unsafe.SizeOf<NodeHeader>(); private static int NodeHeaderSize => Unsafe.SizeOf<NodeHeader>();
private SubStorage2 NodeStorage { get; set; } private SubStorage NodeStorage { get; set; }
private SubStorage2 EntryStorage { get; set; } private SubStorage EntryStorage { get; set; }
private NodeBuffer _nodeL1 = new NodeBuffer(); private NodeBuffer _nodeL1 = new NodeBuffer();
@ -31,7 +31,7 @@ namespace LibHac.FsSystem
private long StartOffset { get; set; } private long StartOffset { get; set; }
private long EndOffset { get; set; } private long EndOffset { get; set; }
public Result Initialize(SubStorage2 nodeStorage, SubStorage2 entryStorage, int nodeSize, int entrySize, public Result Initialize(SubStorage nodeStorage, SubStorage entryStorage, int nodeSize, int entrySize,
int entryCount) int entryCount)
{ {
Assert.AssertTrue(entrySize >= sizeof(long)); Assert.AssertTrue(entrySize >= sizeof(long));
@ -598,7 +598,7 @@ namespace LibHac.FsSystem
// Calculate node extents. // Calculate node extents.
long nodeSize = Tree.NodeSize; long nodeSize = Tree.NodeSize;
long nodeOffset = (nodeIndex + 1) * nodeSize; long nodeOffset = (nodeIndex + 1) * nodeSize;
SubStorage2 storage = Tree.NodeStorage; SubStorage storage = Tree.NodeStorage;
// Read the node. // Read the node.
Result rc = storage.Read(nodeOffset, buffer.Slice(0, (int)nodeSize)); Result rc = storage.Read(nodeOffset, buffer.Slice(0, (int)nodeSize));
@ -637,7 +637,7 @@ namespace LibHac.FsSystem
long entrySize = Tree.EntrySize; long entrySize = Tree.EntrySize;
long entrySetSize = Tree.NodeSize; long entrySetSize = Tree.NodeSize;
long entrySetOffset = entrySetIndex * entrySetSize; long entrySetOffset = entrySetIndex * entrySetSize;
SubStorage2 storage = Tree.EntryStorage; SubStorage storage = Tree.EntryStorage;
// Read the entry set. // Read the entry set.
Result rc = storage.Read(entrySetOffset, buffer.Slice(0, (int)entrySetSize)); Result rc = storage.Read(entrySetOffset, buffer.Slice(0, (int)entrySetSize));

View File

@ -11,8 +11,8 @@ namespace LibHac.FsSystem
{ {
public class Builder public class Builder
{ {
private SubStorage2 NodeStorage { get; set; } private SubStorage NodeStorage { get; set; }
private SubStorage2 EntryStorage { get; set; } private SubStorage EntryStorage { get; set; }
private NodeBuffer _l1Node = new NodeBuffer(); private NodeBuffer _l1Node = new NodeBuffer();
private NodeBuffer _l2Node = new NodeBuffer(); private NodeBuffer _l2Node = new NodeBuffer();
@ -31,14 +31,14 @@ namespace LibHac.FsSystem
/// <summary> /// <summary>
/// Initializes the bucket tree builder. /// Initializes the bucket tree builder.
/// </summary> /// </summary>
/// <param name="headerStorage">The <see cref="SubStorage2"/> the tree's header will be written to.Must be at least the size in bytes returned by <see cref="QueryHeaderStorageSize"/>.</param> /// <param name="headerStorage">The <see cref="SubStorage"/> the tree's header will be written to.Must be at least the size in bytes returned by <see cref="QueryHeaderStorageSize"/>.</param>
/// <param name="nodeStorage">The <see cref="SubStorage2"/> the tree's nodes will be written to. Must be at least the size in bytes returned by <see cref="QueryNodeStorageSize"/>.</param> /// <param name="nodeStorage">The <see cref="SubStorage"/> the tree's nodes will be written to. Must be at least the size in bytes returned by <see cref="QueryNodeStorageSize"/>.</param>
/// <param name="entryStorage">The <see cref="SubStorage2"/> the tree's entries will be written to. Must be at least the size in bytes returned by <see cref="QueryEntryStorageSize"/>.</param> /// <param name="entryStorage">The <see cref="SubStorage"/> the tree's entries will be written to. Must be at least the size in bytes returned by <see cref="QueryEntryStorageSize"/>.</param>
/// <param name="nodeSize">The size of each node in the bucket tree. Must be a power of 2.</param> /// <param name="nodeSize">The size of each node in the bucket tree. Must be a power of 2.</param>
/// <param name="entrySize">The size of each entry that will be stored in the bucket tree.</param> /// <param name="entrySize">The size of each entry that will be stored in the bucket tree.</param>
/// <param name="entryCount">The exact number of entries that will be added to the bucket tree.</param> /// <param name="entryCount">The exact number of entries that will be added to the bucket tree.</param>
/// <returns>The <see cref="Result"/> of the operation.</returns> /// <returns>The <see cref="Result"/> of the operation.</returns>
public Result Initialize(SubStorage2 headerStorage, SubStorage2 nodeStorage, SubStorage2 entryStorage, public Result Initialize(SubStorage headerStorage, SubStorage nodeStorage, SubStorage entryStorage,
int nodeSize, int entrySize, int entryCount) int nodeSize, int entrySize, int entryCount)
{ {
Assert.AssertTrue(entrySize >= sizeof(long)); Assert.AssertTrue(entrySize >= sizeof(long));

View File

@ -13,7 +13,7 @@ namespace LibHac.FsSystem
public static readonly int NodeSize = 1024 * 16; public static readonly int NodeSize = 1024 * 16;
private BucketTree Table { get; } = new BucketTree(); private BucketTree Table { get; } = new BucketTree();
private SubStorage2[] DataStorage { get; } = new SubStorage2[StorageCount]; private SubStorage[] DataStorage { get; } = new SubStorage[StorageCount];
[StructLayout(LayoutKind.Sequential, Size = 0x14, Pack = 4)] [StructLayout(LayoutKind.Sequential, Size = 0x14, Pack = 4)]
public struct Entry public struct Entry
@ -39,7 +39,7 @@ namespace LibHac.FsSystem
public bool IsInitialized() => Table.IsInitialized(); public bool IsInitialized() => Table.IsInitialized();
public Result Initialize(SubStorage2 tableStorage) public Result Initialize(SubStorage tableStorage)
{ {
// Read and verify the bucket tree header. // Read and verify the bucket tree header.
// note: skip init // note: skip init
@ -58,18 +58,18 @@ namespace LibHac.FsSystem
long entryStorageOffset = nodeStorageOffset + nodeStorageSize; long entryStorageOffset = nodeStorageOffset + nodeStorageSize;
// Initialize. // Initialize.
var nodeStorage = new SubStorage2(tableStorage, nodeStorageOffset, nodeStorageSize); var nodeStorage = new SubStorage(tableStorage, nodeStorageOffset, nodeStorageSize);
var entryStorage = new SubStorage2(tableStorage, entryStorageOffset, entryStorageSize); var entryStorage = new SubStorage(tableStorage, entryStorageOffset, entryStorageSize);
return Initialize(nodeStorage, entryStorage, header.EntryCount); return Initialize(nodeStorage, entryStorage, header.EntryCount);
} }
public Result Initialize(SubStorage2 nodeStorage, SubStorage2 entryStorage, int entryCount) public Result Initialize(SubStorage nodeStorage, SubStorage entryStorage, int entryCount)
{ {
return Table.Initialize(nodeStorage, entryStorage, NodeSize, Unsafe.SizeOf<Entry>(), entryCount); return Table.Initialize(nodeStorage, entryStorage, NodeSize, Unsafe.SizeOf<Entry>(), entryCount);
} }
public void SetStorage(int index, SubStorage2 storage) public void SetStorage(int index, SubStorage storage)
{ {
Assert.InRange(index, 0, StorageCount); Assert.InRange(index, 0, StorageCount);
DataStorage[index] = storage; DataStorage[index] = storage;
@ -78,7 +78,7 @@ namespace LibHac.FsSystem
public void SetStorage(int index, IStorage storage, long offset, long size) public void SetStorage(int index, IStorage storage, long offset, long size)
{ {
Assert.InRange(index, 0, StorageCount); Assert.InRange(index, 0, StorageCount);
DataStorage[index] = new SubStorage2(storage, offset, size); DataStorage[index] = new SubStorage(storage, offset, size);
} }
public Result GetEntryList(Span<Entry> entryBuffer, out int outputEntryCount, long offset, long size) public Result GetEntryList(Span<Entry> entryBuffer, out int outputEntryCount, long offset, long size)
@ -280,7 +280,7 @@ namespace LibHac.FsSystem
Assert.AssertTrue(currentSize <= size); Assert.AssertTrue(currentSize <= size);
{ {
SubStorage2 currentStorage = DataStorage[currentEntry.StorageIndex]; SubStorage currentStorage = DataStorage[currentEntry.StorageIndex];
// Get the current data storage's size. // Get the current data storage's size.
rc = currentStorage.GetSize(out long currentDataStorageSize); rc = currentStorage.GetSize(out long currentDataStorageSize);

View File

@ -194,7 +194,7 @@ namespace LibHac.FsSystem.NcaUtils
byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset); byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset);
IStorage bucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true); IStorage bucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true);
var encryptionBucketTreeData = new SubStorage2(bucketTreeData, var encryptionBucketTreeData = new SubStorage(bucketTreeData,
info.EncryptionTreeOffset - bktrOffset, sectionSize - info.EncryptionTreeOffset); info.EncryptionTreeOffset - bktrOffset, sectionSize - info.EncryptionTreeOffset);
var cachedBucketTreeData = new CachedStorage(encryptionBucketTreeData, IndirectStorage.NodeSize, 6, true); var cachedBucketTreeData = new CachedStorage(encryptionBucketTreeData, IndirectStorage.NodeSize, 6, true);
@ -204,8 +204,8 @@ namespace LibHac.FsSystem.NcaUtils
long nodeStorageSize = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount); long nodeStorageSize = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount);
long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount); long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount);
var tableNodeStorage = new SubStorage2(cachedBucketTreeData, 0, nodeStorageSize); var tableNodeStorage = new SubStorage(cachedBucketTreeData, 0, nodeStorageSize);
var tableEntryStorage = new SubStorage2(cachedBucketTreeData, nodeStorageSize, entryStorageSize); var tableEntryStorage = new SubStorage(cachedBucketTreeData, nodeStorageSize, entryStorageSize);
IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), tableNodeStorage, IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), tableNodeStorage,
tableEntryStorage, treeHeader.EntryCount, key, counterEx, true); tableEntryStorage, treeHeader.EntryCount, key, counterEx, true);
@ -242,11 +242,11 @@ namespace LibHac.FsSystem.NcaUtils
long nodeStorageSize = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount); long nodeStorageSize = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount);
long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount); long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount);
var relocationTableStorage = new SubStorage2(patchStorage, patchInfo.RelocationTreeOffset, patchInfo.RelocationTreeSize); var relocationTableStorage = new SubStorage(patchStorage, patchInfo.RelocationTreeOffset, patchInfo.RelocationTreeSize);
var cachedTableStorage = new CachedStorage(relocationTableStorage, IndirectStorage.NodeSize, 4, true); var cachedTableStorage = new CachedStorage(relocationTableStorage, IndirectStorage.NodeSize, 4, true);
var tableNodeStorage = new SubStorage2(cachedTableStorage, 0, nodeStorageSize); var tableNodeStorage = new SubStorage(cachedTableStorage, 0, nodeStorageSize);
var tableEntryStorage = new SubStorage2(cachedTableStorage, nodeStorageSize, entryStorageSize); var tableEntryStorage = new SubStorage(cachedTableStorage, nodeStorageSize, entryStorageSize);
var storage = new IndirectStorage(); var storage = new IndirectStorage();
storage.Initialize(tableNodeStorage, tableEntryStorage, treeHeader.EntryCount).ThrowIfFailure(); storage.Initialize(tableNodeStorage, tableEntryStorage, treeHeader.EntryCount).ThrowIfFailure();

View File

@ -16,8 +16,8 @@ namespace LibHac.FsSystem.Save
public AllocationTableHeader Header { get; } public AllocationTableHeader Header { get; }
public IStorage GetBaseStorage() => BaseStorage.AsReadOnly(); public IStorage GetBaseStorage() => BaseStorage;
public IStorage GetHeaderStorage() => HeaderStorage.AsReadOnly(); public IStorage GetHeaderStorage() => HeaderStorage;
public AllocationTable(IStorage storage, IStorage header) public AllocationTable(IStorage storage, IStorage header)
{ {

View File

@ -52,11 +52,11 @@ namespace LibHac.FsSystem.Save
return map; return map;
} }
public IStorage GetMapStorage() => MapStorage.AsReadOnly(); public IStorage GetMapStorage() => MapStorage;
public IStorage GetHeaderStorage() => HeaderStorage.AsReadOnly(); public IStorage GetHeaderStorage() => HeaderStorage;
public IStorage GetModifiedPhysicalBlocksStorage() => ModifiedPhysicalBlocks.AsReadOnly(); public IStorage GetModifiedPhysicalBlocksStorage() => ModifiedPhysicalBlocks;
public IStorage GetModifiedVirtualBlocksStorage() => ModifiedVirtualBlocks.AsReadOnly(); public IStorage GetModifiedVirtualBlocksStorage() => ModifiedVirtualBlocks;
public IStorage GetFreeBlocksStorage() => FreeBlocks.AsReadOnly(); public IStorage GetFreeBlocksStorage() => FreeBlocks;
public void FsTrim() public void FsTrim()
{ {

View File

@ -118,8 +118,8 @@ namespace LibHac.FsSystem.Save
} }
} }
public IStorage GetBaseStorage() => BaseStorage.AsReadOnly(); public IStorage GetBaseStorage() => BaseStorage;
public IStorage GetHeaderStorage() => HeaderStorage.AsReadOnly(); public IStorage GetHeaderStorage() => HeaderStorage;
public void FsTrim() public void FsTrim()
{ {

View File

@ -138,9 +138,9 @@ namespace LibHac.FsSystem.Save
} }
} }
public IStorage GetBaseStorage() => BaseStorage.AsReadOnly(); public IStorage GetBaseStorage() => BaseStorage;
public IStorage GetHeaderStorage() => HeaderStorage.AsReadOnly(); public IStorage GetHeaderStorage() => HeaderStorage;
public IStorage GetMapEntryStorage() => MapEntryStorage.AsReadOnly(); public IStorage GetMapEntryStorage() => MapEntryStorage;
private static RemapSegment[] InitSegments(RemapHeader header, MapEntry[] mapEntries) private static RemapSegment[] InitSegments(RemapHeader header, MapEntry[] mapEntries)
{ {

View File

@ -261,8 +261,8 @@ namespace LibHac.FsSystem.Save
return Result.Success; return Result.Success;
} }
public IStorage GetBaseStorage() => BaseStorage.AsReadOnly(); public IStorage GetBaseStorage() => BaseStorage;
public IStorage GetHeaderStorage() => HeaderStorage.AsReadOnly(); public IStorage GetHeaderStorage() => HeaderStorage;
public void FsTrim() public void FsTrim()
{ {

View File

@ -54,18 +54,15 @@ namespace LibHac.FsSystem
public static IStorage Slice(this IStorage storage, long start, long length, bool leaveOpen) public static IStorage Slice(this IStorage storage, long start, long length, bool leaveOpen)
{ {
return new SubStorage(storage, start, length, leaveOpen); if (!leaveOpen)
} {
return new SubStorage(storage, start, length);
}
public static IStorage AsReadOnly(this IStorage storage) using (var sharedStorage = new ReferenceCountedDisposable<IStorage>(storage))
{ {
return storage.AsReadOnly(true); return new SubStorage(sharedStorage, start, length);
} }
public static IStorage AsReadOnly(this IStorage storage, bool leaveOpen)
{
storage.GetSize(out long storageSize).ThrowIfFailure();
return new SubStorage(storage, 0, storageSize, leaveOpen, FileAccess.Read);
} }
public static Stream AsStream(this IStorage storage) => new StorageStream(storage, FileAccess.ReadWrite, true); public static Stream AsStream(this IStorage storage) => new StorageStream(storage, FileAccess.ReadWrite, true);

View File

@ -1,101 +0,0 @@
using System;
using System.IO;
using LibHac.Fs;
namespace LibHac.FsSystem
{
public class SubStorage : IStorage
{
private IStorage BaseStorage { get; }
private long Offset { get; }
private FileAccess Access { get; } = FileAccess.ReadWrite;
private long Length { get; set; }
private bool LeaveOpen { get; }
public SubStorage(IStorage baseStorage, long offset, long length)
{
BaseStorage = baseStorage;
Offset = offset;
Length = length;
}
public SubStorage(SubStorage baseStorage, long offset, long length)
{
BaseStorage = baseStorage.BaseStorage;
Offset = baseStorage.Offset + offset;
Length = length;
}
public SubStorage(IStorage baseStorage, long offset, long length, bool leaveOpen)
: this(baseStorage, offset, length)
{
LeaveOpen = leaveOpen;
}
public SubStorage(IStorage baseStorage, long offset, long length, bool leaveOpen, FileAccess access)
: this(baseStorage, offset, length, leaveOpen)
{
Access = access;
}
protected override Result DoRead(long offset, Span<byte> destination)
{
if ((Access & FileAccess.Read) == 0) throw new InvalidOperationException("Storage is not readable");
return BaseStorage.Read(offset + Offset, destination);
}
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
{
if ((Access & FileAccess.Write) == 0) throw new InvalidOperationException("Storage is not writable");
return BaseStorage.Write(offset + Offset, source);
}
protected override Result DoFlush()
{
return BaseStorage.Flush();
}
protected override Result DoGetSize(out long size)
{
size = Length;
return Result.Success;
}
protected override Result DoSetSize(long size)
{
if (BaseStorage == null) return ResultFs.NotInitialized.Log();
// todo: Add IsResizable member
// if (!IsResizable) return ResultFs.SubStorageNotResizable.Log();
if (Offset < 0 || size < 0) return ResultFs.InvalidSize.Log();
Result rc = BaseStorage.GetSize(out long baseSize);
if (rc.IsFailure()) return rc;
if (baseSize != Offset + Length)
{
// SubStorage cannot be resized unless it is located at the end of the base storage.
return ResultFs.UnsupportedOperationInResizableSubStorageSetSize.Log();
}
rc = BaseStorage.SetSize(Offset + size);
if (rc.IsFailure()) return rc;
Length = size;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen)
{
BaseStorage?.Dispose();
}
}
}
}
}

View File

@ -75,7 +75,7 @@ namespace LibHac.Loader
if (inputFileSize < kipFileSize) if (inputFileSize < kipFileSize)
return ResultLibHac.InvalidKipFileSize.Log(); return ResultLibHac.InvalidKipFileSize.Log();
kipData = new SubStorage2(KipStorage, 0, kipFileSize); kipData = new SubStorage(KipStorage, 0, kipFileSize);
return Result.Success; return Result.Success;
} }