Move IStorage classes to the new StorageBase

This commit is contained in:
Alex Barney 2019-10-11 12:57:09 -05:00
parent bfc343e801
commit 162fb4e389
25 changed files with 324 additions and 195 deletions

View file

@ -21,7 +21,7 @@ namespace LibHac.Fs
FsClient = Handle.File.Parent.FsClient;
}
public override Result ReadImpl(long offset, Span<byte> destination)
protected override Result ReadImpl(long offset, Span<byte> destination)
{
lock (_locker)
{
@ -36,7 +36,7 @@ namespace LibHac.Fs
}
}
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
lock (_locker)
{
@ -51,19 +51,19 @@ namespace LibHac.Fs
}
}
public override Result FlushImpl()
protected override Result FlushImpl()
{
return FsClient.FlushFile(Handle);
}
public override Result SetSizeImpl(long size)
protected override Result SetSizeImpl(long size)
{
FileSize = InvalidSize;
return FsClient.SetFileSize(Handle, size);
}
public override Result GetSizeImpl(out long size)
protected override Result GetSizeImpl(out long size)
{
size = default;

View file

@ -105,10 +105,10 @@
public static Result UnsupportedOperation => new Result(ModuleFs, 6300);
public static Result SubStorageNotResizable => new Result(ModuleFs, 6302);
public static Result SubStorageNotResizableMiddleOfFile => new Result(ModuleFs, 6302);
public static Result UnsupportedOperationInMemoryStorageSetSize => new Result(ModuleFs, 6316);
public static Result UnsupportedOperationInHierarchicalIvfcStorageSetSize => new Result(ModuleFs, 6304);
public static Result SubStorageNotResizableMiddleOfFile => new Result(ModuleFs, 6303);
public static Result UnsupportedOperationInMemoryStorageSetSize => new Result(ModuleFs, 6304);
public static Result UnsupportedOperationInAesCtrExStorageWrite => new Result(ModuleFs, 6310);
public static Result UnsupportedOperationInHierarchicalIvfcStorageSetSize => new Result(ModuleFs, 6316);
public static Result UnsupportedOperationInIndirectStorageWrite => new Result(ModuleFs, 6324);
public static Result UnsupportedOperationInIndirectStorageSetSize => new Result(ModuleFs, 6325);
public static Result UnsupportedOperationInRoGameCardStorageWrite => new Result(ModuleFs, 6350);

View file

@ -9,11 +9,11 @@ namespace LibHac.Fs
private int _disposedState;
private bool IsDisposed => _disposedState != 0;
public abstract Result ReadImpl(long offset, Span<byte> destination);
public abstract Result WriteImpl(long offset, ReadOnlySpan<byte> source);
public abstract Result FlushImpl();
public abstract Result GetSizeImpl(out long size);
public abstract Result SetSizeImpl(long size);
protected abstract Result ReadImpl(long offset, Span<byte> destination);
protected abstract Result WriteImpl(long offset, ReadOnlySpan<byte> source);
protected abstract Result FlushImpl();
protected abstract Result GetSizeImpl(out long size);
protected abstract Result SetSizeImpl(long size);
public Result Read(long offset, Span<byte> destination)
{

View file

@ -23,7 +23,7 @@ namespace LibHac.Fs
Size = size;
}
public override Result ReadImpl(long offset, Span<byte> destination)
protected override Result ReadImpl(long offset, Span<byte> destination)
{
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
if (destination.Length == 0) return Result.Success;
@ -33,7 +33,7 @@ namespace LibHac.Fs
return BaseStorage.Read(Offset + offset, destination);
}
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
if (source.Length == 0) return Result.Success;
@ -43,14 +43,14 @@ namespace LibHac.Fs
return BaseStorage.Write(Offset + offset, source);
}
public override Result FlushImpl()
protected override Result FlushImpl()
{
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
return BaseStorage.Flush();
}
public override Result SetSizeImpl(long size)
protected override Result SetSizeImpl(long size)
{
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
if (!IsResizable) return ResultFs.SubStorageNotResizable.Log();
@ -72,7 +72,7 @@ namespace LibHac.Fs
return Result.Success;
}
public override Result GetSizeImpl(out long size)
protected override Result GetSizeImpl(out long size)
{
size = default;

View file

@ -87,7 +87,7 @@ namespace LibHac.FsService.Creators
imageHash.CopyTo(ImageHash);
}
public override Result ReadImpl(long offset, Span<byte> destination)
protected override Result ReadImpl(long offset, Span<byte> destination)
{
// In secure mode, if Handle is old and the card's device ID and
// header hash are still the same, Handle is updated to the new handle
@ -95,22 +95,22 @@ namespace LibHac.FsService.Creators
return GameCard.Read(Handle, offset, destination);
}
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
return ResultFs.UnsupportedOperationInRoGameCardStorageWrite.Log();
}
public override Result FlushImpl()
protected override Result FlushImpl()
{
return Result.Success;
}
public override Result SetSizeImpl(long size)
protected override Result SetSizeImpl(long size)
{
return ResultFs.UnsupportedOperationInRoGameCardStorageSetSize.Log();
}
public override Result GetSizeImpl(out long size)
protected override Result GetSizeImpl(out long size)
{
size = 0;

View file

@ -69,7 +69,7 @@ namespace LibHac.FsSystem
return ResultFs.UnsupportedOperationInAesCtrExStorageWrite.Log();
}
public override Result Flush()
protected override Result FlushImpl()
{
return Result.Success;
}

