diff --git a/Aaru.Images/AaruFormat/Constants.cs b/Aaru.Images/AaruFormat/Constants.cs index 778b575cd..c02c0a54c 100644 --- a/Aaru.Images/AaruFormat/Constants.cs +++ b/Aaru.Images/AaruFormat/Constants.cs @@ -42,7 +42,9 @@ namespace Aaru.DiscImages /// Image format version. A change in this number indicates an incompatible change to the format that prevents /// older implementations from reading it correctly, if at all. /// - const byte AARUFMT_VERSION = 1; + const byte AARUFMT_VERSION_V1 = 1; + /// Adds new index format with 64-bit entries counter + const byte AARUFMT_VERSION = 2; /// Maximum read cache size, 256MiB. const uint MAX_CACHE_SIZE = 256 * 1024 * 1024; /// Size in bytes of LZMA properties. diff --git a/Aaru.Images/AaruFormat/Enums.cs b/Aaru.Images/AaruFormat/Enums.cs index d6599c0ab..ec5c23cc3 100644 --- a/Aaru.Images/AaruFormat/Enums.cs +++ b/Aaru.Images/AaruFormat/Enums.cs @@ -218,9 +218,11 @@ namespace Aaru.DiscImages /// Block containing data DataBlock = 0x4B4C4244, /// Block containing a deduplication table - DeDuplicationTable = 0X2A544444, + DeDuplicationTable = 0x2A544444, /// Block containing the index - Index = 0X58444E49, + Index = 0x58444E49, + /// Block containing the index + Index2 = 0x32584449, /// Block containing logical geometry GeometryBlock = 0x4D4F4547, /// Block containing metadata diff --git a/Aaru.Images/AaruFormat/Read.cs b/Aaru.Images/AaruFormat/Read.cs index e601802d2..c9256640c 100644 --- a/Aaru.Images/AaruFormat/Read.cs +++ b/Aaru.Images/AaruFormat/Read.cs @@ -86,28 +86,62 @@ namespace Aaru.DiscImages imageStream.Read(structureBytes, 0, structureBytes.Length); IndexHeader idxHeader = Marshal.SpanToStructureLittleEndian(structureBytes); - if(idxHeader.identifier != BlockType.Index) + if(idxHeader.identifier != BlockType.Index && + idxHeader.identifier != BlockType.Index2) throw new FeatureUnsupportedImageException("Index not found!"); - AaruConsole.DebugWriteLine("Aaru Format plugin", "Index at {0} contains {1} entries", header.indexOffset, - idxHeader.entries); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", GC.GetTotalMemory(false)); - - // Fill in-memory index - index = new List(); - - for(ushort i = 0; i < idxHeader.entries; i++) + if(idxHeader.identifier == BlockType.Index2) { - structureBytes = new byte[Marshal.SizeOf()]; + imageStream.Position = (long)header.indexOffset; + structureBytes = new byte[Marshal.SizeOf()]; imageStream.Read(structureBytes, 0, structureBytes.Length); - IndexEntry entry = Marshal.SpanToStructureLittleEndian(structureBytes); + IndexHeader2 idxHeader2 = Marshal.SpanToStructureLittleEndian(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); + AaruConsole.DebugWriteLine("Aaru Format plugin", "Index at {0} contains {1} entries", + header.indexOffset, idxHeader2.entries); - index.Add(entry); + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + // Fill in-memory index + index = new List(); + + for(ulong i = 0; i < idxHeader2.entries; i++) + { + structureBytes = new byte[Marshal.SizeOf()]; + imageStream.Read(structureBytes, 0, structureBytes.Length); + IndexEntry entry = Marshal.SpanToStructureLittleEndian(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); + + index.Add(entry); + } + } + else + { + AaruConsole.DebugWriteLine("Aaru Format plugin", "Index at {0} contains {1} entries", + header.indexOffset, idxHeader.entries); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + // Fill in-memory index + index = new List(); + + for(ushort i = 0; i < idxHeader.entries; i++) + { + structureBytes = new byte[Marshal.SizeOf()]; + imageStream.Read(structureBytes, 0, structureBytes.Length); + IndexEntry entry = Marshal.SpanToStructureLittleEndian(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); + + index.Add(entry); + } } AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", GC.GetTotalMemory(false)); diff --git a/Aaru.Images/AaruFormat/Structs.cs b/Aaru.Images/AaruFormat/Structs.cs index c3caf7fa6..59e9487f0 100644 --- a/Aaru.Images/AaruFormat/Structs.cs +++ b/Aaru.Images/AaruFormat/Structs.cs @@ -101,6 +101,18 @@ namespace Aaru.DiscImages public ulong crc64; } + /// Header for the index, followed by entries + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct IndexHeader2 + { + /// Identifier, + public BlockType identifier; + /// How many entries follow this header + public ulong entries; + /// CRC64-ECMA of the index + public ulong crc64; + } + /// Index entry [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IndexEntry diff --git a/Aaru.Images/AaruFormat/Write.cs b/Aaru.Images/AaruFormat/Write.cs index 0cdabd0d9..dd7a628d5 100644 --- a/Aaru.Images/AaruFormat/Write.cs +++ b/Aaru.Images/AaruFormat/Write.cs @@ -270,7 +270,7 @@ namespace Aaru.DiscImages } header.application = "Aaru"; - header.imageMajorVersion = AARUFMT_VERSION; + header.imageMajorVersion = AARUFMT_VERSION_V1; header.imageMinorVersion = 0; header.applicationMajorVersion = (byte)typeof(AaruFormat).Assembly.GetName().Version.Major; header.applicationMinorVersion = (byte)typeof(AaruFormat).Assembly.GetName().Version.Minor; @@ -3357,15 +3357,36 @@ namespace Aaru.DiscImages Crc64Context.Data(blockStream.ToArray(), out byte[] idxCrc); - var idxHeader = new IndexHeader + if(index.Count > ushort.MaxValue) { - identifier = BlockType.Index, entries = (ushort)index.Count, crc64 = BitConverter.ToUInt64(idxCrc, 0) - }; + header.imageMajorVersion = AARUFMT_VERSION; + + var idxHeader = new IndexHeader2 + { + identifier = BlockType.Index2, entries = (ulong)index.Count, + crc64 = BitConverter.ToUInt64(idxCrc, 0) + }; + + // Write index header to disk + structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(structureBytes, ref idxHeader); + imageStream.Write(structureBytes, 0, structureBytes.Length); + } + else + { + var idxHeader = new IndexHeader + { + identifier = BlockType.Index, entries = (ushort)index.Count, + crc64 = BitConverter.ToUInt64(idxCrc, 0) + }; + + // Write index header to disk + structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(structureBytes, ref idxHeader); + imageStream.Write(structureBytes, 0, structureBytes.Length); + } // Write index to disk - structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(structureBytes, ref idxHeader); - imageStream.Write(structureBytes, 0, structureBytes.Length); imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); blockStream.Close(); blockStream = null;