From c0393449f1e0719b0a72b449b3827e0bd61e3b08 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 16 Oct 2018 15:01:16 -0500 Subject: [PATCH] IVFS writing --- LibHac/IntegrityVerificationStream.cs | 52 ++++++++++++++-------- LibHac/Streams/RandomAccessSectorStream.cs | 2 +- LibHac/Streams/SectorStream.cs | 4 +- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/LibHac/IntegrityVerificationStream.cs b/LibHac/IntegrityVerificationStream.cs index c8d72f46..4c07f700 100644 --- a/LibHac/IntegrityVerificationStream.cs +++ b/LibHac/IntegrityVerificationStream.cs @@ -90,7 +90,7 @@ namespace LibHac bytesToHash = bytesRead; } } - + if (BlockValidities[blockNum] == Validity.Invalid && integrityCheckLevel == IntegrityCheckLevel.ErrorOnInvalid) { throw new InvalidDataException("Hash error!"); @@ -100,23 +100,7 @@ namespace LibHac if (BlockValidities[blockNum] != Validity.Unchecked) return bytesRead; - _hash.Initialize(); - - if (Type == IntegrityStreamType.Save) - { - _hash.TransformBlock(Salt, 0, Salt.Length, null, 0); - } - - _hash.TransformBlock(buffer, offset, bytesToHash, null, 0); - _hash.TransformFinalBlock(buffer, 0, 0); - - byte[] hash = _hash.Hash; - - if (Type == IntegrityStreamType.Save) - { - // This bit is set on all save hashes - hash[0x1F] |= 0x80; - } + byte[] hash = DoHash(buffer, offset, bytesToHash); Validity validity = Util.ArraysEqual(_hashBuffer, hash) ? Validity.Valid : Validity.Invalid; BlockValidities[blockNum] = validity; @@ -131,7 +115,37 @@ namespace LibHac public override void Write(byte[] buffer, int offset, int count) { - throw new NotImplementedException(); + long blockNum = CurrentSector; + int toWrite = (int)Math.Min(count, Length - Position); + byte[] hash = DoHash(buffer, offset, toWrite); + + base.Write(buffer, offset, count); + + HashStream.Position = blockNum * DigestSize; + HashStream.Write(hash, 0, DigestSize); + } + + private byte[] DoHash(byte[] buffer, int offset, int count) + { + _hash.Initialize(); + + if (Type == IntegrityStreamType.Save) + { + _hash.TransformBlock(Salt, 0, Salt.Length, null, 0); + } + + _hash.TransformBlock(buffer, offset, count, null, 0); + _hash.TransformFinalBlock(buffer, 0, 0); + + byte[] hash = _hash.Hash; + + if (Type == IntegrityStreamType.Save) + { + // This bit is set on all save hashes + hash[0x1F] |= 0x80; + } + + return hash; } public override bool CanRead => true; diff --git a/LibHac/Streams/RandomAccessSectorStream.cs b/LibHac/Streams/RandomAccessSectorStream.cs index 29ccda27..dc56f5ce 100644 --- a/LibHac/Streams/RandomAccessSectorStream.cs +++ b/LibHac/Streams/RandomAccessSectorStream.cs @@ -44,7 +44,7 @@ namespace LibHac.Streams if (_readBytes == 0 || !_bufferDirty) return; _baseStream.Position = _currentSector * _bufferSize; - _baseStream.Write(_buffer, 0, _readBytes); + _baseStream.Write(_buffer, 0, _bufferSize); _readBytes = 0; _bufferDirty = false; diff --git a/LibHac/Streams/SectorStream.cs b/LibHac/Streams/SectorStream.cs index c69d42be..abf7f93f 100644 --- a/LibHac/Streams/SectorStream.cs +++ b/LibHac/Streams/SectorStream.cs @@ -112,7 +112,9 @@ namespace LibHac.Streams public override void Write(byte[] buffer, int offset, int count) { ValidateSize(count); - _baseStream.Write(buffer, offset, count); + int toWrite = (int)Math.Min(count, Length - Position); + + _baseStream.Write(buffer, offset, toWrite); CurrentSector += count / SectorSize; }