View file

@ -67,7 +67,7 @@ namespace LibHac.FsSystem
return base.WriteImpl(offset, _tempBuffer.AsSpan(0, size));
}
public override Result Flush()
protected override Result FlushImpl()
{
return BaseStorage.Flush();
}

View file

@ -8,7 +8,8 @@ namespace LibHac.FsSystem
{
private IStorage BaseStorage { get; }
private int BlockSize { get; }
private long _length;
private long Length { get; set; }
private bool LeaveOpen { get; }
private LinkedList<CacheBlock> Blocks { get; } = new LinkedList<CacheBlock>();
private Dictionary<long, LinkedListNode<CacheBlock>> BlockDict { get; } = new Dictionary<long, LinkedListNode<CacheBlock>>();
@ -17,9 +18,10 @@ namespace LibHac.FsSystem
{
BaseStorage = baseStorage;
BlockSize = blockSize;
BaseStorage.GetSize(out _length).ThrowIfFailure();
LeaveOpen = leaveOpen;
if (!leaveOpen) ToDispose.Add(BaseStorage);
BaseStorage.GetSize(out long baseSize).ThrowIfFailure();
Length = baseSize;
for (int i = 0; i < cacheSize; i++)
{
@ -37,6 +39,9 @@ namespace LibHac.FsSystem
long inOffset = offset;
int outOffset = 0;
if (!IsRangeValid(offset, destination.Length, Length))
return ResultFs.ValueOutOfRange.Log();
lock (Blocks)
{
while (remaining > 0)
@ -64,6 +69,9 @@ namespace LibHac.FsSystem
long inOffset = offset;
int outOffset = 0;
if (!IsRangeValid(offset, source.Length, Length))
return ResultFs.ValueOutOfRange.Log();
lock (Blocks)
{
while (remaining > 0)
@ -87,7 +95,7 @@ namespace LibHac.FsSystem
return Result.Success;
}
public override Result Flush()
protected override Result FlushImpl()
{
lock (Blocks)
{
@ -100,13 +108,13 @@ namespace LibHac.FsSystem
return BaseStorage.Flush();
}
public override Result GetSize(out long size)
protected override Result GetSizeImpl(out long size)
{
size = _length;
size = Length;
return Result.Success;
}
public override Result SetSize(long size)
protected override Result SetSizeImpl(long size)
{
Result rc = BaseStorage.SetSize(size);
if (rc.IsFailure()) return rc;
@ -114,11 +122,19 @@ namespace LibHac.FsSystem
rc = BaseStorage.GetSize(out long newSize);
if (rc.IsFailure()) return rc;
_length = newSize;
Length = newSize;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (!LeaveOpen)
{
BaseStorage?.Dispose();
}
}
private CacheBlock GetBlock(long blockIndex)
{
if (BlockDict.TryGetValue(blockIndex, out LinkedListNode<CacheBlock> node))
@ -157,9 +173,9 @@ namespace LibHac.FsSystem
long offset = index * BlockSize;
int length = BlockSize;
if (_length != -1)
if (Length != -1)
{
length = (int)Math.Min(_length - offset, length);
length = (int)Math.Min(Length - offset, length);
}
BaseStorage.Read(offset, block.Buffer.AsSpan(0, length)).ThrowIfFailure();

View file

@ -7,12 +7,13 @@ namespace LibHac.FsSystem
public class ConcatenationStorage : StorageBase
{
private ConcatSource[] Sources { get; }
private long _length;
private long Length { get; }
private bool LeaveOpen { get; }
public ConcatenationStorage(IList<IStorage> sources, bool leaveOpen)
{
Sources = new ConcatSource[sources.Count];
if (!leaveOpen) ToDispose.AddRange(sources);
LeaveOpen = leaveOpen;
long length = 0;
for (int i = 0; i < sources.Count; i++)
@ -24,7 +25,7 @@ namespace LibHac.FsSystem
length += sourceSize;
}
_length = length;
Length = length;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
@ -32,6 +33,10 @@ namespace LibHac.FsSystem
long inPos = offset;
int outPos = 0;
int remaining = destination.Length;
if (!IsRangeValid(offset, destination.Length, Length))
return ResultFs.ValueOutOfRange.Log();
int sourceIndex = FindSource(inPos);
while (remaining > 0)
@ -59,6 +64,10 @@ namespace LibHac.FsSystem
long inPos = offset;
int outPos = 0;
int remaining = source.Length;
if (!IsRangeValid(offset, source.Length, Length))
return ResultFs.ValueOutOfRange.Log();
int sourceIndex = FindSource(inPos);
while (remaining > 0)
@ -81,7 +90,7 @@ namespace LibHac.FsSystem
return Result.Success;
}
public override Result Flush()
protected override Result FlushImpl()
{
foreach (ConcatSource source in Sources)
{
@ -92,15 +101,34 @@ namespace LibHac.FsSystem
return Result.Success;
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
size = _length;
return ResultFs.NotImplemented.Log();
}
protected override Result GetSizeImpl(out long size)
{
size = Length;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen && Sources != null)
{
foreach (ConcatSource source in Sources)
{
source?.Storage?.Dispose();
}
}
}
}
private int FindSource(long offset)
{
if (offset < 0 || offset >= _length)
if (offset < 0 || offset >= Length)
throw new ArgumentOutOfRangeException(nameof(offset), offset, "The Storage does not contain this offset.");
int lo = 0;

View file

@ -22,17 +22,17 @@ namespace LibHac.FsSystem
return BaseFile.Write(offset, source);
}
public override Result Flush()
protected override Result FlushImpl()
{
return BaseFile.Flush();
}
public override Result GetSize(out long size)
protected override Result GetSizeImpl(out long size)
{
return BaseFile.GetSize(out size);
}
public override Result SetSize(long size)
protected override Result SetSizeImpl(long size)
{
return BaseFile.SetSize(size);
}

View file

@ -18,7 +18,8 @@ namespace LibHac.FsSystem
/// </summary>
public Validity[][] LevelValidities { get; }
private long _length;
private long Length { get; }
private bool LeaveOpen { get; }
private IntegrityVerificationStorage[] IntegrityStorages { get; }
@ -44,9 +45,10 @@ namespace LibHac.FsSystem
}
DataLevel = Levels[Levels.Length - 1];
DataLevel.GetSize(out _length).ThrowIfFailure();
DataLevel.GetSize(out long dataSize).ThrowIfFailure();
Length = dataSize;
if (!leaveOpen) ToDispose.Add(DataLevel);
LeaveOpen = leaveOpen;
}
public HierarchicalIntegrityVerificationStorage(IvfcHeader header, IStorage masterHash, IStorage data,
@ -104,17 +106,33 @@ namespace LibHac.FsSystem
return DataLevel.Write(offset, source);
}
public override Result Flush()
protected override Result FlushImpl()
{
return DataLevel.Flush();
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
size = _length;
return ResultFs.UnsupportedOperationInHierarchicalIvfcStorageSetSize.Log();
}
protected override Result GetSizeImpl(out long size)
{
size = Length;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen)
{
DataLevel?.Dispose();
}
}
}
/// <summary>
/// Checks the hashes of any unchecked blocks and returns the <see cref="Validity"/> of the data.
/// </summary>
@ -127,7 +145,7 @@ namespace LibHac.FsSystem
IntegrityVerificationStorage storage = IntegrityStorages[IntegrityStorages.Length - 1];
long blockSize = storage.SectorSize;
int blockCount = (int)Util.DivideByRoundUp(_length, blockSize);
int blockCount = (int)Util.DivideByRoundUp(Length, blockSize);
var buffer = new byte[blockSize];
var result = Validity.Valid;

View file

@ -12,20 +12,21 @@ namespace LibHac.FsSystem
private List<IStorage> Sources { get; } = new List<IStorage>();
private BucketTree<RelocationEntry> BucketTree { get; }
private long _length;
private long Length { get; }
private bool LeaveOpen { get; }
public IndirectStorage(IStorage bucketTreeData, bool leaveOpen, params IStorage[] sources)
{
Sources.AddRange(sources);
if (!leaveOpen) ToDispose.AddRange(sources);
LeaveOpen = leaveOpen;
BucketTree = new BucketTree<RelocationEntry>(bucketTreeData);
RelocationEntries = BucketTree.GetEntryList();
RelocationOffsets = RelocationEntries.Select(x => x.Offset).ToList();
_length = BucketTree.BucketOffsets.OffsetEnd;
Length = BucketTree.BucketOffsets.OffsetEnd;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
@ -68,22 +69,36 @@ namespace LibHac.FsSystem
return ResultFs.UnsupportedOperationInIndirectStorageSetSize.Log();
}
public override Result Flush()
protected override Result FlushImpl()
{
return Result.Success;
}
public override Result GetSize(out long size)
protected override Result GetSizeImpl(out long size)
{
size = _length;
size = Length;
return Result.Success;
}
public override Result SetSize(long size)
protected override Result SetSizeImpl(long size)
{
return ResultFs.UnsupportedOperationInIndirectStorageSetSize.Log();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen && Sources != null)
{
foreach (IStorage storage in Sources)
{
storage?.Dispose();
}
}
}
}
private RelocationEntry GetRelocationEntry(long offset)
{
int index = RelocationOffsets.BinarySearch(offset);

View file

@ -124,7 +124,7 @@ namespace LibHac.FsSystem
public Result Read(long offset, Span<byte> destination, IntegrityCheckLevel integrityCheckLevel)
{
ValidateParameters(destination, offset);
// ValidateParameters(destination, offset);
return ReadImpl(offset, destination, integrityCheckLevel);
}
@ -188,12 +188,12 @@ namespace LibHac.FsSystem
}
}
public override Result Flush()
protected override Result FlushImpl()
{
Result rc = HashStorage.Flush();
if (rc.IsFailure()) return rc;
return base.Flush();
return base.FlushImpl();
}
public void FsTrim()

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using LibHac.Fs;
namespace LibHac.FsSystem
{
@ -16,9 +17,6 @@ namespace LibHac.FsSystem
Path = path;
Stream = new FileStream(Path, mode, access);
Storage = new StreamStorage(Stream, false);
ToDispose.Add(Storage);
ToDispose.Add(Stream);
}
protected override Result ReadImpl(long offset, Span<byte> destination)
@ -31,14 +29,28 @@ namespace LibHac.FsSystem
return Storage.Write(offset, source);
}
public override Result Flush()
protected override Result FlushImpl()
{
return Storage.Flush();
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
return ResultFs.NotImplemented.Log();
}
protected override Result GetSizeImpl(out long size)
{
return Storage.GetSize(out size);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Storage?.Dispose();
Stream?.Dispose();
}
}
}
}

