Пример #1
0
        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);
        }
Пример #2
0
        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);
        }