public bool?VerifyMediaImage() { // This will traverse all blocks and check their CRC64 without uncompressing them DicConsole.DebugWriteLine("DiscImageChef format plugin", "Checking index integrity at {0}", header.indexOffset); imageStream.Position = (long)header.indexOffset; IndexHeader idxHeader = new IndexHeader(); structureBytes = new byte[Marshal.SizeOf(idxHeader)]; imageStream.Read(structureBytes, 0, structureBytes.Length); structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(idxHeader)); Marshal.Copy(structureBytes, 0, structurePointer, Marshal.SizeOf(idxHeader)); idxHeader = (IndexHeader)Marshal.PtrToStructure(structurePointer, typeof(IndexHeader)); Marshal.FreeHGlobal(structurePointer); if (idxHeader.identifier != BlockType.Index) { DicConsole.DebugWriteLine("DiscImageChef format plugin", "Incorrect index identifier"); return(false); } DicConsole.DebugWriteLine("DiscImageChef format plugin", "Index at {0} contains {1} entries", header.indexOffset, idxHeader.entries); structureBytes = new byte[Marshal.SizeOf(typeof(IndexEntry)) * idxHeader.entries]; imageStream.Read(structureBytes, 0, structureBytes.Length); Crc64Context.Data(structureBytes, out byte[] verifyCrc); if (BitConverter.ToUInt64(verifyCrc, 0) != idxHeader.crc64) { DicConsole.DebugWriteLine("DiscImageChef format plugin", "Expected index CRC {0:X16} but got {1:X16}", idxHeader.crc64, BitConverter.ToUInt64(verifyCrc, 0)); return(false); } imageStream.Position -= structureBytes.Length; List <IndexEntry> vrIndex = new List <IndexEntry>(); for (ushort i = 0; i < idxHeader.entries; i++) { IndexEntry entry = new IndexEntry(); structureBytes = new byte[Marshal.SizeOf(entry)]; imageStream.Read(structureBytes, 0, structureBytes.Length); structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(entry)); Marshal.Copy(structureBytes, 0, structurePointer, Marshal.SizeOf(entry)); entry = (IndexEntry)Marshal.PtrToStructure(structurePointer, typeof(IndexEntry)); Marshal.FreeHGlobal(structurePointer); DicConsole.DebugWriteLine("DiscImageChef format plugin", "Block type {0} with data type {1} is indexed to be at {2}", entry.blockType, entry.dataType, entry.offset); vrIndex.Add(entry); } // Read up to 1MiB at a time for verification const int VERIFY_SIZE = 1024 * 1024; foreach (IndexEntry entry in vrIndex) { imageStream.Position = (long)entry.offset; Crc64Context crcVerify; ulong readBytes; byte[] verifyBytes; switch (entry.blockType) { case BlockType.DataBlock: BlockHeader blockHeader = new BlockHeader(); structureBytes = new byte[Marshal.SizeOf(blockHeader)]; imageStream.Read(structureBytes, 0, structureBytes.Length); structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(blockHeader)); Marshal.Copy(structureBytes, 0, structurePointer, Marshal.SizeOf(blockHeader)); blockHeader = (BlockHeader)Marshal.PtrToStructure(structurePointer, typeof(BlockHeader)); Marshal.FreeHGlobal(structurePointer); crcVerify = new Crc64Context(); readBytes = 0; DicConsole.DebugWriteLine("DiscImageChef format plugin", "Verifying data block type {0} at position {1}", entry.dataType, entry.offset); while (readBytes + VERIFY_SIZE < blockHeader.cmpLength) { verifyBytes = new byte[VERIFY_SIZE]; imageStream.Read(verifyBytes, 0, verifyBytes.Length); crcVerify.Update(verifyBytes); readBytes += (ulong)verifyBytes.LongLength; } verifyBytes = new byte[blockHeader.cmpLength - readBytes]; imageStream.Read(verifyBytes, 0, verifyBytes.Length); crcVerify.Update(verifyBytes); verifyCrc = crcVerify.Final(); if (BitConverter.ToUInt64(verifyCrc, 0) != blockHeader.cmpCrc64) { DicConsole.DebugWriteLine("DiscImageChef format plugin", "Expected block CRC {0:X16} but got {1:X16}", blockHeader.cmpCrc64, BitConverter.ToUInt64(verifyCrc, 0)); return(false); } break; case BlockType.DeDuplicationTable: DdtHeader ddtHeader = new DdtHeader(); structureBytes = new byte[Marshal.SizeOf(ddtHeader)]; imageStream.Read(structureBytes, 0, structureBytes.Length); structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(ddtHeader)); Marshal.Copy(structureBytes, 0, structurePointer, Marshal.SizeOf(ddtHeader)); ddtHeader = (DdtHeader)Marshal.PtrToStructure(structurePointer, typeof(DdtHeader)); Marshal.FreeHGlobal(structurePointer); crcVerify = new Crc64Context(); readBytes = 0; DicConsole.DebugWriteLine("DiscImageChef format plugin", "Verifying deduplication table type {0} at position {1}", entry.dataType, entry.offset); while (readBytes + VERIFY_SIZE < ddtHeader.cmpLength) { verifyBytes = new byte[readBytes]; imageStream.Read(verifyBytes, 0, verifyBytes.Length); crcVerify.Update(verifyBytes); readBytes += (ulong)verifyBytes.LongLength; } verifyBytes = new byte[ddtHeader.cmpLength - readBytes]; imageStream.Read(verifyBytes, 0, verifyBytes.Length); crcVerify.Update(verifyBytes); verifyCrc = crcVerify.Final(); if (BitConverter.ToUInt64(verifyCrc, 0) != ddtHeader.cmpCrc64) { DicConsole.DebugWriteLine("DiscImageChef format plugin", "Expected DDT CRC {0:X16} but got {1:X16}", ddtHeader.cmpCrc64, BitConverter.ToUInt64(verifyCrc, 0)); return(false); } break; case BlockType.TracksBlock: TracksHeader trkHeader = new TracksHeader(); structureBytes = new byte[Marshal.SizeOf(trkHeader)]; imageStream.Read(structureBytes, 0, structureBytes.Length); structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(trkHeader)); Marshal.Copy(structureBytes, 0, structurePointer, Marshal.SizeOf(trkHeader)); trkHeader = (TracksHeader)Marshal.PtrToStructure(structurePointer, typeof(TracksHeader)); Marshal.FreeHGlobal(structurePointer); DicConsole.DebugWriteLine("DiscImageChef format plugin", "Track block at {0} contains {1} entries", header.indexOffset, trkHeader.entries); structureBytes = new byte[Marshal.SizeOf(typeof(TrackEntry)) * trkHeader.entries]; imageStream.Read(structureBytes, 0, structureBytes.Length); Crc64Context.Data(structureBytes, out verifyCrc); if (BitConverter.ToUInt64(verifyCrc, 0) != trkHeader.crc64) { DicConsole.DebugWriteLine("DiscImageChef format plugin", "Expected index CRC {0:X16} but got {1:X16}", trkHeader.crc64, BitConverter.ToUInt64(verifyCrc, 0)); return(false); } break; default: DicConsole.DebugWriteLine("DiscImageChef format plugin", "Ignored field type {0}", entry.blockType); break; } } return(true); }
public bool?VerifyMediaImage() { // This will traverse all blocks and check their CRC64 without uncompressing them AaruConsole.DebugWriteLine("Aaru Format plugin", "Checking index integrity at {0}", _header.indexOffset); _imageStream.Position = (long)_header.indexOffset; _structureBytes = new byte[Marshal.SizeOf <IndexHeader>()]; _imageStream.Read(_structureBytes, 0, _structureBytes.Length); IndexHeader idxHeader = Marshal.SpanToStructureLittleEndian <IndexHeader>(_structureBytes); if (idxHeader.identifier != BlockType.Index) { AaruConsole.DebugWriteLine("Aaru Format plugin", "Incorrect index identifier"); return(false); } AaruConsole.DebugWriteLine("Aaru Format plugin", "Index at {0} contains {1} entries", _header.indexOffset, idxHeader.entries); _structureBytes = new byte[Marshal.SizeOf <IndexEntry>() * idxHeader.entries]; _imageStream.Read(_structureBytes, 0, _structureBytes.Length); Crc64Context.Data(_structureBytes, out byte[] verifyCrc); if (BitConverter.ToUInt64(verifyCrc, 0) != idxHeader.crc64) { AaruConsole.DebugWriteLine("Aaru Format plugin", "Expected index CRC {0:X16} but got {1:X16}", idxHeader.crc64, BitConverter.ToUInt64(verifyCrc, 0)); return(false); } _imageStream.Position -= _structureBytes.Length; List <IndexEntry> vrIndex = new List <IndexEntry>(); for (ushort i = 0; i < idxHeader.entries; i++) { _structureBytes = new byte[Marshal.SizeOf <IndexEntry>()]; _imageStream.Read(_structureBytes, 0, _structureBytes.Length); IndexEntry entry = Marshal.SpanToStructureLittleEndian <IndexEntry>(_structureBytes); AaruConsole.DebugWriteLine("Aaru Format plugin", "Block type {0} with data type {1} is indexed to be at {2}", entry.blockType, entry.dataType, entry.offset); vrIndex.Add(entry); } // Read up to 1MiB at a time for verification const int verifySize = 1024 * 1024; foreach (IndexEntry entry in vrIndex) { _imageStream.Position = (long)entry.offset; Crc64Context crcVerify; ulong readBytes; byte[] verifyBytes; switch (entry.blockType) { case BlockType.DataBlock: _structureBytes = new byte[Marshal.SizeOf <BlockHeader>()]; _imageStream.Read(_structureBytes, 0, _structureBytes.Length); BlockHeader blockHeader = Marshal.SpanToStructureLittleEndian <BlockHeader>(_structureBytes); crcVerify = new Crc64Context(); readBytes = 0; AaruConsole.DebugWriteLine("Aaru Format plugin", "Verifying data block type {0} at position {1}", entry.dataType, entry.offset); while (readBytes + verifySize < blockHeader.cmpLength) { verifyBytes = new byte[verifySize]; _imageStream.Read(verifyBytes, 0, verifyBytes.Length); crcVerify.Update(verifyBytes); readBytes += (ulong)verifyBytes.LongLength; } verifyBytes = new byte[blockHeader.cmpLength - readBytes]; _imageStream.Read(verifyBytes, 0, verifyBytes.Length); crcVerify.Update(verifyBytes); verifyCrc = crcVerify.Final(); if (BitConverter.ToUInt64(verifyCrc, 0) != blockHeader.cmpCrc64) { AaruConsole.DebugWriteLine("Aaru Format plugin", "Expected block CRC {0:X16} but got {1:X16}", blockHeader.cmpCrc64, BitConverter.ToUInt64(verifyCrc, 0)); return(false); } break; case BlockType.DeDuplicationTable: _structureBytes = new byte[Marshal.SizeOf <DdtHeader>()]; _imageStream.Read(_structureBytes, 0, _structureBytes.Length); DdtHeader ddtHeader = Marshal.SpanToStructureLittleEndian <DdtHeader>(_structureBytes); crcVerify = new Crc64Context(); readBytes = 0; AaruConsole.DebugWriteLine("Aaru Format plugin", "Verifying deduplication table type {0} at position {1}", entry.dataType, entry.offset); while (readBytes + verifySize < ddtHeader.cmpLength) { verifyBytes = new byte[readBytes]; _imageStream.Read(verifyBytes, 0, verifyBytes.Length); crcVerify.Update(verifyBytes); readBytes += (ulong)verifyBytes.LongLength; } verifyBytes = new byte[ddtHeader.cmpLength - readBytes]; _imageStream.Read(verifyBytes, 0, verifyBytes.Length); crcVerify.Update(verifyBytes); verifyCrc = crcVerify.Final(); if (BitConverter.ToUInt64(verifyCrc, 0) != ddtHeader.cmpCrc64) { AaruConsole.DebugWriteLine("Aaru Format plugin", "Expected DDT CRC {0:X16} but got {1:X16}", ddtHeader.cmpCrc64, BitConverter.ToUInt64(verifyCrc, 0)); return(false); } break; case BlockType.TracksBlock: _structureBytes = new byte[Marshal.SizeOf <TracksHeader>()]; _imageStream.Read(_structureBytes, 0, _structureBytes.Length); TracksHeader trkHeader = Marshal.SpanToStructureLittleEndian <TracksHeader>(_structureBytes); AaruConsole.DebugWriteLine("Aaru Format plugin", "Track block at {0} contains {1} entries", _header.indexOffset, trkHeader.entries); _structureBytes = new byte[Marshal.SizeOf <TrackEntry>() * trkHeader.entries]; _imageStream.Read(_structureBytes, 0, _structureBytes.Length); Crc64Context.Data(_structureBytes, out verifyCrc); if (BitConverter.ToUInt64(verifyCrc, 0) != trkHeader.crc64) { AaruConsole.DebugWriteLine("Aaru Format plugin", "Expected index CRC {0:X16} but got {1:X16}", trkHeader.crc64, BitConverter.ToUInt64(verifyCrc, 0)); return(false); } break; default: AaruConsole.DebugWriteLine("Aaru Format plugin", "Ignored field type {0}", entry.blockType); break; } } return(true); }