View file

@ -10,7 +10,7 @@ namespace LibHac.FsSystem
private int _length;
private int _capacity;
private bool _isExpandable;
public MemoryStorage() : this(0) { }
public MemoryStorage(int capacity)
@ -19,7 +19,6 @@ namespace LibHac.FsSystem
_capacity = capacity;
_isExpandable = true;
CanAutoExpand = true;
_buffer = new byte[capacity];
}
@ -41,6 +40,9 @@ namespace LibHac.FsSystem
protected override Result ReadImpl(long offset, Span<byte> destination)
{
if (!IsRangeValid(offset, destination.Length, _length))
return ResultFs.ValueOutOfRange.Log();
_buffer.AsSpan((int)(_start + offset), destination.Length).CopyTo(destination);
return Result.Success;
@ -48,6 +50,9 @@ namespace LibHac.FsSystem
protected override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
if (!IsRangeValid(offset, source.Length, _length))
return ResultFs.ValueOutOfRange.Log();
long requiredCapacity = _start + offset + source.Length;
if (requiredCapacity > _length)
@ -97,15 +102,15 @@ namespace LibHac.FsSystem
}
}
public override Result Flush() => Result.Success;
protected override Result FlushImpl() => Result.Success;
public override Result GetSize(out long size)
protected override Result GetSizeImpl(out long size)
{
size = _length;
return Result.Success;
}
public override Result SetSize(long size)
protected override Result SetSizeImpl(long size)
{
return ResultFs.UnsupportedOperationInMemoryStorageSetSize.Log();
}

View file

@ -8,10 +8,11 @@ namespace LibHac.FsSystem
/// </summary>
public class NullStorage : StorageBase
{
public NullStorage() { }
public NullStorage(long length) => _length = length;
private long Length { get; }
public NullStorage() { }
public NullStorage(long length) => Length = length;
private long _length;
protected override Result ReadImpl(long offset, Span<byte> destination)
{
@ -24,14 +25,19 @@ namespace LibHac.FsSystem
return Result.Success;
}
public override Result Flush()
protected override Result FlushImpl()
{
return Result.Success;
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
size = _length;
return ResultFs.NotImplemented.Log();
}
protected override Result GetSizeImpl(out long size)
{
size = Length;
return Result.Success;
}
}

View file

@ -83,18 +83,18 @@ namespace LibHac.FsSystem.Save
return Result.Success;
}
public override Result Flush()
protected override Result FlushImpl()
{
return BaseStorage.Flush();
}
public override Result GetSize(out long size)
protected override Result GetSizeImpl(out long size)
{
size = _length;
return Result.Success;
}
public override Result SetSize(long size)
protected override Result SetSizeImpl(long size)
{
int oldBlockCount = (int)Util.DivideByRoundUp(_length, BlockSize);
int newBlockCount = (int)Util.DivideByRoundUp(size, BlockSize);

View file

@ -11,7 +11,7 @@ namespace LibHac.FsSystem.Save
private IStorage DataB { get; }
private DuplexBitmap Bitmap { get; }
private long _length;
private long Length { get; }
public DuplexStorage(IStorage dataA, IStorage dataB, IStorage bitmap, int blockSize)
{
@ -23,7 +23,8 @@ namespace LibHac.FsSystem.Save
bitmap.GetSize(out long bitmapSize).ThrowIfFailure();
Bitmap = new DuplexBitmap(BitmapStorage, (int)(bitmapSize * 8));
DataA.GetSize(out _length).ThrowIfFailure();
DataA.GetSize(out long dataSize).ThrowIfFailure();
Length = dataSize;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
@ -32,6 +33,9 @@ namespace LibHac.FsSystem.Save
int outPos = 0;
int remaining = destination.Length;
if (!IsRangeValid(offset, destination.Length, Length))
return ResultFs.ValueOutOfRange.Log();
while (remaining > 0)
{
int blockNum = (int)(inPos / BlockSize);
@ -58,6 +62,9 @@ namespace LibHac.FsSystem.Save
int outPos = 0;
int remaining = source.Length;
if (!IsRangeValid(offset, source.Length, Length))
return ResultFs.ValueOutOfRange.Log();
while (remaining > 0)
{
int blockNum = (int)(inPos / BlockSize);
@ -78,7 +85,7 @@ namespace LibHac.FsSystem.Save
return Result.Success;
}
public override Result Flush()
protected override Result FlushImpl()
{
Result rc = BitmapStorage.Flush();
if (rc.IsFailure()) return rc;
@ -92,9 +99,14 @@ namespace LibHac.FsSystem.Save
return Result.Success;
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
size = _length;
return ResultFs.NotImplemented.Log();
}
protected override Result GetSizeImpl(out long size)
{
size = Length;
return Result.Success;
}

View file

@ -7,7 +7,7 @@ namespace LibHac.FsSystem.Save
{
private DuplexStorage[] Layers { get; }
private DuplexStorage DataLayer { get; }
private long _length;
private long Length { get; }
public HierarchicalDuplexStorage(DuplexFsLayerInfo[] layers, bool masterBit)
{
@ -30,7 +30,8 @@ namespace LibHac.FsSystem.Save
}
DataLayer = Layers[Layers.Length - 1];
DataLayer.GetSize(out _length).ThrowIfFailure();
DataLayer.GetSize(out long dataSize).ThrowIfFailure();
Length = dataSize;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
@ -43,14 +44,19 @@ namespace LibHac.FsSystem.Save
return DataLayer.Write(offset, source);
}
public override Result Flush()
protected override Result FlushImpl()
{
return DataLayer.Flush();
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
size = _length;
return ResultFs.NotImplemented.Log();
}
protected override Result GetSizeImpl(out long size)
{
size = Length;
return Result.Success;
}

View file

@ -15,7 +15,8 @@ namespace LibHac.FsSystem.Save
public int BlockSize { get; }
private long _length;
private long Length { get; }
private bool LeaveOpen { get; }
public JournalStorage(IStorage baseStorage, IStorage header, JournalMapParams mapInfo, bool leaveOpen)
{
@ -27,9 +28,9 @@ namespace LibHac.FsSystem.Save
Map = new JournalMap(mapHeader, mapInfo);
BlockSize = (int)Header.BlockSize;
_length = Header.TotalSize - Header.JournalSize;
Length = Header.TotalSize - Header.JournalSize;
if (!leaveOpen) ToDispose.Add(baseStorage);
LeaveOpen = leaveOpen;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
@ -38,6 +39,9 @@ namespace LibHac.FsSystem.Save
int outPos = 0;
int remaining = destination.Length;
if (!IsRangeValid(offset, destination.Length, Length))
return ResultFs.ValueOutOfRange.Log();
while (remaining > 0)
{
int blockNum = (int)(inPos / BlockSize);
@ -64,6 +68,9 @@ namespace LibHac.FsSystem.Save
int outPos = 0;
int remaining = source.Length;
if (!IsRangeValid(offset, source.Length, Length))
return ResultFs.ValueOutOfRange.Log();
while (remaining > 0)
{
int blockNum = (int)(inPos / BlockSize);
@ -84,17 +91,33 @@ namespace LibHac.FsSystem.Save
return Result.Success;
}
public override Result Flush()
protected override Result FlushImpl()
{
return BaseStorage.Flush();
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
size = _length;
return ResultFs.NotImplemented.Log();
}
protected override Result GetSizeImpl(out long size)
{
size = Length;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen)
{
BaseStorage?.Dispose();
}
}
}
public IStorage GetBaseStorage() => BaseStorage.AsReadOnly();
public IStorage GetHeaderStorage() => HeaderStorage.AsReadOnly();

View file

@ -13,6 +13,7 @@ namespace LibHac.FsSystem.Save
private IStorage BaseStorage { get; }
private IStorage HeaderStorage { get; }
private IStorage MapEntryStorage { get; }
private bool LeaveOpen { get; }
private RemapHeader Header { get; }
public MapEntry[] MapEntries { get; set; }
@ -42,7 +43,7 @@ namespace LibHac.FsSystem.Save
MapEntries[i] = new MapEntry(reader);
}
if (!leaveOpen) ToDispose.Add(BaseStorage);
LeaveOpen = leaveOpen;
Segments = InitSegments(Header, MapEntries);
}
@ -109,18 +110,34 @@ namespace LibHac.FsSystem.Save
return Result.Success;
}
public override Result Flush()
protected override Result FlushImpl()
{
return BaseStorage.Flush();
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
return ResultFs.UnsupportedOperationInHierarchicalIvfcStorageSetSize.Log();
}
protected override Result GetSizeImpl(out long size)
{
// todo: Different result code
size = -1;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen)
{
BaseStorage?.Dispose();
}
}
}
public IStorage GetBaseStorage() => BaseStorage.AsReadOnly();
public IStorage GetHeaderStorage() => HeaderStorage.AsReadOnly();
public IStorage GetMapEntryStorage() => MapEntryStorage.AsReadOnly();

View file

@ -10,7 +10,8 @@ namespace LibHac.FsSystem
public int SectorSize { get; }
public int SectorCount { get; private set; }
private long _length;
private long Length { get; set; }
private bool LeaveOpen { get; }
public SectorStorage(IStorage baseStorage, int sectorSize, bool leaveOpen)
{
@ -20,9 +21,9 @@ namespace LibHac.FsSystem
baseStorage.GetSize(out long baseSize).ThrowIfFailure();
SectorCount = (int)Util.DivideByRoundUp(baseSize, SectorSize);
_length = baseSize;
Length = baseSize;
if (!leaveOpen) ToDispose.Add(BaseStorage);
LeaveOpen = leaveOpen;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
@ -37,18 +38,18 @@ namespace LibHac.FsSystem
return BaseStorage.Write(offset, source);
}
public override Result Flush()
protected override Result FlushImpl()
{
return BaseStorage.Flush();
}
public override Result GetSize(out long size)
protected override Result GetSizeImpl(out long size)
{
size = _length;
size = Length;
return Result.Success;
}
public override Result SetSize(long size)
protected override Result SetSizeImpl(long size)
{
Result rc = BaseStorage.SetSize(size);
if (rc.IsFailure()) return rc;
@ -57,11 +58,22 @@ namespace LibHac.FsSystem
if (rc.IsFailure()) return rc;
SectorCount = (int)Util.DivideByRoundUp(newSize, SectorSize);
_length = newSize;
Length = newSize;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen)
{
BaseStorage?.Dispose();
}
}
}
/// <summary>
/// Validates that the size is a multiple of the sector size
/// </summary>

View file

@ -1,71 +0,0 @@
using System;
using System.Collections.Generic;
using LibHac.Fs;
namespace LibHac.FsSystem
{
public abstract class StorageBase : IStorage
{
private bool _isDisposed;
protected internal List<IDisposable> ToDispose { get; } = new List<IDisposable>();
protected bool CanAutoExpand { get; set; }
protected abstract Result ReadImpl(long offset, Span<byte> destination);
protected abstract Result WriteImpl(long offset, ReadOnlySpan<byte> source);
public abstract Result Flush();
public abstract Result GetSize(out long size);
public Result Read(long offset, Span<byte> destination)
{
ValidateParameters(destination, offset);
return ReadImpl(offset, destination);
}
public Result Write(long offset, ReadOnlySpan<byte> source)
{
ValidateParameters(source, offset);
return WriteImpl(offset, source);
}
public virtual Result SetSize(long size)
{
return ResultFs.NotImplemented.Log();
}
protected virtual void Dispose(bool disposing)
{
if (_isDisposed) return;
if (disposing)
{
Flush();
foreach (IDisposable item in ToDispose)
{
item?.Dispose();
}
}
_isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void ValidateParameters(ReadOnlySpan<byte> span, long offset)
{
if (_isDisposed) throw new ObjectDisposedException(null);
if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset), "Argument must be non-negative.");
Result sizeResult = GetSize(out long length);
sizeResult.ThrowIfFailure();
if (length != -1 && !CanAutoExpand)
{
if (offset + span.Length > length) throw new ArgumentException("The given offset and count exceed the length of the Storage");
}
}
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using LibHac.Fs;
#if !STREAM_SPAN
using System.Buffers;
@ -13,13 +14,14 @@ namespace LibHac.FsSystem
private Stream BaseStream { get; }
private object Locker { get; } = new object();
private long _length;
private long Length { get; }
private bool LeaveOpen { get; }
public StreamStorage(Stream baseStream, bool leaveOpen)
{
BaseStream = baseStream;
_length = BaseStream.Length;
if (!leaveOpen) ToDispose.Add(BaseStream);
Length = BaseStream.Length;
LeaveOpen = leaveOpen;
}
protected override Result ReadImpl(long offset, Span<byte> destination)
@ -90,7 +92,7 @@ namespace LibHac.FsSystem
return Result.Success;
}
public override Result Flush()
protected override Result FlushImpl()
{
lock (Locker)
{
@ -100,10 +102,26 @@ namespace LibHac.FsSystem
}
}
public override Result GetSize(out long size)
protected override Result SetSizeImpl(long size)
{
size = _length;
return ResultFs.NotImplemented.Log();
}
protected override Result GetSizeImpl(out long size)
{
size = Length;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen)
{
BaseStream?.Dispose();
}
}
}
}
}

View file

@ -9,26 +9,27 @@ namespace LibHac.FsSystem
private IStorage BaseStorage { get; }
private long Offset { get; }
private FileAccess Access { get; } = FileAccess.ReadWrite;
private long _length;
private long Length { get; set; }
private bool LeaveOpen { get; }
public SubStorage(IStorage baseStorage, long offset, long length)
{
BaseStorage = baseStorage;
Offset = offset;
_length = length;
Length = length;
}
public SubStorage(SubStorage baseStorage, long offset, long length)
{
BaseStorage = baseStorage.BaseStorage;
Offset = baseStorage.Offset + offset;
_length = length;
Length = length;
}
public SubStorage(IStorage baseStorage, long offset, long length, bool leaveOpen)
: this(baseStorage, offset, length)
{
if (!leaveOpen) ToDispose.Add(BaseStorage);
LeaveOpen = leaveOpen;
}
public SubStorage(IStorage baseStorage, long offset, long length, bool leaveOpen, FileAccess access)
@ -49,18 +50,18 @@ namespace LibHac.FsSystem
return BaseStorage.Write(offset + Offset, source);
}
public override Result Flush()
protected override Result FlushImpl()
{
return BaseStorage.Flush();
}
public override Result GetSize(out long size)
protected override Result GetSizeImpl(out long size)
{
size = _length;
size = Length;
return Result.Success;
}
public override Result SetSize(long size)
protected override Result SetSizeImpl(long size)
{
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
@ -72,7 +73,7 @@ namespace LibHac.FsSystem
Result rc = BaseStorage.GetSize(out long baseSize);
if (rc.IsFailure()) return rc;
if (baseSize != Offset + _length)
if (baseSize != Offset + Length)
{
// SubStorage cannot be resized unless it is located at the end of the base storage.
return ResultFs.SubStorageNotResizableMiddleOfFile.Log();
@ -81,9 +82,20 @@ namespace LibHac.FsSystem
rc = BaseStorage.SetSize(Offset + size);
if (rc.IsFailure()) return rc;
_length = size;
Length = size;
return Result.Success;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!LeaveOpen)
{
BaseStorage?.Dispose();
}
}
}
}
}