diff --git a/Aaru.Images/AaruFormatOld/AaruFormat.cs b/Aaru.Images/AaruFormatOld/AaruFormat.cs deleted file mode 100644 index 0b719f486..000000000 --- a/Aaru.Images/AaruFormatOld/AaruFormat.cs +++ /dev/null @@ -1,191 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : AaruFormat.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Manages Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// Copyright © 2020-2025 Rebecca Wallander -// ****************************************************************************/ - -/* - The idea of the format is being able to easily store, retrieve, and access any data that can be read from media. - - At the start of a file there's a header that contains a format version, application creator name, and a pointer to - the index. - - The index points to one or several DeDuplication Tables, or media tag blocks. - - A deduplication table is a table of offsets to blocks and sectors inside blocks. Each entry equals to an LBA and points - to a byte offset in the file shift left to the number of sectors contained in a block, plus the number of sector inside - the block. - Each block must contain sectors of equal size, but that size can be different between blocks. - The deduplication table should be stored decompressed if its size is too big to be stored on-memory. This is chosen at - creation time but it is a good idea to set the limit to 256MiB (this allows for a device of 33 million sectors, - 17Gb at 512 bps, 68Gb at 2048 bps and 137Gb at 4096 bps). - - Sector tags that are simply too small to be deduplicated are contained in a single block pointed by the index (e.g. - Apple GCR sector tags). - - Optical disks contain a track block that describes the tracks. - TODO: Streaming tapes contain a file block that describes the files and an optional partition block that describes the tape - partitions. - - There are also blocks for image metadata, contents metadata and dump hardware information. - - A differencing image will have all the metadata and deduplication tables, but the entries in these ones will be set to - 0 if the block is stored in the parent image. TODO: This is not yet implemented. - - Also because the file becomes useless without the index and deduplication table, each can be stored twice. In case of - the index it should just be searched for. In case of deduplication tables, both copies should be indexed. - - Finally, writing new data to an existing image is just Copy-On-Write. Create a new block with the modified data, change - the pointer in the corresponding deduplication table. - - P.S.: Data Position Measurement is doable, as soon as I know how to do it. - P.S.2: Support for floppy image contaning bitslices and/or fluxes will be added soon. -*/ - -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; -using Aaru.Checksums; -using Aaru.CommonTypes.Enums; -using Aaru.CommonTypes.Interfaces; -using Aaru.CommonTypes.Structs; - -namespace Aaru.Images; - -/// -/// Implements reading and writing AaruFormat media images -public sealed partial class AaruFormatOld : IWritableOpticalImage, IVerifiableImage, IWritableTapeImage -{ - const string MODULE_NAME = "Aaru Format plugin"; - bool _alreadyWrittenZero; - /// Cache of uncompressed blocks. - Dictionary _blockCache; - /// Cache of block headers. - Dictionary _blockHeaderCache; - /// Provides checksum for deduplication of sectors. - SHA256 _checksumProvider; - bool _compress; - byte[] _compressedBuffer; - CompressionType _compressionAlgorithm; - /// Provides CRC64. - Crc64Context _crc64; - /// Header of the currently writing block. - BlockHeader _currentBlockHeader; - /// Sector offset of writing position in currently writing block. - uint _currentBlockOffset; - /// Current size in bytes of the block cache - uint _currentCacheSize; - /// Cache of DDT entries. - Dictionary _ddtEntryCache; - bool _deduplicate; - /// On-memory deduplication table indexed by checksum. - Dictionary _deduplicationTable; - /// Dictionary size for compression algorithms - uint _dictionarySize; - /// Block with logical geometry. - GeometryBlock _geometryBlock; - /// Image header. - AaruHeader _header; - /// Image information. - ImageInfo _imageInfo; - /// Image data stream. - Stream _imageStream; - /// Index. - List _index; - /// If set to true, the DDT entries are in-memory. - bool _inMemoryDdt; - ulong _lastWrittenBlock; - Md5Context _md5Provider; - /// Cache of media tags. - Dictionary _mediaTags; - byte[] _mode2Subheaders; - /// If DDT is on-disk, this is the image stream offset at which it starts. - long _outMemoryDdtPosition; - bool _rewinded; - byte[] _sectorCprMai; - byte[] _sectorDecryptedTitleKey; - byte[] _sectorEdc; - byte[] _sectorId; - byte[] _sectorIed; - /// Cache for data that prefixes the user data on a sector (e.g. sync). - byte[] _sectorPrefix; - uint[] _sectorPrefixDdt; - MemoryStream _sectorPrefixMs; - /// Cache for data that goes side by side with user data (e.g. CompactDisc subchannel). - byte[] _sectorSubchannel; - /// Cache for data that suffixes the user data on a sector (e.g. edc, ecc). - byte[] _sectorSuffix; - uint[] _sectorSuffixDdt; - MemoryStream _sectorSuffixMs; - Sha1Context _sha1Provider; - Sha256Context _sha256Provider; - /// Shift for calculating number of sectors in a block. - byte _shift; - SpamSumContext _spamsumProvider; - /// Cache for bytes to write/rad on-disk. - byte[] _structureBytes; - /// Cache for pointer for marshaling structures. - nint _structurePointer; - Dictionary _tapeDdt; - /// Cache of CompactDisc track's flags - Dictionary _trackFlags; - /// Cache of CompactDisc track's ISRC - Dictionary _trackIsrcs; - /// In-memory deduplication table - ulong[] _userDataDdt; - byte[] _writingBuffer; - int _writingBufferPosition; - bool _writingLong; - ulong _writtenSectors; - - public AaruFormatOld() => _imageInfo = new ImageInfo - { - ReadableSectorTags = [], - ReadableMediaTags = [], - HasPartitions = false, - HasSessions = false, - Version = null, - Application = "Aaru", - ApplicationVersion = null, - Creator = null, - Comments = null, - MediaManufacturer = null, - MediaModel = null, - MediaSerialNumber = null, - MediaBarcode = null, - MediaPartNumber = null, - MediaSequence = 0, - LastMediaSequence = 0, - DriveManufacturer = null, - DriveModel = null, - DriveSerialNumber = null, - DriveFirmwareRevision = null - }; -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/CdEcc.cs b/Aaru.Images/AaruFormatOld/CdEcc.cs deleted file mode 100644 index 0bfe66f3a..000000000 --- a/Aaru.Images/AaruFormatOld/CdEcc.cs +++ /dev/null @@ -1,343 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : ClauniaSubchannelTransform.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Contains the CD ECC algorithm. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ECC algorithm from ECM(c) 2002-2011 Neill Corlett -// ****************************************************************************/ - -using System; -using Aaru.CommonTypes.Enums; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ - byte[] _eccBTable; - byte[] _eccFTable; - uint[] _edcTable; - bool _initedEdc; - - void EccInit() - { - if(_initedEdc) return; - - _eccFTable = new byte[256]; - _eccBTable = new byte[256]; - _edcTable = new uint[256]; - - for(uint i = 0; i < 256; i++) - { - uint edc = i; - var j = (uint)(i << 1 ^ ((i & 0x80) == 0x80 ? 0x11D : 0)); - _eccFTable[i] = (byte)j; - _eccBTable[i ^ j] = (byte)i; - - for(j = 0; j < 8; j++) edc = edc >> 1 ^ ((edc & 1) > 0 ? 0xD8018001 : 0); - - _edcTable[i] = edc; - } - - _initedEdc = true; - } - - bool SuffixIsCorrect(byte[] sector) - { - if(!_initedEdc) EccInit(); - - if(sector[0x814] != 0x00 || // reserved (8 bytes) - sector[0x815] != 0x00 || - sector[0x816] != 0x00 || - sector[0x817] != 0x00 || - sector[0x818] != 0x00 || - sector[0x819] != 0x00 || - sector[0x81A] != 0x00 || - sector[0x81B] != 0x00) - return false; - - bool correctEccP = CheckEcc(sector, sector, 86, 24, 2, 86, sector, 0xC, 0x10, 0x81C); - - if(!correctEccP) return false; - - bool correctEccQ = CheckEcc(sector, sector, 52, 43, 86, 88, sector, 0xC, 0x10, 0x81C + 0xAC); - - if(!correctEccQ) return false; - - var storedEdc = BitConverter.ToUInt32(sector, 0x810); - uint edc = 0; - var size = 0x810; - var pos = 0; - - for(; size > 0; size--) edc = edc >> 8 ^ _edcTable[(edc ^ sector[pos++]) & 0xFF]; - - uint calculatedEdc = edc; - - return calculatedEdc == storedEdc; - } - - bool SuffixIsCorrectMode2(byte[] sector) - { - if(!_initedEdc) EccInit(); - - var zeroAddress = new byte[4]; - - bool correctEccP = CheckEcc(zeroAddress, sector, 86, 24, 2, 86, sector, 0, 0x10, 0x81C); - - if(!correctEccP) return false; - - bool correctEccQ = CheckEcc(zeroAddress, sector, 52, 43, 86, 88, sector, 0, 0x10, 0x81C + 0xAC); - - if(!correctEccQ) return false; - - var storedEdc = BitConverter.ToUInt32(sector, 0x818); - uint edc = 0; - var size = 0x808; - var pos = 0x10; - - for(; size > 0; size--) edc = edc >> 8 ^ _edcTable[(edc ^ sector[pos++]) & 0xFF]; - - uint calculatedEdc = edc; - - return calculatedEdc == storedEdc; - } - - bool CheckEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, uint minorInc, - byte[] ecc, int addressOffset, int dataOffset, int eccOffset) - { - uint size = majorCount * minorCount; - uint major; - - for(major = 0; major < majorCount; major++) - { - uint idx = (major >> 1) * majorMult + (major & 1); - byte eccA = 0; - byte eccB = 0; - uint minor; - - for(minor = 0; minor < minorCount; minor++) - { - byte temp = idx < 4 ? address[idx + addressOffset] : data[idx + dataOffset - 4]; - idx += minorInc; - - if(idx >= size) idx -= size; - - eccA ^= temp; - eccB ^= temp; - eccA = _eccFTable[eccA]; - } - - eccA = _eccBTable[_eccFTable[eccA] ^ eccB]; - - if(ecc[major + eccOffset] != eccA || ecc[major + majorCount + eccOffset] != (eccA ^ eccB)) return false; - } - - return true; - } - - void WriteEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, uint minorInc, - ref byte[] ecc, int addressOffset, int dataOffset, int eccOffset) - { - uint size = majorCount * minorCount; - uint major; - - for(major = 0; major < majorCount; major++) - { - uint idx = (major >> 1) * majorMult + (major & 1); - byte eccA = 0; - byte eccB = 0; - uint minor; - - for(minor = 0; minor < minorCount; minor++) - { - byte temp = idx < 4 ? address[idx + addressOffset] : data[idx + dataOffset - 4]; - idx += minorInc; - - if(idx >= size) idx -= size; - - eccA ^= temp; - eccB ^= temp; - eccA = _eccFTable[eccA]; - } - - eccA = _eccBTable[_eccFTable[eccA] ^ eccB]; - ecc[major + eccOffset] = eccA; - ecc[major + majorCount + eccOffset] = (byte)(eccA ^ eccB); - } - } - - void EccWriteSector(byte[] address, byte[] data, ref byte[] ecc, int addressOffset, int dataOffset, int eccOffset) - { - WriteEcc(address, data, 86, 24, 2, 86, ref ecc, addressOffset, dataOffset, eccOffset); // P - WriteEcc(address, data, 52, 43, 86, 88, ref ecc, addressOffset, dataOffset, eccOffset + 0xAC); // Q - } - - static (byte minute, byte second, byte frame) LbaToMsf(long pos) => - ((byte)((pos + 150) / 75 / 60), (byte)((pos + 150) / 75 % 60), (byte)((pos + 150) % 75)); - - static void ReconstructPrefix(ref byte[] sector, // must point to a full 2352-byte sector - TrackType type, long lba) - { - // - // Sync - // - sector[0x000] = 0x00; - sector[0x001] = 0xFF; - sector[0x002] = 0xFF; - sector[0x003] = 0xFF; - sector[0x004] = 0xFF; - sector[0x005] = 0xFF; - sector[0x006] = 0xFF; - sector[0x007] = 0xFF; - sector[0x008] = 0xFF; - sector[0x009] = 0xFF; - sector[0x00A] = 0xFF; - sector[0x00B] = 0x00; - - (byte minute, byte second, byte frame) msf = LbaToMsf(lba); - - sector[0x00C] = (byte)((msf.minute / 10 << 4) + msf.minute % 10); - sector[0x00D] = (byte)((msf.second / 10 << 4) + msf.second % 10); - sector[0x00E] = (byte)((msf.frame / 10 << 4) + msf.frame % 10); - - switch(type) - { - case TrackType.CdMode1: - // - // Mode - // - sector[0x00F] = 0x01; - - break; - case TrackType.CdMode2Form1: - case TrackType.CdMode2Form2: - case TrackType.CdMode2Formless: - // - // Mode - // - sector[0x00F] = 0x02; - - // - // Flags - // - sector[0x010] = sector[0x014]; - sector[0x011] = sector[0x015]; - sector[0x012] = sector[0x016]; - sector[0x013] = sector[0x017]; - - break; - default: - return; - } - } - - void ReconstructEcc(ref byte[] sector, // must point to a full 2352-byte sector - TrackType type) - { - byte[] computedEdc; - - if(!_initedEdc) EccInit(); - - switch(type) - { - // - // Compute EDC - // - case TrackType.CdMode1: - computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x810)); - sector[0x810] = computedEdc[0]; - sector[0x811] = computedEdc[1]; - sector[0x812] = computedEdc[2]; - sector[0x813] = computedEdc[3]; - - break; - case TrackType.CdMode2Form1: - computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x808, 0x10)); - sector[0x818] = computedEdc[0]; - sector[0x819] = computedEdc[1]; - sector[0x81A] = computedEdc[2]; - sector[0x81B] = computedEdc[3]; - - break; - case TrackType.CdMode2Form2: - computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x91C, 0x10)); - sector[0x92C] = computedEdc[0]; - sector[0x92D] = computedEdc[1]; - sector[0x92E] = computedEdc[2]; - sector[0x92F] = computedEdc[3]; - - break; - default: - return; - } - - var zeroAddress = new byte[4]; - - switch(type) - { - // - // Compute ECC - // - case TrackType.CdMode1: - // - // Reserved - // - sector[0x814] = 0x00; - sector[0x815] = 0x00; - sector[0x816] = 0x00; - sector[0x817] = 0x00; - sector[0x818] = 0x00; - sector[0x819] = 0x00; - sector[0x81A] = 0x00; - sector[0x81B] = 0x00; - EccWriteSector(sector, sector, ref sector, 0xC, 0x10, 0x81C); - - break; - case TrackType.CdMode2Form1: - EccWriteSector(zeroAddress, sector, ref sector, 0, 0x10, 0x81C); - - break; - default: - return; - } - - // - // Done - // - } - - uint ComputeEdc(uint edc, byte[] src, int size, int srcOffset = 0) - { - if(!_initedEdc) EccInit(); - - int pos = srcOffset; - - for(; size > 0; size--) edc = edc >> 8 ^ _edcTable[(edc ^ src[pos++]) & 0xFF]; - - return edc; - } -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/ClauniaSubchannelTransform.cs b/Aaru.Images/AaruFormatOld/ClauniaSubchannelTransform.cs deleted file mode 100644 index acfc634f9..000000000 --- a/Aaru.Images/AaruFormatOld/ClauniaSubchannelTransform.cs +++ /dev/null @@ -1,310 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : ClauniaSubchannelTransform.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Contains the Claunia Subchannel Transform algorithm. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -using System; -using System.Diagnostics; -using Aaru.Logging; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ - static byte[] ClauniaSubchannelTransform(byte[] interleaved) - { - if(interleaved == null) return null; - - int[] p = new int[interleaved.Length / 8]; - int[] q = new int[interleaved.Length / 8]; - int[] r = new int[interleaved.Length / 8]; - int[] s = new int[interleaved.Length / 8]; - int[] t = new int[interleaved.Length / 8]; - int[] u = new int[interleaved.Length / 8]; - int[] v = new int[interleaved.Length / 8]; - int[] w = new int[interleaved.Length / 8]; - - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - for(int i = 0; i < interleaved.Length; i += 8) - { - p[i / 8] = interleaved[i] & 0x80; - p[i / 8] += (interleaved[i + 1] & 0x80) >> 1; - p[i / 8] += (interleaved[i + 2] & 0x80) >> 2; - p[i / 8] += (interleaved[i + 3] & 0x80) >> 3; - p[i / 8] += (interleaved[i + 4] & 0x80) >> 4; - p[i / 8] += (interleaved[i + 5] & 0x80) >> 5; - p[i / 8] += (interleaved[i + 6] & 0x80) >> 6; - p[i / 8] += (interleaved[i + 7] & 0x80) >> 7; - - q[i / 8] = (interleaved[i] & 0x40) << 1; - q[i / 8] += interleaved[i + 1] & 0x40; - q[i / 8] += (interleaved[i + 2] & 0x40) >> 1; - q[i / 8] += (interleaved[i + 3] & 0x40) >> 2; - q[i / 8] += (interleaved[i + 4] & 0x40) >> 3; - q[i / 8] += (interleaved[i + 5] & 0x40) >> 4; - q[i / 8] += (interleaved[i + 6] & 0x40) >> 5; - q[i / 8] += (interleaved[i + 7] & 0x40) >> 6; - - r[i / 8] = (interleaved[i] & 0x20) << 2; - r[i / 8] += (interleaved[i + 1] & 0x20) << 1; - r[i / 8] += interleaved[i + 2] & 0x20; - r[i / 8] += (interleaved[i + 3] & 0x20) >> 1; - r[i / 8] += (interleaved[i + 4] & 0x20) >> 2; - r[i / 8] += (interleaved[i + 5] & 0x20) >> 3; - r[i / 8] += (interleaved[i + 6] & 0x20) >> 4; - r[i / 8] += (interleaved[i + 7] & 0x20) >> 5; - - s[i / 8] = (interleaved[i] & 0x10) << 3; - s[i / 8] += (interleaved[i + 1] & 0x10) << 2; - s[i / 8] += (interleaved[i + 2] & 0x10) << 1; - s[i / 8] += interleaved[i + 3] & 0x10; - s[i / 8] += (interleaved[i + 4] & 0x10) >> 1; - s[i / 8] += (interleaved[i + 5] & 0x10) >> 2; - s[i / 8] += (interleaved[i + 6] & 0x10) >> 3; - s[i / 8] += (interleaved[i + 7] & 0x10) >> 4; - - t[i / 8] = (interleaved[i] & 0x08) << 4; - t[i / 8] += (interleaved[i + 1] & 0x08) << 3; - t[i / 8] += (interleaved[i + 2] & 0x08) << 2; - t[i / 8] += (interleaved[i + 3] & 0x08) << 1; - t[i / 8] += interleaved[i + 4] & 0x08; - t[i / 8] += (interleaved[i + 5] & 0x08) >> 1; - t[i / 8] += (interleaved[i + 6] & 0x08) >> 2; - t[i / 8] += (interleaved[i + 7] & 0x08) >> 3; - - u[i / 8] = (interleaved[i] & 0x04) << 5; - u[i / 8] += (interleaved[i + 1] & 0x04) << 4; - u[i / 8] += (interleaved[i + 2] & 0x04) << 3; - u[i / 8] += (interleaved[i + 3] & 0x04) << 2; - u[i / 8] += (interleaved[i + 4] & 0x04) << 1; - u[i / 8] += interleaved[i + 5] & 0x04; - u[i / 8] += (interleaved[i + 6] & 0x04) >> 1; - u[i / 8] += (interleaved[i + 7] & 0x04) >> 2; - - v[i / 8] = (interleaved[i] & 0x02) << 6; - v[i / 8] += (interleaved[i + 1] & 0x02) << 5; - v[i / 8] += (interleaved[i + 2] & 0x02) << 4; - v[i / 8] += (interleaved[i + 3] & 0x02) << 3; - v[i / 8] += (interleaved[i + 4] & 0x02) << 2; - v[i / 8] += (interleaved[i + 5] & 0x02) << 1; - v[i / 8] += interleaved[i + 6] & 0x02; - v[i / 8] += (interleaved[i + 7] & 0x02) >> 1; - - w[i / 8] = (interleaved[i] & 0x01) << 7; - w[i / 8] += (interleaved[i + 1] & 0x01) << 6; - w[i / 8] += (interleaved[i + 2] & 0x01) << 5; - w[i / 8] += (interleaved[i + 3] & 0x01) << 4; - w[i / 8] += (interleaved[i + 4] & 0x01) << 3; - w[i / 8] += (interleaved[i + 5] & 0x01) << 2; - w[i / 8] += (interleaved[i + 6] & 0x01) << 1; - w[i / 8] += interleaved[i + 7] & 0x01; - } - - stopwatch.Stop(); - TimeSpan deinterleave = stopwatch.Elapsed; - - byte[] sequential = new byte[interleaved.Length]; - stopwatch.Restart(); - - int qStart = p.Length * 1; - int rStart = p.Length * 2; - int sStart = p.Length * 3; - int tStart = p.Length * 4; - int uStart = p.Length * 5; - int vStart = p.Length * 6; - int wStart = p.Length * 7; - - for(int i = 0; i < p.Length; i++) - { - sequential[i] = (byte)p[i]; - sequential[qStart + i] = (byte)q[i]; - sequential[rStart + i] = (byte)r[i]; - sequential[sStart + i] = (byte)s[i]; - sequential[tStart + i] = (byte)t[i]; - sequential[uStart + i] = (byte)u[i]; - sequential[vStart + i] = (byte)v[i]; - sequential[wStart + i] = (byte)w[i]; - } - - stopwatch.Stop(); - TimeSpan sequentialize = stopwatch.Elapsed; - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_ms_to_deinterleave_subchannel, - deinterleave.TotalMilliseconds); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_ms_to_sequentialize_subchannel, - sequentialize.TotalMilliseconds); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_ms_to_transform_subchannel, - deinterleave.TotalMilliseconds + sequentialize.TotalMilliseconds); - - return sequential; - } - - static byte[] ClauniaSubchannelUntransform(byte[] sequential) - { - if(sequential == null) return null; - - int[] p = new int[sequential.Length / 8]; - int[] q = new int[sequential.Length / 8]; - int[] r = new int[sequential.Length / 8]; - int[] s = new int[sequential.Length / 8]; - int[] t = new int[sequential.Length / 8]; - int[] u = new int[sequential.Length / 8]; - int[] v = new int[sequential.Length / 8]; - int[] w = new int[sequential.Length / 8]; - - int qStart = p.Length * 1; - int rStart = p.Length * 2; - int sStart = p.Length * 3; - int tStart = p.Length * 4; - int uStart = p.Length * 5; - int vStart = p.Length * 6; - int wStart = p.Length * 7; - - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - for(int i = 0; i < p.Length; i++) - { - p[i] = sequential[i]; - q[i] = sequential[qStart + i]; - r[i] = sequential[rStart + i]; - s[i] = sequential[sStart + i]; - t[i] = sequential[tStart + i]; - u[i] = sequential[uStart + i]; - v[i] = sequential[vStart + i]; - w[i] = sequential[wStart + i]; - } - - stopwatch.Stop(); - TimeSpan desequentialize = stopwatch.Elapsed; - - byte[] interleaved = new byte[sequential.Length]; - stopwatch.Restart(); - - for(int i = 0; i < interleaved.Length; i += 8) - { - interleaved[i] = (byte)((p[i / 8] & 0x80) == 0x80 ? 0x80 : 0); - interleaved[i + 1] += (byte)((p[i / 8] & 0x40) == 0x40 ? 0x80 : 0); - interleaved[i + 2] += (byte)((p[i / 8] & 0x20) == 0x20 ? 0x80 : 0); - interleaved[i + 3] += (byte)((p[i / 8] & 0x10) == 0x10 ? 0x80 : 0); - interleaved[i + 4] += (byte)((p[i / 8] & 0x08) == 0x08 ? 0x80 : 0); - interleaved[i + 5] += (byte)((p[i / 8] & 0x04) == 0x04 ? 0x80 : 0); - interleaved[i + 6] += (byte)((p[i / 8] & 0x02) == 0x02 ? 0x80 : 0); - interleaved[i + 7] += (byte)((p[i / 8] & 0x01) == 0x01 ? 0x80 : 0); - - interleaved[i] += (byte)((q[i / 8] & 0x80) == 0x80 ? 0x40 : 0); - interleaved[i + 1] += (byte)((q[i / 8] & 0x40) == 0x40 ? 0x40 : 0); - interleaved[i + 2] += (byte)((q[i / 8] & 0x20) == 0x20 ? 0x40 : 0); - interleaved[i + 3] += (byte)((q[i / 8] & 0x10) == 0x10 ? 0x40 : 0); - interleaved[i + 4] += (byte)((q[i / 8] & 0x08) == 0x08 ? 0x40 : 0); - interleaved[i + 5] += (byte)((q[i / 8] & 0x04) == 0x04 ? 0x40 : 0); - interleaved[i + 6] += (byte)((q[i / 8] & 0x02) == 0x02 ? 0x40 : 0); - interleaved[i + 7] += (byte)((q[i / 8] & 0x01) == 0x01 ? 0x40 : 0); - - interleaved[i] += (byte)((r[i / 8] & 0x80) == 0x80 ? 0x20 : 0); - interleaved[i + 1] += (byte)((r[i / 8] & 0x40) == 0x40 ? 0x20 : 0); - interleaved[i + 2] += (byte)((r[i / 8] & 0x20) == 0x20 ? 0x20 : 0); - interleaved[i + 3] += (byte)((r[i / 8] & 0x10) == 0x10 ? 0x20 : 0); - interleaved[i + 4] += (byte)((r[i / 8] & 0x08) == 0x08 ? 0x20 : 0); - interleaved[i + 5] += (byte)((r[i / 8] & 0x04) == 0x04 ? 0x20 : 0); - interleaved[i + 6] += (byte)((r[i / 8] & 0x02) == 0x02 ? 0x20 : 0); - interleaved[i + 7] += (byte)((r[i / 8] & 0x01) == 0x01 ? 0x20 : 0); - - interleaved[i] += (byte)((s[i / 8] & 0x80) == 0x80 ? 0x10 : 0); - interleaved[i + 1] += (byte)((s[i / 8] & 0x40) == 0x40 ? 0x10 : 0); - interleaved[i + 2] += (byte)((s[i / 8] & 0x20) == 0x20 ? 0x10 : 0); - interleaved[i + 3] += (byte)((s[i / 8] & 0x10) == 0x10 ? 0x10 : 0); - interleaved[i + 4] += (byte)((s[i / 8] & 0x08) == 0x08 ? 0x10 : 0); - interleaved[i + 5] += (byte)((s[i / 8] & 0x04) == 0x04 ? 0x10 : 0); - interleaved[i + 6] += (byte)((s[i / 8] & 0x02) == 0x02 ? 0x10 : 0); - interleaved[i + 7] += (byte)((s[i / 8] & 0x01) == 0x01 ? 0x10 : 0); - - interleaved[i] += (byte)((t[i / 8] & 0x80) == 0x80 ? 0x08 : 0); - interleaved[i + 1] += (byte)((t[i / 8] & 0x40) == 0x40 ? 0x08 : 0); - interleaved[i + 2] += (byte)((t[i / 8] & 0x20) == 0x20 ? 0x08 : 0); - interleaved[i + 3] += (byte)((t[i / 8] & 0x10) == 0x10 ? 0x08 : 0); - interleaved[i + 4] += (byte)((t[i / 8] & 0x08) == 0x08 ? 0x08 : 0); - interleaved[i + 5] += (byte)((t[i / 8] & 0x04) == 0x04 ? 0x08 : 0); - interleaved[i + 6] += (byte)((t[i / 8] & 0x02) == 0x02 ? 0x08 : 0); - interleaved[i + 7] += (byte)((t[i / 8] & 0x01) == 0x01 ? 0x08 : 0); - - interleaved[i] += (byte)((u[i / 8] & 0x80) == 0x80 ? 0x04 : 0); - interleaved[i + 1] += (byte)((u[i / 8] & 0x40) == 0x40 ? 0x04 : 0); - interleaved[i + 2] += (byte)((u[i / 8] & 0x20) == 0x20 ? 0x04 : 0); - interleaved[i + 3] += (byte)((u[i / 8] & 0x10) == 0x10 ? 0x04 : 0); - interleaved[i + 4] += (byte)((u[i / 8] & 0x08) == 0x08 ? 0x04 : 0); - interleaved[i + 5] += (byte)((u[i / 8] & 0x04) == 0x04 ? 0x04 : 0); - interleaved[i + 6] += (byte)((u[i / 8] & 0x02) == 0x02 ? 0x04 : 0); - interleaved[i + 7] += (byte)((u[i / 8] & 0x01) == 0x01 ? 0x04 : 0); - - interleaved[i] += (byte)((v[i / 8] & 0x80) == 0x80 ? 0x02 : 0); - interleaved[i + 1] += (byte)((v[i / 8] & 0x40) == 0x40 ? 0x02 : 0); - interleaved[i + 2] += (byte)((v[i / 8] & 0x20) == 0x20 ? 0x02 : 0); - interleaved[i + 3] += (byte)((v[i / 8] & 0x10) == 0x10 ? 0x02 : 0); - interleaved[i + 4] += (byte)((v[i / 8] & 0x08) == 0x08 ? 0x02 : 0); - interleaved[i + 5] += (byte)((v[i / 8] & 0x04) == 0x04 ? 0x02 : 0); - interleaved[i + 6] += (byte)((v[i / 8] & 0x02) == 0x02 ? 0x02 : 0); - interleaved[i + 7] += (byte)((v[i / 8] & 0x01) == 0x01 ? 0x02 : 0); - - interleaved[i] += (byte)((w[i / 8] & 0x80) == 0x80 ? 0x01 : 0); - interleaved[i + 1] += (byte)((w[i / 8] & 0x40) == 0x40 ? 0x01 : 0); - interleaved[i + 2] += (byte)((w[i / 8] & 0x20) == 0x20 ? 0x01 : 0); - interleaved[i + 3] += (byte)((w[i / 8] & 0x10) == 0x10 ? 0x01 : 0); - interleaved[i + 4] += (byte)((w[i / 8] & 0x08) == 0x08 ? 0x01 : 0); - interleaved[i + 5] += (byte)((w[i / 8] & 0x04) == 0x04 ? 0x01 : 0); - interleaved[i + 6] += (byte)((w[i / 8] & 0x02) == 0x02 ? 0x01 : 0); - interleaved[i + 7] += (byte)((w[i / 8] & 0x01) == 0x01 ? 0x01 : 0); - } - - stopwatch.Stop(); - TimeSpan interleave = stopwatch.Elapsed; - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_ms_to_desequentialize_subchannel, - desequentialize.TotalMilliseconds); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_ms_to_interleave_subchannel, - interleave.TotalMilliseconds); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_ms_to_untransform_subchannel, - interleave.TotalMilliseconds + desequentialize.TotalMilliseconds); - - return interleaved; - } -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Constants.cs b/Aaru.Images/AaruFormatOld/Constants.cs deleted file mode 100644 index 957069436..000000000 --- a/Aaru.Images/AaruFormatOld/Constants.cs +++ /dev/null @@ -1,67 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Constants.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Contains constants for Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ - /// Old magic identifier = "DICMFRMT". - const ulong DIC_MAGIC = 0x544D52464D434944; - /// Magic identifier = "AARUFRMT". - const ulong AARU_MAGIC = 0x544D524655524141; - /// - /// 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_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. - const int LZMA_PROPERTIES_LENGTH = 5; - /// Maximum number of entries for the DDT cache. - const int MAX_DDT_ENTRY_CACHE = 16000000; - /// How many samples are contained in a RedBook sector. - const int SAMPLES_PER_SECTOR = 588; - /// Maximum number of samples for a FLAC block. Bigger than 4608 gives no benefit. - const int MAX_FLAKE_BLOCK = 4608; - /// - /// Minimum number of samples for a FLAC block. does not support it to be - /// smaller than 256. - /// - const int MIN_FLAKE_BLOCK = 256; - /// This mask is to check for flags in CompactDisc suffix/prefix DDT - const uint CD_XFIX_MASK = 0xFF000000; - /// This mask is to check for position in CompactDisc suffix/prefix deduplicated block - const uint CD_DFIX_MASK = 0x00FFFFFF; -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Enums.cs b/Aaru.Images/AaruFormatOld/Enums.cs deleted file mode 100644 index 82333a998..000000000 --- a/Aaru.Images/AaruFormatOld/Enums.cs +++ /dev/null @@ -1,309 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Enums.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Contains enumerations for Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -// ReSharper disable UnusedMember.Local - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ -#region Nested type: BlockType - - /// List of known blocks types - enum BlockType : uint - { - /// Block containing data - DataBlock = 0x4B4C4244, - /// Block containing a deduplication table - DeDuplicationTable = 0x2A544444, - /// Block containing the index - Index = 0x58444E49, - /// Block containing the index - Index2 = 0x32584449, - /// Block containing logical geometry - GeometryBlock = 0x4D4F4547, - /// Block containing metadata - MetadataBlock = 0x4154454D, - /// Block containing optical disc tracks - TracksBlock = 0x534B5254, - /// Block containing CICM XML metadata - CicmBlock = 0x4D434943, - /// Block containing contents checksums - ChecksumBlock = 0x4D534B43, - /// TODO: Block containing data position measurements - DataPositionMeasurementBlock = 0x2A4D5044, - /// TODO: Block containing a snapshot index - SnapshotBlock = 0x50414E53, - /// TODO: Block containing how to locate the parent image - ParentBlock = 0x544E5250, - /// Block containing an array of hardware used to create the image - DumpHardwareBlock = 0x2A504D44, - /// Block containing list of files for a tape image - TapeFileBlock = 0x454C4654, - /// Block containing list of partitions for a tape image - TapePartitionBlock = 0x54425054, - /// Block containing list of indexes for Compact Disc tracks - CompactDiscIndexesBlock = 0x58494443, - /// Block containing JSON version of Aaru Metadata - AaruMetadataJsonBlock = 0x444D534A - } - -#endregion - -#region Nested type: CdFixFlags - - enum CdFixFlags : uint - { - NotDumped = 0x10000000, - Correct = 0x20000000, - Mode2Form1Ok = 0x30000000, - Mode2Form2Ok = 0x40000000, - Mode2Form2NoCrc = 0x50000000 - } - -#endregion - -#region Nested type: ChecksumAlgorithm - - enum ChecksumAlgorithm : byte - { - Invalid = 0, - Md5 = 1, - Sha1 = 2, - Sha256 = 3, - SpamSum = 4 - } - -#endregion - -#region Nested type: CompressionType - - /// List of known compression types - enum CompressionType : ushort - { - /// Not compressed - None = 0, - /// LZMA - Lzma = 1, - /// FLAC - Flac = 2, - /// LZMA in Claunia Subchannel Transform processed data - LzmaClauniaSubchannelTransform = 3 - } - -#endregion - -#region Nested type: DataType - - /// List of known data types - enum DataType : ushort - { - /// No data - NoData = 0, - /// User data - UserData = 1, - /// CompactDisc partial Table of Contents - CompactDiscPartialToc = 2, - /// CompactDisc session information - CompactDiscSessionInfo = 3, - /// CompactDisc Table of Contents - CompactDiscToc = 4, - /// CompactDisc Power Management Area - CompactDiscPma = 5, - /// CompactDisc Absolute Time In Pregroove - CompactDiscAtip = 6, - /// CompactDisc Lead-in's CD-Text - CompactDiscLeadInCdText = 7, - /// DVD Physical Format Information - DvdPfi = 8, - /// DVD Lead-in's Copyright Management Information - DvdLeadInCmi = 9, - /// DVD Disc Key - DvdDiscKey = 10, - /// DVD Burst Cutting Area - DvdBca = 11, - /// DVD DMI - DvdDmi = 12, - /// DVD Media Identifier - DvdMediaIdentifier = 13, - /// DVD Media Key Block - DvdMediaKeyBlock = 14, - /// DVD-RAM Disc Definition Structure - DvdRamDds = 15, - /// DVD-RAM Medium Status - DvdRamMediumStatus = 16, - /// DVD-RAM Spare Area Information - DvdRamSpareArea = 17, - /// DVD-R RMD - DvdRRmd = 18, - /// DVD-R Pre-recorded Information - DvdRPrerecordedInfo = 19, - /// DVD-R Media Identifier - DvdRMediaIdentifier = 20, - /// DVD-R Physical Format Information - DvdRPfi = 21, - /// DVD ADress In Pregroove - DvdAdip = 22, - /// HD DVD Copy Protection Information - HdDvdCpi = 23, - /// HD DVD Medium Status - HdDvdMediumStatus = 24, - /// DVD DL Layer Capacity - DvdDlLayerCapacity = 25, - /// DVD DL Middle Zone Address - DvdDlMiddleZoneAddress = 26, - /// DVD DL Jump Interval Size - DvdDlJumpIntervalSize = 27, - /// DVD DL Manual Layer Jump LBA - DvdDlManualLayerJumpLba = 28, - /// Bluray Disc Information - BlurayDi = 29, - /// Bluray Burst Cutting Area - BlurayBca = 30, - /// Bluray Disc Definition Structure - BlurayDds = 31, - /// Bluray Cartridge Status - BlurayCartridgeStatus = 32, - /// Bluray Spare Area Information - BluraySpareArea = 33, - /// AACS Volume Identifier - AacsVolumeIdentifier = 34, - /// AACS Serial Number - AacsSerialNumber = 35, - /// AACS Media Identifier - AacsMediaIdentifier = 36, - /// AACS Media Key Block - AacsMediaKeyBlock = 37, - /// AACS Data Keys - AacsDataKeys = 38, - /// AACS LBA Extents - AacsLbaExtents = 39, - /// CPRM Media Key Block - CprmMediaKeyBlock = 40, - /// Recognized Layers - HybridRecognizedLayers = 41, - /// MMC Write Protection - ScsiMmcWriteProtection = 42, - /// MMC Disc Information - ScsiMmcDiscInformation = 43, - /// MMC Track Resources Information - ScsiMmcTrackResourcesInformation = 44, - /// MMC POW Resources Information - ScsiMmcPowResourcesInformation = 45, - /// SCSI INQUIRY RESPONSE - ScsiInquiry = 46, - /// SCSI MODE PAGE 2Ah - ScsiModePage2A = 47, - /// ATA IDENTIFY response - AtaIdentify = 48, - /// ATAPI IDENTIFY response - AtapiIdentify = 49, - /// PCMCIA CIS - PcmciaCis = 50, - /// SecureDigital CID - SecureDigitalCid = 51, - /// SecureDigital CSD - SecureDigitalCsd = 52, - /// SecureDigital SCR - SecureDigitalScr = 53, - /// SecureDigital OCR - SecureDigitalOcr = 54, - /// MultiMediaCard CID - MultiMediaCardCid = 55, - /// MultiMediaCard CSD - MultiMediaCardCsd = 56, - /// MultiMediaCard OCR - MultiMediaCardOcr = 57, - /// MultiMediaCard Extended CSD - MultiMediaCardExtendedCsd = 58, - /// Xbox Security Sector - XboxSecuritySector = 59, - /// Floppy Lead-out - FloppyLeadOut = 60, - /// Dvd Disc Control Block - DvdDiscControlBlock = 61, - /// CompactDisc First track pregap - CompactDiscFirstTrackPregap = 62, - /// CompactDisc Lead-out - CompactDiscLeadOut = 63, - /// SCSI MODE SENSE (6) response - ScsiModeSense6 = 64, - /// SCSI MODE SENSE (10) response - ScsiModeSense10 = 65, - /// USB descriptors - UsbDescriptors = 66, - /// Xbox DMI - XboxDmi = 67, - /// Xbox Physical Format Information - XboxPfi = 68, - /// CompactDisc sector prefix (sync, header - CdSectorPrefix = 69, - /// CompactDisc sector suffix (edc, ecc p, ecc q) - CdSectorSuffix = 70, - /// CompactDisc subchannel - CdSectorSubchannel = 71, - /// Apple Profile (20 byte) tag - AppleProfileTag = 72, - /// Apple Sony (12 byte) tag - AppleSonyTag = 73, - /// Priam Data Tower (24 byte) tag - PriamDataTowerTag = 74, - /// CompactDisc Media Catalogue Number (as in Lead-in), 13 bytes, ASCII - CompactDiscMediaCatalogueNumber = 75, - /// CompactDisc sector prefix (sync, header), only incorrect stored - CdSectorPrefixCorrected = 76, - /// CompactDisc sector suffix (edc, ecc p, ecc q), only incorrect stored - CdSectorSuffixCorrected = 77, - /// CompactDisc MODE 2 subheader - CompactDiscMode2Subheader = 78, - /// CompactDisc Lead-in - CompactDiscLeadIn = 79, - /// Decrypted DVD Disc Key - DvdDiscKeyDecrypted = 80, - /// DVD Copyright Management Information (CPR_MAI) - DvdSectorCprMai = 81, - /// Decrypted DVD Title Key - DvdSectorTitleKeyDecrypted = 82, - /// DVD Identification Data (ID) - DvdSectorId = 83, - /// DVD ID Error Detection Code (IED) - DvdSectorIed = 84, - /// DVD Error Detection Code (EDC) - DvdSectorEdc = 85, - /// DVD Error Correction Code (ECC) Parity of Inner Code (PI) - DvdSectorEccPi = 86, - /// DVD Error Correction Code (ECC) Parity of Outer Code (PO) - DvdEccBlockPo = 87, - } - -#endregion -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Helpers.cs b/Aaru.Images/AaruFormatOld/Helpers.cs deleted file mode 100644 index a0f9e2999..000000000 --- a/Aaru.Images/AaruFormatOld/Helpers.cs +++ /dev/null @@ -1,532 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Helpers.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Contains helpers for Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -using System; -using Aaru.CommonTypes; -using Aaru.CommonTypes.Enums; -using Aaru.CommonTypes.Structs.Devices.ATA; -using Aaru.CommonTypes.Structs.Devices.SCSI; -using Aaru.Decoders.SecureDigital; -using Aaru.Helpers; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ - /// Checks for media tags that may contain metadata and sets it up if not already set - void SetMetadataFromTags() - { - // Search for SecureDigital CID - if(_mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] sdCid)) - { - CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(sdCid); - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveManufacturer)) - _imageInfo.DriveManufacturer = VendorString.Prettify(decoded.Manufacturer); - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveModel)) _imageInfo.DriveModel = decoded.ProductName; - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision)) - { - _imageInfo.DriveFirmwareRevision = - $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; - } - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber)) - _imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}"; - } - - // Search for MultiMediaCard CID - if(_mediaTags.TryGetValue(MediaTagType.MMC_CID, out byte[] mmcCid)) - { - Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(mmcCid); - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveManufacturer)) - _imageInfo.DriveManufacturer = Decoders.MMC.VendorString.Prettify(decoded.Manufacturer); - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveModel)) _imageInfo.DriveModel = decoded.ProductName; - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision)) - { - _imageInfo.DriveFirmwareRevision = - $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; - } - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber)) - _imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}"; - } - - // Search for SCSI INQUIRY - if(_mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] scsiInquiry)) - { - Inquiry? nullableInquiry = Inquiry.Decode(scsiInquiry); - - if(nullableInquiry.HasValue) - { - Inquiry inquiry = nullableInquiry.Value; - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveManufacturer)) - _imageInfo.DriveManufacturer = StringHandlers.CToString(inquiry.VendorIdentification)?.Trim(); - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveModel)) - _imageInfo.DriveModel = StringHandlers.CToString(inquiry.ProductIdentification)?.Trim(); - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision)) - _imageInfo.DriveFirmwareRevision = StringHandlers.CToString(inquiry.ProductRevisionLevel)?.Trim(); - } - } - - // Search for ATA or ATAPI IDENTIFY - if(!_mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) && - !_mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify)) - return; - - Identify.IdentifyDevice? nullableIdentify = CommonTypes.Structs.Devices.ATA.Identify.Decode(ataIdentify); - - if(!nullableIdentify.HasValue) return; - - Identify.IdentifyDevice identify = nullableIdentify.Value; - - string[] separated = identify.Model.Split(' '); - - if(separated.Length == 1) - { - if(string.IsNullOrWhiteSpace(_imageInfo.DriveModel)) - _imageInfo.DriveModel = separated[0]; - else - { - if(string.IsNullOrWhiteSpace(_imageInfo.DriveManufacturer)) _imageInfo.DriveManufacturer = separated[0]; - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveModel)) _imageInfo.DriveModel = separated[^1]; - } - } - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision)) - _imageInfo.DriveFirmwareRevision = identify.FirmwareRevision; - - if(string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber)) - _imageInfo.DriveSerialNumber = identify.SerialNumber; - } - - // Get the Aaru Metadata media type from Aaru media type - static MetadataMediaType GetMetadataMediaType(MediaType type) - { - return type switch - { - MediaType.CD - or MediaType.CDDA - or MediaType.CDG - or MediaType.CDEG - or MediaType.CDI - or MediaType.CDIREADY - or MediaType.CDROM - or MediaType.CDROMXA - or MediaType.CDPLUS - or MediaType.CDMO - or MediaType.CDR - or MediaType.CDRW - or MediaType.CDMRW - or MediaType.VCD - or MediaType.SVCD - or MediaType.PCD - or MediaType.SACD - or MediaType.DDCD - or MediaType.DDCDR - or MediaType.DDCDRW - or MediaType.DTSCD - or MediaType.CDMIDI - or MediaType.CDV - or MediaType.DVDROM - or MediaType.DVDR - or MediaType.DVDRW - or MediaType.DVDPR - or MediaType.DVDPRW - or MediaType.DVDPRWDL - or MediaType.DVDRDL - or MediaType.DVDPRDL - or MediaType.DVDRAM - or MediaType.DVDRWDL - or MediaType.DVDDownload - or MediaType.HDDVDROM - or MediaType.HDDVDRAM - or MediaType.HDDVDR - or MediaType.HDDVDRW - or MediaType.HDDVDRDL - or MediaType.HDDVDRWDL - or MediaType.BDROM - or MediaType.UHDBD - or MediaType.BDR - or MediaType.BDRE - or MediaType.BDRXL - or MediaType.BDREXL - or MediaType.EVD - or MediaType.FVD - or MediaType.HVD - or MediaType.CBHD - or MediaType.HDVMD - or MediaType.VCDHD - or MediaType.SVOD - or MediaType.FDDVD - or MediaType.LD - or MediaType.LDROM - or MediaType.CRVdisc - or MediaType.LDROM2 - or MediaType.LVROM - or MediaType.MegaLD - or MediaType.PS1CD - or MediaType.PS2CD - or MediaType.PS2DVD - or MediaType.PS3DVD - or MediaType.PS3BD - or MediaType.PS4BD - or MediaType.PS5BD - or MediaType.UMD - or MediaType.XGD - or MediaType.XGD2 - or MediaType.XGD3 - or MediaType.XGD4 - or MediaType.MEGACD - or MediaType.SATURNCD - or MediaType.GDROM - or MediaType.GDR - or MediaType.SuperCDROM2 - or MediaType.JaguarCD - or MediaType.ThreeDO - or MediaType.PCFX - or MediaType.NeoGeoCD - or MediaType.GOD - or MediaType.WOD - or MediaType.WUOD - or MediaType.CDTV - or MediaType.CD32 - or MediaType.Nuon - or MediaType.Playdia - or MediaType.Pippin - or MediaType.FMTOWNS - or MediaType.MilCD - or MediaType.VideoNow - or MediaType.VideoNowColor - or MediaType.VideoNowXp - or MediaType.CVD => MetadataMediaType.OpticalDisc, - _ => MetadataMediaType.BlockMedia - }; - } - - // Gets a DDT entry - ulong GetDdtEntry(ulong sectorAddress) - { - if(_inMemoryDdt) return _userDataDdt[sectorAddress]; - - if(_ddtEntryCache.TryGetValue(sectorAddress, out ulong entry)) return entry; - - long oldPosition = _imageStream.Position; - _imageStream.Position = _outMemoryDdtPosition + Marshal.SizeOf(); - _imageStream.Position += (long)(sectorAddress * sizeof(ulong)); - var temp = new byte[sizeof(ulong)]; - _imageStream.EnsureRead(temp, 0, sizeof(ulong)); - _imageStream.Position = oldPosition; - entry = BitConverter.ToUInt64(temp, 0); - - if(_ddtEntryCache.Count >= MAX_DDT_ENTRY_CACHE) _ddtEntryCache.Clear(); - - _ddtEntryCache.Add(sectorAddress, entry); - - return entry; - } - - // Sets a DDT entry - void SetDdtEntry(ulong sectorAddress, ulong pointer) - { - if(_inMemoryDdt) - { - if(IsTape) - _tapeDdt[sectorAddress] = pointer; - else - _userDataDdt[sectorAddress] = pointer; - - return; - } - - long oldPosition = _imageStream.Position; - _imageStream.Position = _outMemoryDdtPosition + Marshal.SizeOf(); - _imageStream.Position += (long)(sectorAddress * sizeof(ulong)); - _imageStream.Write(BitConverter.GetBytes(pointer), 0, sizeof(ulong)); - _imageStream.Position = oldPosition; - } - - // Converts between image data type and Aaru media tag type - static MediaTagType GetMediaTagTypeForDataType(DataType type) => type switch - { - DataType.CompactDiscPartialToc => MediaTagType - .CD_TOC, - DataType.CompactDiscSessionInfo => MediaTagType - .CD_SessionInfo, - DataType.CompactDiscToc => MediaTagType - .CD_FullTOC, - DataType.CompactDiscPma => MediaTagType.CD_PMA, - DataType.CompactDiscAtip => MediaTagType - .CD_ATIP, - DataType.CompactDiscLeadInCdText => - MediaTagType.CD_TEXT, - DataType.DvdPfi => MediaTagType.DVD_PFI, - DataType.DvdLeadInCmi => MediaTagType.DVD_CMI, - DataType.DvdDiscKey => - MediaTagType.DVD_DiscKey, - DataType.DvdBca => MediaTagType.DVD_BCA, - DataType.DvdDmi => MediaTagType.DVD_DMI, - DataType.DvdMediaIdentifier => MediaTagType - .DVD_MediaIdentifier, - DataType.DvdMediaKeyBlock => MediaTagType - .DVD_MKB, - DataType.DvdRamDds => MediaTagType.DVDRAM_DDS, - DataType.DvdRamMediumStatus => MediaTagType - .DVDRAM_MediumStatus, - DataType.DvdRamSpareArea => MediaTagType - .DVDRAM_SpareArea, - DataType.DvdRRmd => MediaTagType.DVDR_RMD, - DataType.DvdRPrerecordedInfo => MediaTagType - .DVDR_PreRecordedInfo, - DataType.DvdRMediaIdentifier => MediaTagType - .DVDR_MediaIdentifier, - DataType.DvdRPfi => MediaTagType.DVDR_PFI, - DataType.DvdAdip => MediaTagType.DVD_ADIP, - DataType.HdDvdCpi => MediaTagType.HDDVD_CPI, - DataType.HdDvdMediumStatus => MediaTagType - .HDDVD_MediumStatus, - DataType.DvdDlLayerCapacity => MediaTagType - .DVDDL_LayerCapacity, - DataType.DvdDlMiddleZoneAddress => MediaTagType - .DVDDL_MiddleZoneAddress, - DataType.DvdDlJumpIntervalSize => MediaTagType - .DVDDL_JumpIntervalSize, - DataType.DvdDlManualLayerJumpLba => - MediaTagType.DVDDL_ManualLayerJumpLBA, - DataType.BlurayDi => MediaTagType.BD_DI, - DataType.BlurayBca => MediaTagType.BD_BCA, - DataType.BlurayDds => MediaTagType.BD_DDS, - DataType.BlurayCartridgeStatus => MediaTagType - .BD_CartridgeStatus, - DataType.BluraySpareArea => MediaTagType - .BD_SpareArea, - DataType.AacsVolumeIdentifier => MediaTagType - .AACS_VolumeIdentifier, - DataType.AacsSerialNumber => MediaTagType - .AACS_SerialNumber, - DataType.AacsMediaIdentifier => MediaTagType - .AACS_MediaIdentifier, - DataType.AacsMediaKeyBlock => MediaTagType - .AACS_MKB, - DataType.AacsDataKeys => MediaTagType - .AACS_DataKeys, - DataType.AacsLbaExtents => MediaTagType - .AACS_LBAExtents, - DataType.CprmMediaKeyBlock => MediaTagType - .AACS_CPRM_MKB, - DataType.HybridRecognizedLayers => MediaTagType - .Hybrid_RecognizedLayers, - DataType.ScsiMmcWriteProtection => MediaTagType - .MMC_WriteProtection, - DataType.ScsiMmcDiscInformation => MediaTagType - .MMC_DiscInformation, - DataType.ScsiMmcTrackResourcesInformation => - MediaTagType.MMC_TrackResourcesInformation, - DataType.ScsiMmcPowResourcesInformation => - MediaTagType.MMC_POWResourcesInformation, - DataType.ScsiInquiry => MediaTagType - .SCSI_INQUIRY, - DataType.ScsiModePage2A => MediaTagType - .SCSI_MODEPAGE_2A, - DataType.AtaIdentify => MediaTagType - .ATA_IDENTIFY, - DataType.AtapiIdentify => MediaTagType - .ATAPI_IDENTIFY, - DataType.PcmciaCis => MediaTagType.PCMCIA_CIS, - DataType.SecureDigitalCid => MediaTagType - .SD_CID, - DataType.SecureDigitalCsd => MediaTagType - .SD_CSD, - DataType.SecureDigitalScr => MediaTagType - .SD_SCR, - DataType.SecureDigitalOcr => MediaTagType - .SD_OCR, - DataType.MultiMediaCardCid => MediaTagType - .MMC_CID, - DataType.MultiMediaCardCsd => MediaTagType - .MMC_CSD, - DataType.MultiMediaCardOcr => MediaTagType - .MMC_OCR, - DataType.MultiMediaCardExtendedCsd => - MediaTagType.MMC_ExtendedCSD, - DataType.XboxSecuritySector => MediaTagType - .Xbox_SecuritySector, - DataType.FloppyLeadOut => MediaTagType - .Floppy_LeadOut, - DataType.DvdDiscControlBlock => MediaTagType - .DCB, - DataType.CompactDiscFirstTrackPregap => - MediaTagType.CD_FirstTrackPregap, - DataType.CompactDiscLeadOut => MediaTagType - .CD_LeadOut, - DataType.ScsiModeSense6 => MediaTagType - .SCSI_MODESENSE_6, - DataType.ScsiModeSense10 => MediaTagType - .SCSI_MODESENSE_10, - DataType.UsbDescriptors => MediaTagType - .USB_Descriptors, - DataType.XboxDmi => MediaTagType.Xbox_DMI, - DataType.XboxPfi => MediaTagType.Xbox_PFI, - DataType.CompactDiscMediaCatalogueNumber => - MediaTagType.CD_MCN, - DataType.CompactDiscLeadIn => MediaTagType - .CD_LeadIn, - DataType.DvdDiscKeyDecrypted => MediaTagType - .DVD_DiscKey_Decrypted, - _ => throw new ArgumentOutOfRangeException() - }; - - // Converts between Aaru media tag type and image data type - static DataType GetDataTypeForMediaTag(MediaTagType tag) => tag switch - { - MediaTagType.CD_TOC => DataType - .CompactDiscPartialToc, - MediaTagType.CD_SessionInfo => DataType - .CompactDiscSessionInfo, - MediaTagType.CD_FullTOC => DataType.CompactDiscToc, - MediaTagType.CD_PMA => DataType.CompactDiscPma, - MediaTagType.CD_ATIP => DataType.CompactDiscAtip, - MediaTagType.CD_TEXT => DataType - .CompactDiscLeadInCdText, - MediaTagType.DVD_PFI => DataType.DvdPfi, - MediaTagType.DVD_CMI => DataType.DvdLeadInCmi, - MediaTagType.DVD_DiscKey => DataType.DvdDiscKey, - MediaTagType.DVD_BCA => DataType.DvdBca, - MediaTagType.DVD_DMI => DataType.DvdDmi, - MediaTagType.DVD_MediaIdentifier => DataType - .DvdMediaIdentifier, - MediaTagType.DVD_MKB => DataType.DvdMediaKeyBlock, - MediaTagType.DVDRAM_DDS => DataType.DvdRamDds, - MediaTagType.DVDRAM_MediumStatus => DataType - .DvdRamMediumStatus, - MediaTagType.DVDRAM_SpareArea => DataType - .DvdRamSpareArea, - MediaTagType.DVDR_RMD => DataType.DvdRRmd, - MediaTagType.DVDR_PreRecordedInfo => DataType - .DvdRPrerecordedInfo, - MediaTagType.DVDR_MediaIdentifier => DataType - .DvdRMediaIdentifier, - MediaTagType.DVDR_PFI => DataType.DvdRPfi, - MediaTagType.DVD_ADIP => DataType.DvdAdip, - MediaTagType.HDDVD_CPI => DataType.HdDvdCpi, - MediaTagType.HDDVD_MediumStatus => DataType - .HdDvdMediumStatus, - MediaTagType.DVDDL_LayerCapacity => DataType - .DvdDlLayerCapacity, - MediaTagType.DVDDL_MiddleZoneAddress => DataType - .DvdDlMiddleZoneAddress, - MediaTagType.DVDDL_JumpIntervalSize => DataType - .DvdDlJumpIntervalSize, - MediaTagType.DVDDL_ManualLayerJumpLBA => DataType - .DvdDlManualLayerJumpLba, - MediaTagType.BD_DI => DataType.BlurayDi, - MediaTagType.BD_BCA => DataType.BlurayBca, - MediaTagType.BD_DDS => DataType.BlurayDds, - MediaTagType.BD_CartridgeStatus => DataType - .BlurayCartridgeStatus, - MediaTagType.BD_SpareArea => DataType - .BluraySpareArea, - MediaTagType.AACS_VolumeIdentifier => DataType - .AacsVolumeIdentifier, - MediaTagType.AACS_SerialNumber => DataType - .AacsSerialNumber, - MediaTagType.AACS_MediaIdentifier => DataType - .AacsMediaIdentifier, - MediaTagType.AACS_MKB => DataType.AacsMediaKeyBlock, - MediaTagType.AACS_DataKeys => DataType.AacsDataKeys, - MediaTagType.AACS_LBAExtents => DataType - .AacsLbaExtents, - MediaTagType.AACS_CPRM_MKB => DataType - .CprmMediaKeyBlock, - MediaTagType.Hybrid_RecognizedLayers => DataType - .HybridRecognizedLayers, - MediaTagType.MMC_WriteProtection => DataType - .ScsiMmcWriteProtection, - MediaTagType.MMC_DiscInformation => DataType - .ScsiMmcDiscInformation, - MediaTagType.MMC_TrackResourcesInformation => - DataType.ScsiMmcTrackResourcesInformation, - MediaTagType.MMC_POWResourcesInformation => DataType - .ScsiMmcPowResourcesInformation, - MediaTagType.SCSI_INQUIRY => DataType.ScsiInquiry, - MediaTagType.SCSI_MODEPAGE_2A => DataType - .ScsiModePage2A, - MediaTagType.ATA_IDENTIFY => DataType.AtaIdentify, - MediaTagType.ATAPI_IDENTIFY => DataType - .AtapiIdentify, - MediaTagType.PCMCIA_CIS => DataType.PcmciaCis, - MediaTagType.SD_CID => DataType.SecureDigitalCid, - MediaTagType.SD_CSD => DataType.SecureDigitalCsd, - MediaTagType.SD_SCR => DataType.SecureDigitalScr, - MediaTagType.SD_OCR => DataType.SecureDigitalOcr, - MediaTagType.MMC_CID => DataType.MultiMediaCardCid, - MediaTagType.MMC_CSD => DataType.MultiMediaCardCsd, - MediaTagType.MMC_OCR => DataType.MultiMediaCardOcr, - MediaTagType.MMC_ExtendedCSD => DataType - .MultiMediaCardExtendedCsd, - MediaTagType.Xbox_SecuritySector => DataType - .XboxSecuritySector, - MediaTagType.Floppy_LeadOut => DataType - .FloppyLeadOut, - MediaTagType.DCB => DataType.DvdDiscControlBlock, - MediaTagType.CD_FirstTrackPregap => DataType - .CompactDiscFirstTrackPregap, - MediaTagType.CD_LeadOut => DataType - .CompactDiscLeadOut, - MediaTagType.SCSI_MODESENSE_6 => DataType - .ScsiModeSense6, - MediaTagType.SCSI_MODESENSE_10 => DataType - .ScsiModeSense10, - MediaTagType.USB_Descriptors => DataType - .UsbDescriptors, - MediaTagType.Xbox_DMI => DataType.XboxDmi, - MediaTagType.Xbox_PFI => DataType.XboxPfi, - MediaTagType.CD_MCN => DataType - .CompactDiscMediaCatalogueNumber, - MediaTagType.CD_LeadIn => - DataType.CompactDiscLeadIn, - MediaTagType.DVD_DiscKey_Decrypted => DataType - .DvdDiscKeyDecrypted, - _ => throw new - ArgumentOutOfRangeException(nameof(tag), - tag, - null) - }; -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Identify.cs b/Aaru.Images/AaruFormatOld/Identify.cs deleted file mode 100644 index 5d7692606..000000000 --- a/Aaru.Images/AaruFormatOld/Identify.cs +++ /dev/null @@ -1,58 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Identify.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Identifies Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -using Aaru.CommonTypes.Interfaces; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ -#region IWritableOpticalImage Members - - /// - public bool Identify(IFilter imageFilter) => false; - - /* - _imageStream = imageFilter.GetDataForkStream(); - _imageStream.Seek(0, SeekOrigin.Begin); - - if(_imageStream.Length < Marshal.SizeOf()) return false; - - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - _header = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - return _header.identifier is DIC_MAGIC or AARU_MAGIC && _header.imageMajorVersion <= AARUFMT_VERSION; - */ - -#endregion -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Properties.cs b/Aaru.Images/AaruFormatOld/Properties.cs deleted file mode 100644 index a1afc092a..000000000 --- a/Aaru.Images/AaruFormatOld/Properties.cs +++ /dev/null @@ -1,140 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Properties.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Contains properties for Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using Aaru.CommonTypes; -using Aaru.CommonTypes.AaruMetadata; -using Aaru.CommonTypes.Enums; -using Aaru.CommonTypes.Structs; -using Partition = Aaru.CommonTypes.Partition; -using Track = Aaru.CommonTypes.Structs.Track; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ -#region IWritableOpticalImage Members - - /// - public OpticalImageCapabilities OpticalCapabilities => OpticalImageCapabilities.CanStoreAudioTracks | - OpticalImageCapabilities.CanStoreDataTracks | - OpticalImageCapabilities.CanStorePregaps | - OpticalImageCapabilities.CanStoreSubchannelRw | - OpticalImageCapabilities.CanStoreSessions | - OpticalImageCapabilities.CanStoreIsrc | - OpticalImageCapabilities.CanStoreCdText | - OpticalImageCapabilities.CanStoreMcn | - OpticalImageCapabilities.CanStoreRawData | - OpticalImageCapabilities.CanStoreCookedData | - OpticalImageCapabilities.CanStoreMultipleTracks | - OpticalImageCapabilities.CanStoreNotCdSessions | - OpticalImageCapabilities.CanStoreNotCdTracks | - OpticalImageCapabilities.CanStoreIndexes | - OpticalImageCapabilities.CanStoreHiddenTracks; - - /// - - // ReSharper disable once ConvertToAutoProperty - public ImageInfo Info => _imageInfo; - - /// - public string Name => "Aaru (old)"; - - /// - public Guid Id => new("49360069-1784-4A2F-B723-0C844D610B0A"); - - /// - public string Format => "Aaru (old)"; - - /// - public string Author => Authors.NataliaPortillo; - - /// - public List Partitions { get; private set; } - - /// - public List Tracks { get; private set; } - - /// - public List Sessions { get; private set; } - - /// - public List DumpHardware { get; private set; } - - /// - public Metadata AaruMetadata { get; private set; } - - /// - public IEnumerable SupportedMediaTags => Enum.GetValues(typeof(MediaTagType)).Cast(); - - /// - public IEnumerable SupportedSectorTags => - Enum.GetValues(typeof(SectorTagType)).Cast(); - - /// - public IEnumerable SupportedMediaTypes => Enum.GetValues(typeof(MediaType)).Cast(); - - /// - public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions => new[] - { - ("sectors_per_block", typeof(uint), - Localization.How_many_sectors_to_store_per_block_will_be_rounded_to_next_power_of_two, 4096U), - ("dictionary", typeof(uint), Localization.Size_in_bytes_of_the_LZMA_dictionary, (uint)(1 << 25)), - ("max_ddt_size", typeof(uint), - Localization.Maximum_size_in_mebibytes_for_in_memory_DDT_If_image_needs_a_bigger_one_it_will_be_on_disk, 256U), - ("md5", typeof(bool), Localization.Calculate_and_store_MD5_of_image_user_data, false), - ("sha1", typeof(bool), Localization.Calculate_and_store_SHA1_of_image_user_data, false), - ("sha256", typeof(bool), Localization.Calculate_and_store_SHA256_of_image_user_data, false), - ("spamsum", typeof(bool), Localization.Calculate_and_store_SpamSum_of_image_user_data, false), - ("deduplicate", typeof(bool), - Localization.Store_only_unique_sectors_This_consumes_more_memory_and_is_slower_but_its_enabled_by_default, - true), - ("compress", typeof(bool), Localization.Compress_user_data_blocks_Other_blocks_will_always_be_compressed, - (object)true) - }; - - /// - public IEnumerable KnownExtensions => new[] - { - ".dicf", ".aaru", ".aaruformat", ".aaruf", ".aif" - }; - - /// - public bool IsWriting { get; private set; } - - /// - public string ErrorMessage { get; private set; } - -#endregion -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Read.cs b/Aaru.Images/AaruFormatOld/Read.cs deleted file mode 100644 index 8b486ff7c..000000000 --- a/Aaru.Images/AaruFormatOld/Read.cs +++ /dev/null @@ -1,2556 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Read.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Reads Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// Copyright © 2020-2025 Rebecca Wallander -// ****************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.Json; -using System.Xml; -using System.Xml.Serialization; -using Aaru.Checksums; -using Aaru.CommonTypes; -using Aaru.CommonTypes.AaruMetadata; -using Aaru.CommonTypes.Enums; -using Aaru.CommonTypes.Interfaces; -using Aaru.Compression; -using Aaru.Decoders.CD; -using Aaru.Helpers; -using Aaru.Logging; -using Humanizer; -using Schemas; -using Marshal = Aaru.Helpers.Marshal; -using Partition = Aaru.CommonTypes.Partition; -using Session = Aaru.CommonTypes.Structs.Session; -using TapeFile = Aaru.CommonTypes.Structs.TapeFile; -using TapePartition = Aaru.CommonTypes.Structs.TapePartition; -using Track = Aaru.CommonTypes.Structs.Track; -using TrackType = Aaru.CommonTypes.Enums.TrackType; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ -#region IWritableOpticalImage Members - - /// - public ErrorNumber Open(IFilter imageFilter) - { - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - _imageStream = imageFilter.GetDataForkStream(); - _imageStream.Seek(0, SeekOrigin.Begin); - - if(_imageStream.Length < Marshal.SizeOf()) return ErrorNumber.InvalidArgument; - - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - _header = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - if(_header.imageMajorVersion > AARUFMT_VERSION) - { - AaruLogging.Error(string.Format(Localization.Image_version_0_not_recognized, _header.imageMajorVersion)); - - return ErrorNumber.NotSupported; - } - - _imageInfo.Application = _header.application; - _imageInfo.ApplicationVersion = $"{_header.applicationMajorVersion}.{_header.applicationMinorVersion}"; - _imageInfo.Version = $"{_header.imageMajorVersion}.{_header.imageMinorVersion}"; - _imageInfo.MediaType = _header.mediaType; - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - // Read the index header - _imageStream.Position = (long)_header.indexOffset; - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - IndexHeader idxHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(idxHeader.identifier != BlockType.Index && idxHeader.identifier != BlockType.Index2) - { - AaruLogging.Error(Localization.Index_not_found); - - return ErrorNumber.InvalidArgument; - } - - if(idxHeader.identifier == BlockType.Index2) - { - _imageStream.Position = (long)_header.indexOffset; - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - IndexHeader2 idxHeader2 = Marshal.SpanToStructureLittleEndian(_structureBytes); - - AaruLogging.Debug(MODULE_NAME, - Localization.Index_at_0_contains_1_entries, - _header.indexOffset, - idxHeader2.entries); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - // Fill in-memory index - _index = []; - - for(ulong i = 0; i < idxHeader2.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - IndexEntry entry = Marshal.SpanToStructureLittleEndian(_structureBytes); - - AaruLogging.Debug(MODULE_NAME, - Localization.Block_type_0_with_data_type_1_is_indexed_to_be_at_2, - entry.blockType, - entry.dataType, - entry.offset); - - _index.Add(entry); - } - } - else - { - AaruLogging.Debug(MODULE_NAME, - Localization.Index_at_0_contains_1_entries, - _header.indexOffset, - idxHeader.entries); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - // Fill in-memory index - _index = []; - - for(ushort i = 0; i < idxHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - IndexEntry entry = Marshal.SpanToStructureLittleEndian(_structureBytes); - - AaruLogging.Debug(MODULE_NAME, - Localization.Block_type_0_with_data_type_1_is_indexed_to_be_at_2, - entry.blockType, - entry.dataType, - entry.offset); - - _index.Add(entry); - } - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - _imageInfo.ImageSize = 0; - - bool foundUserDataDdt = false; - _mediaTags = new Dictionary(); - List compactDiscIndexes = null; - - foreach(IndexEntry entry in _index) - { - _imageStream.Position = (long)entry.offset; - - switch(entry.blockType) - { - case BlockType.DataBlock: - // NOP block, skip - if(entry.dataType == DataType.NoData) break; - - _imageStream.Position = (long)entry.offset; - - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - BlockHeader blockHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - _imageInfo.ImageSize += blockHeader.cmpLength; - - // Unused, skip - if(entry.dataType == DataType.UserData) - { - if(blockHeader.sectorSize > _imageInfo.SectorSize) - _imageInfo.SectorSize = blockHeader.sectorSize; - - break; - } - - if(blockHeader.identifier != entry.blockType) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_identifier_for_data_block_at_position_0, - entry.offset); - - break; - } - - if(blockHeader.type != entry.dataType) - { - AaruLogging.Debug(MODULE_NAME, - Localization - .Expected_block_with_data_type_0_at_position_1_but_found_data_type_2, - entry.dataType, - entry.offset, - blockHeader.type); - - break; - } - - byte[] data; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_data_block_type_0_at_position_1, - entry.dataType, - entry.offset); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - // Decompress media tag - if(blockHeader.compression is CompressionType.Lzma - or CompressionType.LzmaClauniaSubchannelTransform) - { - if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform && - entry.dataType != DataType.CdSectorSubchannel) - { - AaruLogging.Debug(MODULE_NAME, - Localization - .Invalid_compression_type_0_for_block_with_data_type_1_continuing, - blockHeader.compression, - entry.dataType); - - break; - } - - var decompressStopwatch = new Stopwatch(); - decompressStopwatch.Start(); - byte[] compressedTag = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.EnsureRead(compressedTag, 0, compressedTag.Length); - data = new byte[blockHeader.length]; - int decompressedLength = LZMA.DecodeBuffer(compressedTag, data, lzmaProperties); - - if(decompressedLength != blockHeader.length) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Error_decompressing_block_should_be_0_bytes_but_got_1_bytes, - blockHeader.length, - decompressedLength); - - return ErrorNumber.InOutError; - } - - if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform) - data = ClauniaSubchannelUntransform(data); - - decompressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_decompress_block, - decompressStopwatch.Elapsed.TotalSeconds); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - } - else if(blockHeader.compression == CompressionType.None) - { - data = new byte[blockHeader.length]; - _imageStream.EnsureRead(data, 0, (int)blockHeader.length); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - } - else - { - AaruLogging.Debug(MODULE_NAME, - Localization.Found_unknown_compression_type_0_continuing, - (ushort)blockHeader.compression); - - break; - } - - // Check CRC, if not correct, skip it - Crc64Context.Data(data, out byte[] blockCrc); - - if(BitConverter.ToUInt64(blockCrc, 0) != blockHeader.crc64 && blockHeader.crc64 != 0) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_CRC_found_0_X16_found_expected_1_X16_continuing, - BitConverter.ToUInt64(blockCrc, 0), - blockHeader.crc64); - - break; - } - - // Check if it's not a media tag, but a sector tag, and fill the appropriate table then - switch(entry.dataType) - { - case DataType.CdSectorPrefix: - case DataType.CdSectorPrefixCorrected: - if(entry.dataType == DataType.CdSectorPrefixCorrected) - { - _sectorPrefixMs ??= new MemoryStream(); - _sectorPrefixMs.Write(data, 0, data.Length); - } - else - _sectorPrefix = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.CdSectorSuffix: - case DataType.CdSectorSuffixCorrected: - if(entry.dataType == DataType.CdSectorSuffixCorrected) - { - _sectorSuffixMs ??= new MemoryStream(); - _sectorSuffixMs.Write(data, 0, data.Length); - } - else - _sectorSuffix = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.CdSectorSubchannel: - _sectorSubchannel = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.AppleProfileTag: - case DataType.AppleSonyTag: - case DataType.PriamDataTowerTag: - _sectorSubchannel = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.CompactDiscMode2Subheader: - _mode2Subheaders = data; - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorCprMai: - _sectorCprMai = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorCmi)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorCmi); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorTitleKey)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorTitleKey); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorId: - _sectorId = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorInformation)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorInformation); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorNumber)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorNumber); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorIed: - _sectorIed = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorIed)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorIed); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorEdc: - _sectorEdc = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorEdc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorEdc); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorTitleKeyDecrypted: - _sectorDecryptedTitleKey = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdTitleKeyDecrypted)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdTitleKeyDecrypted); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - default: - MediaTagType mediaTagType = GetMediaTagTypeForDataType(blockHeader.type); - - if(_mediaTags.ContainsKey(mediaTagType)) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Media_tag_type_0_duplicated_removing_previous_entry, - mediaTagType); - - _mediaTags.Remove(mediaTagType); - } - - _mediaTags.Add(mediaTagType, data); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - } - - break; - case BlockType.DeDuplicationTable: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - DdtHeader ddtHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - _imageInfo.ImageSize += ddtHeader.cmpLength; - - if(ddtHeader.identifier != BlockType.DeDuplicationTable) break; - - switch(entry.dataType) - { - case DataType.UserData: - _imageInfo.Sectors = ddtHeader.entries; - _shift = ddtHeader.shift; - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - // Check for DDT compression - switch(ddtHeader.compression) - { - case CompressionType.Lzma: - AaruLogging.Debug(MODULE_NAME, Localization.Decompressing_DDT); - var ddtStopwatch = new Stopwatch(); - ddtStopwatch.Start(); - byte[] compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.EnsureRead(compressedDdt, 0, compressedDdt.Length); - byte[] decompressedDdt = new byte[ddtHeader.length]; - - ulong decompressedLength = - (ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties); - - if(decompressedLength != ddtHeader.length) - { - AaruLogging.Debug(MODULE_NAME, - Localization - .Error_decompressing_DDT_should_be_0_bytes_but_got_1_bytes, - ddtHeader.length, - decompressedLength); - - return ErrorNumber.InOutError; - } - - _userDataDdt = MemoryMarshal.Cast(decompressedDdt).ToArray(); - ddtStopwatch.Stop(); - _inMemoryDdt = true; - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_decompress_DDT, - ddtStopwatch.Elapsed.TotalSeconds); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case CompressionType.None: - _inMemoryDdt = false; - _outMemoryDdtPosition = (long)entry.offset; - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - default: - AaruLogging.Error(string.Format(Localization - .Found_unsupported_compression_algorithm_0, - (ushort)ddtHeader.compression)); - - return ErrorNumber.NotSupported; - } - - foundUserDataDdt = true; - - break; - case DataType.CdSectorPrefixCorrected: - case DataType.CdSectorSuffixCorrected: - { - byte[] decompressedDdt = new byte[ddtHeader.length]; - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - // Check for DDT compression - switch(ddtHeader.compression) - { - case CompressionType.Lzma: - AaruLogging.Debug(MODULE_NAME, Localization.Decompressing_DDT); - var ddtStopwatch = new Stopwatch(); - ddtStopwatch.Start(); - byte[] compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.EnsureRead(compressedDdt, 0, compressedDdt.Length); - - ulong decompressedLength = - (ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties); - - ddtStopwatch.Stop(); - - if(decompressedLength != ddtHeader.length) - { - AaruLogging.Debug(MODULE_NAME, - Localization - .Error_decompressing_DDT_should_be_0_bytes_but_got_1_bytes, - ddtHeader.length, - decompressedLength); - - return ErrorNumber.InOutError; - } - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_decompress_DDT, - ddtStopwatch.Elapsed.TotalSeconds); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case CompressionType.None: - _imageStream.EnsureRead(decompressedDdt, 0, decompressedDdt.Length); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - default: - AaruLogging.Error(string.Format(Localization - .Found_unsupported_compression_algorithm_0, - (ushort)ddtHeader.compression)); - - return ErrorNumber.NotSupported; - } - - uint[] cdDdt = MemoryMarshal.Cast(decompressedDdt).ToArray(); - - switch(entry.dataType) - { - case DataType.CdSectorPrefixCorrected: - _sectorPrefixDdt = cdDdt; - _sectorPrefixMs = new MemoryStream(); - - break; - case DataType.CdSectorSuffixCorrected: - _sectorSuffixDdt = cdDdt; - _sectorSuffixMs = new MemoryStream(); - - break; - } - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - } - } - - break; - - // Logical geometry block. It doesn't have a CRC coz, well, it's not so important - case BlockType.GeometryBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - _geometryBlock = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(_geometryBlock.identifier == BlockType.GeometryBlock) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Geometry_set_to_0_cylinders_1_heads_2_sectors_per_track, - _geometryBlock.cylinders, - _geometryBlock.heads, - _geometryBlock.sectorsPerTrack); - - _imageInfo.Cylinders = _geometryBlock.cylinders; - _imageInfo.Heads = _geometryBlock.heads; - _imageInfo.SectorsPerTrack = _geometryBlock.sectorsPerTrack; - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - } - - break; - - // Metadata block - case BlockType.MetadataBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - MetadataBlock metadataBlock = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(metadataBlock.identifier != entry.blockType) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_identifier_for_data_block_at_position_0, - entry.offset); - - break; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Found_metadata_block_at_position_0, entry.offset); - - byte[] metadata = new byte[metadataBlock.blockSize]; - _imageStream.Position = (long)entry.offset; - _imageStream.EnsureRead(metadata, 0, metadata.Length); - - if(metadataBlock is { mediaSequence: > 0, lastMediaSequence: > 0 }) - { - _imageInfo.MediaSequence = metadataBlock.mediaSequence; - _imageInfo.LastMediaSequence = metadataBlock.lastMediaSequence; - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_sequence_as_0_of_1, - _imageInfo.MediaSequence, - _imageInfo.LastMediaSequence); - } - - if(metadataBlock.creatorLength > 0 && - metadataBlock.creatorLength + metadataBlock.creatorOffset <= metadata.Length) - { - _imageInfo.Creator = Encoding.Unicode.GetString(metadata, - (int)metadataBlock.creatorOffset, - (int)(metadataBlock.creatorLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_creator_0, _imageInfo.Creator); - } - - if(metadataBlock.commentsOffset > 0 && - metadataBlock.commentsLength + metadataBlock.commentsOffset <= metadata.Length) - { - _imageInfo.Comments = Encoding.Unicode.GetString(metadata, - (int)metadataBlock.commentsOffset, - (int)(metadataBlock.commentsLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_comments_0, _imageInfo.Comments); - } - - if(metadataBlock.mediaTitleOffset > 0 && - metadataBlock.mediaTitleLength + metadataBlock.mediaTitleOffset <= metadata.Length) - { - _imageInfo.MediaTitle = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaTitleOffset, - (int)(metadataBlock.mediaTitleLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_media_title_0, _imageInfo.MediaTitle); - } - - if(metadataBlock.mediaManufacturerOffset > 0 && - metadataBlock.mediaManufacturerLength + metadataBlock.mediaManufacturerOffset <= metadata.Length) - { - _imageInfo.MediaManufacturer = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaManufacturerOffset, - (int)(metadataBlock.mediaManufacturerLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_manufacturer_0, - _imageInfo.MediaManufacturer); - } - - if(metadataBlock.mediaModelOffset > 0 && - metadataBlock.mediaModelLength + metadataBlock.mediaModelOffset <= metadata.Length) - { - _imageInfo.MediaModel = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaModelOffset, - (int)(metadataBlock.mediaModelLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_media_model_0, _imageInfo.MediaModel); - } - - if(metadataBlock.mediaSerialNumberOffset > 0 && - metadataBlock.mediaSerialNumberLength + metadataBlock.mediaSerialNumberOffset <= metadata.Length) - { - _imageInfo.MediaSerialNumber = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaSerialNumberOffset, - (int)(metadataBlock.mediaSerialNumberLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_serial_number_0, - _imageInfo.MediaSerialNumber); - } - - if(metadataBlock.mediaBarcodeOffset > 0 && - metadataBlock.mediaBarcodeLength + metadataBlock.mediaBarcodeOffset <= metadata.Length) - { - _imageInfo.MediaBarcode = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaBarcodeOffset, - (int)(metadataBlock.mediaBarcodeLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_media_barcode_0, _imageInfo.MediaBarcode); - } - - if(metadataBlock.mediaPartNumberOffset > 0 && - metadataBlock.mediaPartNumberLength + metadataBlock.mediaPartNumberOffset <= metadata.Length) - { - _imageInfo.MediaPartNumber = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaPartNumberOffset, - (int)(metadataBlock.mediaPartNumberLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_part_number_0, - _imageInfo.MediaPartNumber); - } - - if(metadataBlock.driveManufacturerOffset > 0 && - metadataBlock.driveManufacturerLength + metadataBlock.driveManufacturerOffset <= metadata.Length) - { - _imageInfo.DriveManufacturer = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.driveManufacturerOffset, - (int)(metadataBlock.driveManufacturerLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_drive_manufacturer_0, - _imageInfo.DriveManufacturer); - } - - if(metadataBlock.driveModelOffset > 0 && - metadataBlock.driveModelLength + metadataBlock.driveModelOffset <= metadata.Length) - { - _imageInfo.DriveModel = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.driveModelOffset, - (int)(metadataBlock.driveModelLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_drive_model_0, _imageInfo.DriveModel); - } - - if(metadataBlock.driveSerialNumberOffset > 0 && - metadataBlock.driveSerialNumberLength + metadataBlock.driveSerialNumberOffset <= metadata.Length) - { - _imageInfo.DriveSerialNumber = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.driveSerialNumberOffset, - (int)(metadataBlock.driveSerialNumberLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_drive_serial_number_0, - _imageInfo.DriveSerialNumber); - } - - if(metadataBlock.driveFirmwareRevisionOffset > 0 && - metadataBlock.driveFirmwareRevisionLength + metadataBlock.driveFirmwareRevisionOffset <= - metadata.Length) - { - _imageInfo.DriveFirmwareRevision = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.driveFirmwareRevisionOffset, - (int)(metadataBlock.driveFirmwareRevisionLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_drive_firmware_revision_0, - _imageInfo.DriveFirmwareRevision); - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - - // Optical disc tracks block - case BlockType.TracksBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - TracksHeader tracksHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(tracksHeader.identifier != BlockType.TracksBlock) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_identifier_for_tracks_block_at_position_0, - entry.offset); - - break; - } - - _structureBytes = new byte[Marshal.SizeOf() * tracksHeader.entries]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] trksCrc); - - if(BitConverter.ToUInt64(trksCrc, 0) != tracksHeader.crc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_CRC_found_0_X16_found_expected_1_X16_continuing, - BitConverter.ToUInt64(trksCrc, 0), - tracksHeader.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - Tracks = []; - _trackFlags = new Dictionary(); - _trackIsrcs = new Dictionary(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_0_tracks_at_position_1, - tracksHeader.entries, - entry.offset); - - for(ushort i = 0; i < tracksHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - TrackEntry trackEntry = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - Tracks.Add(new Track - { - Sequence = trackEntry.sequence, - Type = trackEntry.type, - StartSector = (ulong)trackEntry.start, - EndSector = (ulong)trackEntry.end, - Pregap = (ulong)trackEntry.pregap, - Session = trackEntry.session, - File = imageFilter.Filename, - FileType = "BINARY", - Filter = imageFilter - }); - - if(trackEntry.type == TrackType.Data) continue; - - _trackFlags.Add(trackEntry.sequence, trackEntry.flags); - - if(!string.IsNullOrEmpty(trackEntry.isrc)) - _trackIsrcs.Add(trackEntry.sequence, trackEntry.isrc); - } - - if(_trackFlags.Count > 0 && !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackFlags)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); - - if(_trackIsrcs.Count > 0 && !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc); - - _imageInfo.HasPartitions = true; - _imageInfo.HasSessions = true; - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - - // CICM XML metadata block - case BlockType.CicmBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - CicmMetadataBlock cicmBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(cicmBlock.identifier != BlockType.CicmBlock) break; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_CICM_XML_metadata_block_at_position_0, - entry.offset); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - byte[] cicmBytes = new byte[cicmBlock.length]; - _imageStream.EnsureRead(cicmBytes, 0, cicmBytes.Length); - var cicmMs = new MemoryStream(cicmBytes); - - // The converter to AaruMetadata basically overcomes this (should?) -#pragma warning disable IL2026 - var cicmXs = new XmlSerializer(typeof(CICMMetadataType)); -#pragma warning restore IL2026 - - try - { - var sr = new StreamReader(cicmMs); - - // The converter to AaruMetadata basically overcomes this (should?) -#pragma warning disable IL2026 - AaruMetadata = (CICMMetadataType)cicmXs.Deserialize(sr); -#pragma warning restore IL2026 - sr.Close(); - } - catch(XmlException ex) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Exception_0_processing_CICM_XML_metadata_block, - ex.Message); - - AaruLogging.Exception(ex, - Localization.Exception_0_processing_CICM_XML_metadata_block, - ex.Message); - - AaruMetadata = null; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - - // Aaru Metadata JSON block - case BlockType.AaruMetadataJsonBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - AaruMetadataJsonBlock aaruMetadataBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(aaruMetadataBlock.identifier != BlockType.AaruMetadataJsonBlock) break; - - AaruLogging.Debug(MODULE_NAME, Localization.Found_Aaru_Metadata_block_at_position_0, entry.offset); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - byte[] jsonBytes = new byte[aaruMetadataBlock.length]; - _imageStream.EnsureRead(jsonBytes, 0, jsonBytes.Length); - - try - { - AaruMetadata = - (JsonSerializer.Deserialize(jsonBytes, typeof(MetadataJson), MetadataJsonContext.Default) as - MetadataJson)?.AaruMetadata; - } - catch(JsonException ex) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Exception_0_processing_Aaru_Metadata_block, - ex.Message); - - AaruLogging.Exception(ex, Localization.Exception_0_processing_Aaru_Metadata_block, ex.Message); - - AaruMetadata = null; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - - // Dump hardware block - case BlockType.DumpHardwareBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - DumpHardwareHeader dumpBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(dumpBlock.identifier != BlockType.DumpHardwareBlock) break; - - AaruLogging.Debug(MODULE_NAME, Localization.Found_dump_hardware_block_at_position_0, entry.offset); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - _structureBytes = new byte[dumpBlock.length]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] dumpCrc); - - if(BitConverter.ToUInt64(dumpCrc, 0) != dumpBlock.crc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_CRC_found_0_X16_found_expected_1_X16_continuing, - BitConverter.ToUInt64(dumpCrc, 0), - dumpBlock.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - DumpHardware = []; - - for(ushort i = 0; i < dumpBlock.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - DumpHardwareEntry dumpEntry = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - var dump = new DumpHardware - { - Software = new Software(), - Extents = [] - }; - - byte[] tmp; - - if(dumpEntry.manufacturerLength > 0) - { - tmp = new byte[dumpEntry.manufacturerLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Manufacturer = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.modelLength > 0) - { - tmp = new byte[dumpEntry.modelLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Model = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.revisionLength > 0) - { - tmp = new byte[dumpEntry.revisionLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Revision = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.firmwareLength > 0) - { - tmp = new byte[dumpEntry.firmwareLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Firmware = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.serialLength > 0) - { - tmp = new byte[dumpEntry.serialLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Serial = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareNameLength > 0) - { - tmp = new byte[dumpEntry.softwareNameLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Software.Name = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareVersionLength > 0) - { - tmp = new byte[dumpEntry.softwareVersionLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Software.Version = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareOperatingSystemLength > 0) - { - tmp = new byte[dumpEntry.softwareOperatingSystemLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp); - } - - tmp = new byte[16]; - - for(uint j = 0; j < dumpEntry.extents; j++) - { - _imageStream.EnsureRead(tmp, 0, tmp.Length); - - dump.Extents.Add(new Extent - { - Start = BitConverter.ToUInt64(tmp, 0), - End = BitConverter.ToUInt64(tmp, 8) - }); - } - - dump.Extents = dump.Extents.OrderBy(t => t.Start).ToList(); - - if(dump.Extents.Count > 0) DumpHardware.Add(dump); - } - - if(DumpHardware.Count == 0) DumpHardware = null; - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - - // Tape partition block - case BlockType.TapePartitionBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - TapePartitionHeader partitionHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(partitionHeader.identifier != BlockType.TapePartitionBlock) break; - - AaruLogging.Debug(MODULE_NAME, Localization.Found_tape_partition_block_at_position_0, entry.offset); - - byte[] tapePartitionBytes = new byte[partitionHeader.length]; - _imageStream.EnsureRead(tapePartitionBytes, 0, tapePartitionBytes.Length); - - ReadOnlySpan tapePartitions = - MemoryMarshal.Cast(tapePartitionBytes); - - TapePartitions = []; - - foreach(TapePartitionEntry tapePartition in tapePartitions) - { - TapePartitions.Add(new TapePartition - { - FirstBlock = tapePartition.FirstBlock, - LastBlock = tapePartition.LastBlock, - Number = tapePartition.Number - }); - } - - IsTape = true; - - break; - - // Tape file block - case BlockType.TapeFileBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - TapeFileHeader fileHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(fileHeader.identifier != BlockType.TapeFileBlock) break; - - AaruLogging.Debug(MODULE_NAME, Localization.Found_tape_file_block_at_position_0, entry.offset); - - byte[] tapeFileBytes = new byte[fileHeader.length]; - _imageStream.EnsureRead(tapeFileBytes, 0, tapeFileBytes.Length); - ReadOnlySpan tapeFiles = MemoryMarshal.Cast(tapeFileBytes); - Files = []; - - foreach(TapeFileEntry file in tapeFiles) - { - Files.Add(new TapeFile - { - FirstBlock = file.FirstBlock, - LastBlock = file.LastBlock, - Partition = file.Partition, - File = file.File - }); - } - - IsTape = true; - - break; - - // Optical disc tracks block - case BlockType.CompactDiscIndexesBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - CompactDiscIndexesHeader indexesHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(indexesHeader.identifier != BlockType.CompactDiscIndexesBlock) - { - AaruLogging.Debug(MODULE_NAME, - Localization - .Incorrect_identifier_for_compact_disc_indexes_block_at_position_0, - entry.offset); - - break; - } - - _structureBytes = new byte[Marshal.SizeOf() * indexesHeader.entries]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] idsxCrc); - - if(BitConverter.ToUInt64(idsxCrc, 0) != indexesHeader.crc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_CRC_found_0_X16_found_expected_1_X16_continuing, - BitConverter.ToUInt64(idsxCrc, 0), - indexesHeader.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - compactDiscIndexes = []; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_0_compact_disc_indexes_at_position_1, - indexesHeader.entries, - entry.offset); - - for(ushort i = 0; i < indexesHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - compactDiscIndexes.Add(Marshal - .ByteArrayToStructureLittleEndian< - CompactDiscIndexEntry>(_structureBytes)); - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - } - } - - if(!foundUserDataDdt) - { - AaruLogging.Error(Localization.Could_not_find_user_data_deduplication_table); - - return ErrorNumber.InvalidArgument; - } - - _imageInfo.CreationTime = DateTime.FromFileTimeUtc(_header.creationTime); - AaruLogging.Debug(MODULE_NAME, Localization.Image_created_on_0, _imageInfo.CreationTime); - _imageInfo.LastModificationTime = DateTime.FromFileTimeUtc(_header.lastWrittenTime); - - AaruLogging.Debug(MODULE_NAME, Localization.Image_last_written_on_0, _imageInfo.LastModificationTime); - - _imageInfo.MetadataMediaType = GetMetadataMediaType(_header.mediaType); - - if(_geometryBlock.identifier != BlockType.GeometryBlock && - _imageInfo.MetadataMediaType == MetadataMediaType.BlockMedia) - { - _imageInfo.Cylinders = (uint)(_imageInfo.Sectors / 16 / 63); - _imageInfo.Heads = 16; - _imageInfo.SectorsPerTrack = 63; - } - - _imageInfo.ReadableMediaTags.AddRange(_mediaTags.Keys); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - // Initialize caches - _blockCache = new Dictionary(); - _blockHeaderCache = new Dictionary(); - _currentCacheSize = 0; - - if(!_inMemoryDdt) _ddtEntryCache = new Dictionary(); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - // Initialize tracks, sessions and partitions - if(_imageInfo.MetadataMediaType == MetadataMediaType.OpticalDisc) - { - if(Tracks != null) - { - bool leadOutFixed = false; - bool sessionPregapFixed = false; - - if(_mediaTags.TryGetValue(MediaTagType.CD_FullTOC, out byte[] fullToc)) - { - byte[] tmp = new byte[fullToc.Length + 2]; - Array.Copy(fullToc, 0, tmp, 2, fullToc.Length); - tmp[0] = (byte)(fullToc.Length >> 8); - tmp[1] = (byte)(fullToc.Length & 0xFF); - - FullTOC.CDFullTOC? decodedFullToc = FullTOC.Decode(tmp); - - if(decodedFullToc.HasValue) - { - Dictionary leadOutStarts = new(); // Lead-out starts - - foreach(FullTOC.TrackDataDescriptor trk in - decodedFullToc.Value.TrackDescriptors.Where(trk => trk.ADR is 1 or 4 && - trk.POINT == 0xA2)) - { - int phour, pmin, psec, pframe; - - if(trk.PFRAME == 0) - { - pframe = 74; - - if(trk.PSEC == 0) - { - psec = 59; - - if(trk.PMIN == 0) - { - pmin = 59; - phour = trk.PHOUR - 1; - } - else - { - pmin = trk.PMIN - 1; - phour = trk.PHOUR; - } - } - else - { - psec = trk.PSEC - 1; - pmin = trk.PMIN; - phour = trk.PHOUR; - } - } - else - { - pframe = trk.PFRAME - 1; - psec = trk.PSEC; - pmin = trk.PMIN; - phour = trk.PHOUR; - } - - int lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150; - leadOutStarts?.Add(trk.SessionNumber, lastSector + 1); - } - - foreach(KeyValuePair leadOuts in leadOutStarts) - { - var lastTrackInSession = new Track(); - - foreach(Track trk in Tracks.Where(trk => trk.Session == leadOuts.Key) - .Where(trk => trk.Sequence > lastTrackInSession.Sequence)) - lastTrackInSession = trk; - - if(lastTrackInSession.Sequence == 0 || - lastTrackInSession.EndSector == (ulong)leadOuts.Value - 1) - continue; - - lastTrackInSession.EndSector = (ulong)leadOuts.Value - 1; - leadOutFixed = true; - } - } - } - - if(_header.imageMajorVersion <= 1) - { - foreach(Track track in Tracks) - { - if(track.Sequence <= 1) continue; - - uint firstTrackNumberInSameSession = - Tracks.Where(t => t.Session == track.Session).Min(t => t.Sequence); - - if(firstTrackNumberInSameSession != track.Sequence) continue; - - if(track.Pregap == 150) continue; - - long dif = (long)track.Pregap - 150; - track.Pregap = (ulong)((long)track.Pregap - dif); - track.StartSector = (ulong)((long)track.StartSector + dif); - - sessionPregapFixed = true; - } - } - - if(leadOutFixed) - AaruLogging.Error(Localization.This_image_has_a_corrupted_track_list_convert_will_fix_it); - - if(sessionPregapFixed) - { - AaruLogging.Error(Localization - .This_image_has_a_corrupted_track_list_a_best_effort_has_been_tried_but_may_require_manual_editing_or_redump); - } - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - if(Tracks == null || Tracks.Count == 0) - { - Tracks = - [ - new Track - { - BytesPerSector = (int)_imageInfo.SectorSize, - EndSector = _imageInfo.Sectors - 1, - File = imageFilter.Filename, - FileType = "BINARY", - Filter = imageFilter, - RawBytesPerSector = (int)_imageInfo.SectorSize, - Session = 1, - Sequence = 1, - Type = TrackType.Data - } - ]; - - _trackFlags = new Dictionary - { - { - 1, (byte)CdFlags.DataTrack - } - }; - - _trackIsrcs = new Dictionary(); - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - Sessions = []; - - for(int i = 1; i <= Tracks.Max(t => t.Session); i++) - { - Sessions.Add(new Session - { - Sequence = (ushort)i, - StartTrack = Tracks.Where(t => t.Session == i).Min(t => t.Sequence), - EndTrack = Tracks.Where(t => t.Session == i).Max(t => t.Sequence), - StartSector = Tracks.Where(t => t.Session == i).Min(t => t.StartSector), - EndSector = Tracks.Where(t => t.Session == i).Max(t => t.EndSector) - }); - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - foreach(Track track in Tracks.OrderBy(t => t.StartSector)) - { - switch(track.Sequence) - { - case 0: - track.Pregap = 150; - track.Indexes[0] = -150; - track.Indexes[1] = (int)track.StartSector; - - continue; - case 1 when Tracks.All(t => t.Sequence != 0): - track.Pregap = 150; - track.Indexes[0] = -150; - track.Indexes[1] = (int)track.StartSector; - - continue; - } - - if(track.Pregap > 0) - { - track.Indexes[0] = (int)track.StartSector; - track.Indexes[1] = (int)(track.StartSector + track.Pregap); - } - else - track.Indexes[1] = (int)track.StartSector; - } - - ulong currentTrackOffset = 0; - Partitions = []; - - foreach(Track track in Tracks.OrderBy(t => t.StartSector)) - { - Partitions.Add(new Partition - { - Sequence = track.Sequence, - Type = track.Type.Humanize(), - Name = string.Format(Localization.Track_0, track.Sequence), - Offset = currentTrackOffset, - Start = (ulong)track.Indexes[1], - Size = (track.EndSector - (ulong)track.Indexes[1] + 1) * (ulong)track.BytesPerSector, - Length = track.EndSector - (ulong)track.Indexes[1] + 1, - Scheme = Localization.Optical_disc_track - }); - - currentTrackOffset += (track.EndSector - track.StartSector + 1) * (ulong)track.BytesPerSector; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - Track[] tracks = Tracks.ToArray(); - - foreach(Track trk in tracks) - { - ErrorNumber errno = ReadSector(trk.StartSector, out byte[] sector); - - if(errno != ErrorNumber.NoError) continue; - - trk.BytesPerSector = sector.Length; - - trk.RawBytesPerSector = - _sectorPrefix != null && _sectorSuffix != null || - _sectorPrefixDdt != null && _sectorSuffixDdt != null - ? 2352 - : sector.Length; - - if(_sectorSubchannel == null) continue; - - trk.SubchannelFile = trk.File; - trk.SubchannelFilter = trk.Filter; - trk.SubchannelType = TrackSubchannelType.Raw; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - Tracks = tracks.ToList(); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - if(compactDiscIndexes != null) - { - foreach(CompactDiscIndexEntry compactDiscIndex in compactDiscIndexes.OrderBy(i => i.Track) - .ThenBy(i => i.Index)) - { - Track track = Tracks.FirstOrDefault(t => t.Sequence == compactDiscIndex.Track); - - if(track is null) continue; - - track.Indexes[compactDiscIndex.Index] = compactDiscIndex.Lba; - } - } - } - else - { - Tracks = null; - Sessions = null; - Partitions = null; - } - - SetMetadataFromTags(); - - if(_sectorSuffixDdt != null) EccInit(); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NoError; - - if(_imageInfo.MediaType is MediaType.CD - or MediaType.CDDA - or MediaType.CDG - or MediaType.CDEG - or MediaType.CDI - or MediaType.CDROM - or MediaType.CDROMXA - or MediaType.CDPLUS - or MediaType.CDMO - or MediaType.CDR - or MediaType.CDRW - or MediaType.CDMRW - or MediaType.VCD - or MediaType.SVCD - or MediaType.PCD - or MediaType.DTSCD - or MediaType.CDMIDI - or MediaType.CDV - or MediaType.CDIREADY - or MediaType.FMTOWNS - or MediaType.PS1CD - or MediaType.PS2CD - or MediaType.MEGACD - or MediaType.SATURNCD - or MediaType.GDROM - or MediaType.GDR - or MediaType.MilCD - or MediaType.SuperCDROM2 - or MediaType.JaguarCD - or MediaType.ThreeDO - or MediaType.PCFX - or MediaType.NeoGeoCD - or MediaType.CDTV - or MediaType.CD32 - or MediaType.Playdia - or MediaType.Pippin - or MediaType.VideoNow - or MediaType.VideoNowColor - or MediaType.VideoNowXp - or MediaType.CVD) - return ErrorNumber.NoError; - - { - foreach(Track track in Tracks) - { - track.Pregap = 0; - track.Indexes?.Clear(); - } - } - - return ErrorNumber.NoError; - } - - /// - public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer) - { - buffer = null; - - return _mediaTags.TryGetValue(tag, out buffer) ? ErrorNumber.NoError : ErrorNumber.NoData; - } - - /// - public ErrorNumber ReadSector(ulong sectorAddress, out byte[] buffer) - { - buffer = null; - - if(sectorAddress > _imageInfo.Sectors - 1) return ErrorNumber.OutOfRange; - - ulong ddtEntry = GetDdtEntry(sectorAddress); - uint offsetMask = (uint)((1 << _shift) - 1); - ulong offset = ddtEntry & offsetMask; - ulong blockOffset = ddtEntry >> _shift; - - // Partially written image... as we can't know the real sector size just assume it's common :/ - if(ddtEntry == 0) - { - buffer = new byte[_imageInfo.SectorSize]; - - return ErrorNumber.NoError; - } - - // Check if block is cached - if(_blockCache.TryGetValue(blockOffset, out byte[] block) && - _blockHeaderCache.TryGetValue(blockOffset, out BlockHeader blockHeader)) - { - buffer = new byte[blockHeader.sectorSize]; - Array.Copy(block, (long)(offset * blockHeader.sectorSize), buffer, 0, blockHeader.sectorSize); - - return ErrorNumber.NoError; - } - - // Read block header - _imageStream.Position = (long)blockOffset; - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - blockHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - // Decompress block - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - ulong decompressedLength; - - switch(blockHeader.compression) - { - case CompressionType.None: - block = new byte[blockHeader.length]; - _imageStream.EnsureRead(block, 0, (int)blockHeader.length); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - case CompressionType.Lzma: - byte[] compressedBlock = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.EnsureRead(compressedBlock, 0, compressedBlock.Length); - block = new byte[blockHeader.length]; - decompressedLength = (ulong)LZMA.DecodeBuffer(compressedBlock, block, lzmaProperties); - - if(decompressedLength != blockHeader.length) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Error_decompressing_block_should_be_0_bytes_but_got_1_bytes, - blockHeader.length, - decompressedLength); - - return ErrorNumber.InOutError; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - case CompressionType.Flac: - byte[] flacBlock = new byte[blockHeader.cmpLength]; - _imageStream.EnsureRead(flacBlock, 0, flacBlock.Length); - block = new byte[blockHeader.length]; - decompressedLength = (ulong)FLAC.DecodeBuffer(flacBlock, block); - - if(decompressedLength != blockHeader.length) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Error_decompressing_block_should_be_0_bytes_but_got_1_bytes, - blockHeader.length, - decompressedLength); - - return ErrorNumber.InOutError; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - default: - return ErrorNumber.NotSupported; - } - - // Check if cache needs to be emptied - if(_currentCacheSize + blockHeader.length >= MAX_CACHE_SIZE) - { - _currentCacheSize = 0; - _blockHeaderCache = new Dictionary(); - _blockCache = new Dictionary(); - } - - // Add block to cache - _currentCacheSize += blockHeader.length; - _blockHeaderCache.Add(blockOffset, blockHeader); - _blockCache.Add(blockOffset, block); - - buffer = new byte[blockHeader.sectorSize]; - Array.Copy(block, (long)(offset * blockHeader.sectorSize), buffer, 0, blockHeader.sectorSize); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - return ErrorNumber.NoError; - } - - /// - public ErrorNumber ReadSectorTag(ulong sectorAddress, SectorTagType tag, out byte[] buffer) => - ReadSectorsTag(sectorAddress, 1, tag, out buffer); - - /// - public ErrorNumber ReadSector(ulong sectorAddress, uint track, out byte[] buffer) - { - buffer = null; - - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported; - - Track trk = Tracks.FirstOrDefault(t => t.Sequence == track); - - return trk?.Sequence != track - ? ErrorNumber.SectorNotFound - : ReadSector(trk.StartSector + sectorAddress, out buffer); - } - - /// - public ErrorNumber ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag, out byte[] buffer) - { - buffer = null; - - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported; - - Track trk = Tracks.FirstOrDefault(t => t.Sequence == track); - - return trk?.Sequence != track - ? ErrorNumber.SectorNotFound - : ReadSectorTag(trk.StartSector + sectorAddress, tag, out buffer); - } - - /// - public ErrorNumber ReadSectors(ulong sectorAddress, uint length, out byte[] buffer) - { - buffer = null; - - if(sectorAddress > _imageInfo.Sectors - 1) return ErrorNumber.OutOfRange; - - if(sectorAddress + length > _imageInfo.Sectors) return ErrorNumber.OutOfRange; - - var ms = new MemoryStream(); - - for(uint i = 0; i < length; i++) - { - ErrorNumber errno = ReadSector(sectorAddress + i, out byte[] sector); - - if(errno != ErrorNumber.NoError) return errno; - - ms.Write(sector, 0, sector.Length); - } - - buffer = ms.ToArray(); - - return ErrorNumber.NoError; - } - - /// - public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag, out byte[] buffer) - { - uint sectorOffset; - uint sectorSize; - uint sectorSkip; - byte[] dataSource; - buffer = null; - - if(_imageInfo.MetadataMediaType == MetadataMediaType.OpticalDisc) - { - Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector); - - if(trk is null) return ErrorNumber.SectorNotFound; - - if(trk.Sequence == 0 && trk.StartSector == 0 && trk.EndSector == 0) return ErrorNumber.SectorNotFound; - - switch(tag) - { - case SectorTagType.CdSectorEcc: - case SectorTagType.CdSectorEccP: - case SectorTagType.CdSectorEccQ: - case SectorTagType.CdSectorEdc: - case SectorTagType.CdSectorHeader: - case SectorTagType.CdSectorSubchannel: - case SectorTagType.CdSectorSubHeader: - case SectorTagType.CdSectorSync: - case SectorTagType.DvdSectorCmi: - case SectorTagType.DvdSectorTitleKey: - case SectorTagType.DvdSectorInformation: - case SectorTagType.DvdSectorNumber: - case SectorTagType.DvdSectorIed: - case SectorTagType.DvdSectorEdc: - case SectorTagType.DvdTitleKeyDecrypted: - break; - case SectorTagType.CdTrackFlags: - if(!_trackFlags.TryGetValue((byte)sectorAddress, out byte flags)) return ErrorNumber.NoData; - - buffer = [flags]; - - return ErrorNumber.NoError; - case SectorTagType.CdTrackIsrc: - if(!_trackIsrcs.TryGetValue((byte)sectorAddress, out string isrc)) return ErrorNumber.NoData; - - buffer = Encoding.UTF8.GetBytes(isrc); - - return ErrorNumber.NoError; - default: - return ErrorNumber.NotSupported; - } - - switch(trk.Type) - { - case TrackType.CdMode1: - switch(tag) - { - case SectorTagType.CdSectorSync: - { - sectorOffset = 0; - sectorSize = 12; - sectorSkip = 4; - dataSource = _sectorPrefix; - - break; - } - - case SectorTagType.CdSectorHeader: - { - sectorOffset = 12; - sectorSize = 4; - sectorSkip = 2336; - dataSource = _sectorPrefix; - - break; - } - - case SectorTagType.CdSectorSubHeader: - return ErrorNumber.NotSupported; - case SectorTagType.CdSectorEcc: - { - sectorOffset = 12; - sectorSize = 276; - sectorSkip = 0; - dataSource = _sectorSuffix; - - break; - } - - case SectorTagType.CdSectorEccP: - { - sectorOffset = 12; - sectorSize = 172; - sectorSkip = 104; - dataSource = _sectorSuffix; - - break; - } - - case SectorTagType.CdSectorEccQ: - { - sectorOffset = 184; - sectorSize = 104; - sectorSkip = 0; - dataSource = _sectorSuffix; - - break; - } - - case SectorTagType.CdSectorEdc: - { - sectorOffset = 0; - sectorSize = 4; - sectorSkip = 284; - dataSource = _sectorSuffix; - - break; - } - - case SectorTagType.CdSectorSubchannel: - { - sectorOffset = 0; - sectorSize = 96; - sectorSkip = 0; - dataSource = _sectorSubchannel; - - break; - } - - default: - return ErrorNumber.NotSupported; - } - - break; - case TrackType.CdMode2Formless: - case TrackType.CdMode2Form1: - case TrackType.CdMode2Form2: - { - switch(tag) - { - case SectorTagType.CdSectorSync: - { - sectorOffset = 0; - sectorSize = 12; - sectorSkip = 4; - dataSource = _sectorPrefix; - - break; - } - - case SectorTagType.CdSectorHeader: - { - sectorOffset = 12; - sectorSize = 4; - sectorSkip = 0; - dataSource = _sectorPrefix; - - break; - } - - case SectorTagType.CdSectorSubHeader: - { - sectorOffset = 0; - sectorSize = 8; - sectorSkip = 0; - dataSource = _mode2Subheaders; - - break; - } - - // These could be implemented - case SectorTagType.CdSectorEcc: - case SectorTagType.CdSectorEccP: - case SectorTagType.CdSectorEccQ: - case SectorTagType.CdSectorEdc: - return ErrorNumber.NotSupported; - case SectorTagType.CdSectorSubchannel: - { - sectorOffset = 0; - sectorSize = 96; - sectorSkip = 0; - dataSource = _sectorSubchannel; - - break; - } - - default: - return ErrorNumber.NotSupported; - } - - break; - } - - case TrackType.Audio: - { - switch(tag) - { - case SectorTagType.CdSectorSubchannel: - { - sectorOffset = 0; - sectorSize = 96; - sectorSkip = 0; - dataSource = _sectorSubchannel; - - break; - } - - default: - return ErrorNumber.NotSupported; - } - - break; - } - - case TrackType.Data: - { - if(_imageInfo.MediaType == MediaType.DVDROM) - { - switch(tag) - { - case SectorTagType.DvdSectorCmi: - { - sectorOffset = 0; - sectorSize = 1; - sectorSkip = 5; - dataSource = _sectorCprMai; - - break; - } - case SectorTagType.DvdSectorTitleKey: - { - sectorOffset = 1; - sectorSize = 5; - sectorSkip = 0; - dataSource = _sectorCprMai; - - break; - } - case SectorTagType.DvdSectorInformation: - { - sectorOffset = 0; - sectorSize = 1; - sectorSkip = 3; - dataSource = _sectorId; - - break; - } - case SectorTagType.DvdSectorNumber: - { - sectorOffset = 1; - sectorSize = 3; - sectorSkip = 0; - dataSource = _sectorId; - - break; - } - case SectorTagType.DvdSectorIed: - { - sectorOffset = 0; - sectorSize = 2; - sectorSkip = 0; - dataSource = _sectorIed; - - break; - } - case SectorTagType.DvdSectorEdc: - { - sectorOffset = 0; - sectorSize = 4; - sectorSkip = 0; - dataSource = _sectorEdc; - - break; - } - case SectorTagType.DvdTitleKeyDecrypted: - { - sectorOffset = 0; - sectorSize = 5; - sectorSkip = 0; - dataSource = _sectorDecryptedTitleKey; - - break; - } - default: - return ErrorNumber.NotSupported; - } - } - else - return ErrorNumber.NotSupported; - - break; - } - - default: - return ErrorNumber.NotSupported; - } - } - else - return ErrorNumber.NoData; - - if(dataSource == null) return ErrorNumber.NotSupported; - - buffer = new byte[sectorSize * length]; - - if(sectorOffset == 0 && sectorSkip == 0) - { - Array.Copy(dataSource, (long)(sectorAddress * sectorSize), buffer, 0, length * sectorSize); - - return ErrorNumber.NoError; - } - - for(int i = 0; i < length; i++) - { - Array.Copy(dataSource, - (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip) + sectorOffset), - buffer, - i * sectorSize, - sectorSize); - } - - return ErrorNumber.NoError; - } - - /// - public ErrorNumber ReadSectors(ulong sectorAddress, uint length, uint track, out byte[] buffer) - { - buffer = null; - - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported; - - Track trk = Tracks.FirstOrDefault(t => t.Sequence == track); - - if(trk?.Sequence != track) return ErrorNumber.SectorNotFound; - - return trk.StartSector + sectorAddress + length > trk.EndSector + 1 - ? ErrorNumber.OutOfRange - : ReadSectors(trk.StartSector + sectorAddress, length, out buffer); - } - - /// - public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag, - out byte[] buffer) - { - buffer = null; - - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported; - - Track trk = Tracks.FirstOrDefault(t => t.Sequence == track); - - return trk?.Sequence != track - ? ErrorNumber.SectorNotFound - : trk.StartSector + sectorAddress + length > trk.EndSector + 1 - ? ErrorNumber.OutOfRange - : ReadSectorsTag(trk.StartSector + sectorAddress, length, tag, out buffer); - } - - /// - public ErrorNumber ReadSectorLong(ulong sectorAddress, out byte[] buffer) - { - buffer = null; - - switch(_imageInfo.MetadataMediaType) - { - case MetadataMediaType.OpticalDisc: - Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector); - - if(trk is null) return ErrorNumber.SectorNotFound; - - if(trk.Sequence == 0 && trk.StartSector == 0 && trk.EndSector == 0) return ErrorNumber.SectorNotFound; - - if((_sectorSuffix == null || _sectorPrefix == null) && - (_sectorSuffixDdt == null || _sectorPrefixDdt == null)) - return ReadSector(sectorAddress, out buffer); - - buffer = new byte[2352]; - ErrorNumber errno = ReadSector(sectorAddress, out byte[] data); - - if(errno != ErrorNumber.NoError) return errno; - - switch(trk.Type) - { - case TrackType.Audio: - case TrackType.Data: - buffer = data; - - return ErrorNumber.NoError; - case TrackType.CdMode1: - Array.Copy(data, 0, buffer, 16, 2048); - - if(_sectorPrefix != null) - Array.Copy(_sectorPrefix, (int)sectorAddress * 16, buffer, 0, 16); - else if(_sectorPrefixDdt != null) - { - if((_sectorPrefixDdt[sectorAddress] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct) - ReconstructPrefix(ref buffer, trk.Type, (long)sectorAddress); - else if((_sectorPrefixDdt[sectorAddress] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped || - _sectorPrefixDdt[sectorAddress] == 0) - { - // Do nothing - } - else - { - uint prefixPosition = ((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16; - - if(prefixPosition > _sectorPrefixMs.Length) return ErrorNumber.InvalidArgument; - - _sectorPrefixMs.Position = prefixPosition; - - _sectorPrefixMs.EnsureRead(buffer, 0, 16); - } - } - else - return ErrorNumber.InvalidArgument; - - if(_sectorSuffix != null) - Array.Copy(_sectorSuffix, (int)sectorAddress * 288, buffer, 2064, 288); - else if(_sectorSuffixDdt != null) - { - if((_sectorSuffixDdt[sectorAddress] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct) - ReconstructEcc(ref buffer, trk.Type); - else if((_sectorSuffixDdt[sectorAddress] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped || - _sectorSuffixDdt[sectorAddress] == 0) - { - // Do nothing - } - else - { - uint suffixPosition = ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; - - if(suffixPosition > _sectorSuffixMs.Length) return ErrorNumber.InvalidArgument; - - _sectorSuffixMs.Position = suffixPosition; - - _sectorSuffixMs.EnsureRead(buffer, 2064, 288); - } - } - else - return ErrorNumber.InvalidArgument; - - return ErrorNumber.NoError; - case TrackType.CdMode2Formless: - case TrackType.CdMode2Form1: - case TrackType.CdMode2Form2: - if(_sectorPrefix != null) - Array.Copy(_sectorPrefix, (int)sectorAddress * 16, buffer, 0, 16); - else if(_sectorPrefixMs != null) - { - if((_sectorPrefixDdt[sectorAddress] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct) - ReconstructPrefix(ref buffer, trk.Type, (long)sectorAddress); - else if((_sectorPrefixDdt[sectorAddress] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped || - _sectorPrefixDdt[sectorAddress] == 0) - { - // Do nothing - } - else - { - uint prefixPosition = ((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16; - - if(prefixPosition > _sectorPrefixMs.Length) return ErrorNumber.InvalidArgument; - - _sectorPrefixMs.Position = prefixPosition; - - _sectorPrefixMs.EnsureRead(buffer, 0, 16); - } - } - else - return ErrorNumber.InvalidArgument; - - if(_mode2Subheaders != null && _sectorSuffixDdt != null) - { - Array.Copy(_mode2Subheaders, (int)sectorAddress * 8, buffer, 16, 8); - - switch(_sectorSuffixDdt[sectorAddress] & CD_XFIX_MASK) - { - case (uint)CdFixFlags.Mode2Form1Ok: - Array.Copy(data, 0, buffer, 24, 2048); - ReconstructEcc(ref buffer, TrackType.CdMode2Form1); - - break; - case (uint)CdFixFlags.Mode2Form2Ok: - case (uint)CdFixFlags.Mode2Form2NoCrc: - { - Array.Copy(data, 0, buffer, 24, 2324); - - if((_sectorSuffixDdt[sectorAddress] & CD_XFIX_MASK) == - (uint)CdFixFlags.Mode2Form2Ok) - ReconstructEcc(ref buffer, TrackType.CdMode2Form2); - - break; - } - default: - { - if((_sectorSuffixDdt[sectorAddress] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped || - _sectorSuffixDdt[sectorAddress] == 0) - { - // Do nothing - } - else // Mode 2 where EDC failed - { - // Incorrectly written images - if(data.Length == 2328) - Array.Copy(data, 0, buffer, 24, 2328); - else - { - bool form2 = (buffer[18] & 0x20) == 0x20 || (buffer[22] & 0x20) == 0x20; - - uint suffixPosition = - ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; - - if(suffixPosition > _sectorSuffixMs.Length) - return ErrorNumber.InvalidArgument; - - _sectorSuffixMs.Position = suffixPosition; - - _sectorSuffixMs.EnsureRead(buffer, form2 ? 2348 : 2072, form2 ? 4 : 280); - Array.Copy(data, 0, buffer, 24, form2 ? 2324 : 2048); - } - } - - break; - } - } - } - else if(_mode2Subheaders != null) - { - Array.Copy(_mode2Subheaders, (int)sectorAddress * 8, buffer, 16, 8); - Array.Copy(data, 0, buffer, 24, 2328); - } - else - Array.Copy(data, 0, buffer, 16, 2336); - - return ErrorNumber.NoError; - } - - break; - case MetadataMediaType.BlockMedia: - switch(_imageInfo.MediaType) - { - case MediaType.AppleFileWare: - case MediaType.AppleProfile: - case MediaType.AppleSonySS: - case MediaType.AppleSonyDS: - case MediaType.AppleWidget: - case MediaType.PriamDataTower: - return ReadSectorsLong(sectorAddress, 1, out buffer); - } - - break; - } - - return ErrorNumber.NotSupported; - } - - /// - public ErrorNumber ReadSectorLong(ulong sectorAddress, uint track, out byte[] buffer) - { - buffer = null; - - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported; - - Track trk = Tracks.FirstOrDefault(t => t.Sequence == track); - - return trk?.Sequence != track - ? ErrorNumber.SectorNotFound - : ReadSectorLong(trk.StartSector + sectorAddress, out buffer); - } - - /// - public ErrorNumber ReadSectorsLong(ulong sectorAddress, uint length, out byte[] buffer) - { - byte[] data; - ErrorNumber errno; - buffer = null; - - switch(_imageInfo.MetadataMediaType) - { - case MetadataMediaType.OpticalDisc: - Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector); - - if(trk is null) return ErrorNumber.SectorNotFound; - - if(trk.Sequence == 0 && trk.StartSector == 0 && trk.EndSector == 0) return ErrorNumber.SectorNotFound; - - if(sectorAddress + length > trk.EndSector + 1) return ErrorNumber.OutOfRange; - - switch(trk.Type) - { - // These types only contain user data - case TrackType.Audio: - case TrackType.Data: - return ReadSectors(sectorAddress, length, out buffer); - - // Join prefix (sync, header) with user data with suffix (edc, ecc p, ecc q) - case TrackType.CdMode1: - if(_sectorPrefix != null && _sectorSuffix != null) - { - buffer = new byte[2352 * length]; - errno = ReadSectors(sectorAddress, length, out data); - - if(errno != ErrorNumber.NoError) return errno; - - for(uint i = 0; i < length; i++) - { - Array.Copy(_sectorPrefix, (int)((sectorAddress + i) * 16), buffer, (int)(i * 2352), 16); - - Array.Copy(data, (int)(i * 2048), buffer, (int)(i * 2352) + 16, 2048); - - Array.Copy(_sectorSuffix, - (int)((sectorAddress + i) * 288), - buffer, - (int)(i * 2352) + 2064, - 288); - } - - return ErrorNumber.NoError; - } - - if(_sectorPrefixDdt == null || _sectorSuffixDdt == null) - return ReadSectors(sectorAddress, length, out buffer); - - buffer = new byte[2352 * length]; - - for(uint i = 0; i < length; i++) - { - errno = ReadSectorLong(sectorAddress + i, out byte[] temp); - - if(errno != ErrorNumber.NoError) return errno; - - Array.Copy(temp, 0, buffer, 2352 * i, 2352); - } - - return ErrorNumber.NoError; - - // Join prefix (sync, header) with user data - case TrackType.CdMode2Formless: - case TrackType.CdMode2Form1: - case TrackType.CdMode2Form2: - if(_sectorPrefix != null && _sectorSuffix != null) - { - buffer = new byte[2352 * length]; - errno = ReadSectors(sectorAddress, length, out data); - - if(errno != ErrorNumber.NoError) return errno; - - for(uint i = 0; i < length; i++) - { - Array.Copy(_sectorPrefix, (int)((sectorAddress + i) * 16), buffer, (int)(i * 2352), 16); - - Array.Copy(data, (int)(i * 2336), buffer, (int)(i * 2352) + 16, 2336); - } - - return ErrorNumber.NoError; - } - - if(_sectorPrefixDdt == null || _sectorSuffixDdt == null) - return ReadSectors(sectorAddress, length, out buffer); - - buffer = new byte[2352 * length]; - - for(uint i = 0; i < length; i++) - { - errno = ReadSectorLong(sectorAddress + i, out byte[] temp); - - if(errno != ErrorNumber.NoError) return errno; - - Array.Copy(temp, 0, buffer, 2352 * i, 2352); - } - - return ErrorNumber.NoError; - } - - break; - case MetadataMediaType.BlockMedia: - switch(_imageInfo.MediaType) - { - // Join user data with tags - case MediaType.AppleFileWare: - case MediaType.AppleProfile: - case MediaType.AppleSonySS: - case MediaType.AppleSonyDS: - case MediaType.AppleWidget: - case MediaType.PriamDataTower: - if(_sectorSubchannel == null) return ReadSector(sectorAddress, out buffer); - - uint tagSize = _imageInfo.MediaType switch - { - MediaType.AppleFileWare - or MediaType.AppleProfile - or MediaType.AppleWidget => 20, - MediaType.AppleSonySS or MediaType.AppleSonyDS => 12, - MediaType.PriamDataTower => 24, - _ => 0 - }; - - uint sectorSize = 512 + tagSize; - errno = ReadSectors(sectorAddress, length, out data); - - if(errno != ErrorNumber.NoError) return errno; - - buffer = new byte[(sectorSize + 512) * length]; - - for(uint i = 0; i < length; i++) - { - Array.Copy(_sectorSubchannel, - (int)((sectorAddress + i) * tagSize), - buffer, - (int)(i * sectorSize + 512), - tagSize); - - Array.Copy(data, (int)((sectorAddress + i) * 512), buffer, (int)(i * 512), 512); - } - - return ErrorNumber.NoError; - } - - break; - } - - return ErrorNumber.NotSupported; - } - - /// - public ErrorNumber ReadSectorsLong(ulong sectorAddress, uint length, uint track, out byte[] buffer) - { - buffer = null; - - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return ErrorNumber.NotSupported; - - Track trk = Tracks.FirstOrDefault(t => t.Sequence == track); - - return trk?.Sequence != track - ? ErrorNumber.SectorNotFound - : trk.StartSector + sectorAddress + length > trk.EndSector + 1 - ? ErrorNumber.OutOfRange - : ReadSectorsLong(trk.StartSector + sectorAddress, length, out buffer); - } - - /// - public List GetSessionTracks(Session session) => Tracks.Where(t => t.Sequence == session.Sequence).ToList(); - - /// - public List GetSessionTracks(ushort session) => Tracks.Where(t => t.Sequence == session).ToList(); - -#endregion -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Structs.cs b/Aaru.Images/AaruFormatOld/Structs.cs deleted file mode 100644 index b45005a0d..000000000 --- a/Aaru.Images/AaruFormatOld/Structs.cs +++ /dev/null @@ -1,508 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Structs.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Contains structures for Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -using System.Runtime.InteropServices; -using Aaru.CommonTypes; -using Aaru.CommonTypes.Enums; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ -#region Nested type: AaruHeader - - /// Header, at start of file - [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)] - struct AaruHeader - { - /// Header identifier, - public ulong identifier; - /// UTF-16LE name of the application that created the image - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] - public string application; - /// Image format major version. A new major version means a possibly incompatible change of format - public byte imageMajorVersion; - /// Image format minor version. A new minor version indicates a compatible change of format - public byte imageMinorVersion; - /// Major version of the application that created the image - public byte applicationMajorVersion; - /// Minor version of the application that created the image - public byte applicationMinorVersion; - /// Type of media contained on image - public MediaType mediaType; - /// Offset to index - public ulong indexOffset; - /// Windows filetime (100 nanoseconds since 1601/01/01 00:00:00 UTC) of image creation time - public long creationTime; - /// Windows filetime (100 nanoseconds since 1601/01/01 00:00:00 UTC) of image last written time - public long lastWrittenTime; - } - -#endregion - -#region Nested type: AaruMetadataJsonBlock - - /// Aaru Metadata JSON block - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct AaruMetadataJsonBlock - { - /// Identifier, - public BlockType identifier; - public uint length; - } - -#endregion - -#region Nested type: BlockHeader - - /// Block header, precedes block data - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct BlockHeader - { - /// Identifier, - public BlockType identifier; - /// Type of data contained by this block - public DataType type; - /// Compression algorithm used to compress the block - public CompressionType compression; - /// Size in bytes of each sector contained in this block - public uint sectorSize; - /// Compressed length for the block - public uint cmpLength; - /// Uncompressed length for the block - public uint length; - /// CRC64-ECMA of the compressed block - public ulong cmpCrc64; - /// CRC64-ECMA of the uncompressed block - public ulong crc64; - } - -#endregion - -#region Nested type: ChecksumEntry - - /// Checksum entry, followed by checksum data itself - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct ChecksumEntry - { - /// Checksum algorithm - public ChecksumAlgorithm type; - /// Length in bytes of checksum that follows this structure - public uint length; - } - -#endregion - -#region Nested type: ChecksumHeader - - /// - /// Checksum block, contains a checksum of all user data sectors (except for optical discs that is 2352 bytes raw - /// sector if available - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct ChecksumHeader - { - /// Identifier, - public BlockType identifier; - /// Length in bytes of the block - public uint length; - /// How many checksums follow - public byte entries; - } - -#endregion - -#region Nested type: CicmMetadataBlock - - /// CICM Metadata XML block - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct CicmMetadataBlock - { - /// Identifier, - public readonly BlockType identifier; - public readonly uint length; - } - -#endregion - -#region Nested type: CompactDiscIndexEntry - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct CompactDiscIndexEntry - { - /// How many entries follow this header - public ushort Track; - /// Size of the whole block, not including this header, in bytes - public ushort Index; - /// CRC64-ECMA of the block - public int Lba; - } - -#endregion - -#region Nested type: CompactDiscIndexesHeader - - /// - /// Compact Disc track indexes block, contains a cache of all Compact Disc indexes to not need to interpret - /// subchannel - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct CompactDiscIndexesHeader - { - /// Identifier, - public BlockType identifier; - /// How many entries follow this header - public ushort entries; - /// Size of the whole block, not including this header, in bytes - public readonly ulong length; - /// CRC64-ECMA of the block - public ulong crc64; - } - -#endregion - -#region Nested type: DdtHeader - - /// Header for a deduplication table. Table follows it - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DdtHeader - { - /// Identifier, - public BlockType identifier; - /// Type of data pointed by this DDT - public DataType type; - /// Compression algorithm used to compress the DDT - public CompressionType compression; - /// Each entry is ((byte offset in file) << shift) + (sector offset in block) - public byte shift; - /// How many entries are in the table - public ulong entries; - /// Compressed length for the DDT - public ulong cmpLength; - /// Uncompressed length for the DDT - public ulong length; - /// CRC64-ECMA of the compressed DDT - public ulong cmpCrc64; - /// CRC64-ECMA of the uncompressed DDT - public readonly ulong crc64; - } - -#endregion - -#region Nested type: DumpHardwareEntry - - /// Dump hardware entry, contains length of strings that follow, in the same order as the length, this structure - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DumpHardwareEntry - { - /// Length of UTF-8 manufacturer string - public uint manufacturerLength; - /// Length of UTF-8 model string - public uint modelLength; - /// Length of UTF-8 revision string - public uint revisionLength; - /// Length of UTF-8 firmware version string - public uint firmwareLength; - /// Length of UTF-8 serial string - public uint serialLength; - /// Length of UTF-8 software name string - public uint softwareNameLength; - /// Length of UTF-8 software version string - public uint softwareVersionLength; - /// Length of UTF-8 software operating system string - public uint softwareOperatingSystemLength; - /// How many extents are after the strings - public uint extents; - } - -#endregion - -#region Nested type: DumpHardwareHeader - - /// Dump hardware block, contains a list of hardware used to dump the media on this image - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DumpHardwareHeader - { - /// Identifier, - public BlockType identifier; - /// How many entries follow this header - public ushort entries; - /// Size of the whole block, not including this header, in bytes - public uint length; - /// CRC64-ECMA of the block - public ulong crc64; - } - -#endregion - -#region Nested type: GeometryBlock - - /// Geometry block, contains physical geometry information - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct GeometryBlock - { - /// Identifier, - public BlockType identifier; - public uint cylinders; - public uint heads; - public uint sectorsPerTrack; - } - -#endregion - -#region Nested type: IndexEntry - - /// Index entry - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct IndexEntry - { - /// Type of item pointed by this entry - public BlockType blockType; - /// Type of data contained by the block pointed by this entry - public DataType dataType; - /// Offset in file where item is stored - public ulong offset; - } - -#endregion - -#region Nested type: IndexHeader - - /// Header for the index, followed by entries - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct IndexHeader - { - /// Identifier, - public BlockType identifier; - /// How many entries follow this header - public ushort entries; - /// CRC64-ECMA of the index - public ulong crc64; - } - -#endregion - -#region Nested type: IndexHeader2 - - /// 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; - } - -#endregion - -#region Nested type: MetadataBlock - - /// Metadata block, contains metadata - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct MetadataBlock - { - /// Identifier, - public BlockType identifier; - /// Size in bytes of this whole metadata block - public uint blockSize; - /// Sequence of media set this media belongs to - public int mediaSequence; - /// Total number of media on the media set this media belongs to - public int lastMediaSequence; - /// Offset to start of creator string from start of this block - public uint creatorOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint creatorLength; - /// Offset to start of creator string from start of this block - public uint commentsOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint commentsLength; - /// Offset to start of creator string from start of this block - public uint mediaTitleOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint mediaTitleLength; - /// Offset to start of creator string from start of this block - public uint mediaManufacturerOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint mediaManufacturerLength; - /// Offset to start of creator string from start of this block - public uint mediaModelOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint mediaModelLength; - /// Offset to start of creator string from start of this block - public uint mediaSerialNumberOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint mediaSerialNumberLength; - /// Offset to start of creator string from start of this block - public uint mediaBarcodeOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint mediaBarcodeLength; - /// Offset to start of creator string from start of this block - public uint mediaPartNumberOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint mediaPartNumberLength; - /// Offset to start of creator string from start of this block - public uint driveManufacturerOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint driveManufacturerLength; - /// Offset to start of creator string from start of this block - public uint driveModelOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint driveModelLength; - /// Offset to start of creator string from start of this block - public uint driveSerialNumberOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint driveSerialNumberLength; - /// Offset to start of creator string from start of this block - public uint driveFirmwareRevisionOffset; - /// Length in bytes of the null-terminated UTF-16LE creator string - public uint driveFirmwareRevisionLength; - } - -#endregion - -#region Nested type: TapeFileEntry - - /// Tape file entry - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct TapeFileEntry - { - /// File number - public uint File; - /// Partition number - public readonly byte Partition; - /// First block, inclusive, of the file - public ulong FirstBlock; - /// Last block, inclusive, of the file - public ulong LastBlock; - } - -#endregion - -#region Nested type: TapeFileHeader - - /// Tape file block, contains a list of all files in a tape - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct TapeFileHeader - { - /// Identifier, - public BlockType identifier; - /// How many entries follow this header - public uint entries; - /// Size of the whole block, not including this header, in bytes - public ulong length; - /// CRC64-ECMA of the block - public ulong crc64; - } - -#endregion - -#region Nested type: TapePartitionEntry - - /// Tape partition entry - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct TapePartitionEntry - { - /// Partition number - public byte Number; - /// First block, inclusive, of the partition - public ulong FirstBlock; - /// Last block, inclusive, of the partition - public ulong LastBlock; - } - -#endregion - -#region Nested type: TapePartitionHeader - - /// Tape partition block, contains a list of all partitions in a tape - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct TapePartitionHeader - { - /// Identifier, - public BlockType identifier; - /// How many entries follow this header - public byte entries; - /// Size of the whole block, not including this header, in bytes - public ulong length; - /// CRC64-ECMA of the block - public ulong crc64; - } - -#endregion - -#region Nested type: TrackEntry - - /// Optical disc track - [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] - struct TrackEntry - { - /// Track sequence - public byte sequence; - /// Track type - public TrackType type; - /// Track starting LBA - public long start; - /// Track last LBA - public long end; - /// Track pregap in sectors - public long pregap; - /// Track session - public byte session; - /// Track's ISRC in ASCII - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)] - public string isrc; - /// Track flags - public byte flags; - } - -#endregion - -#region Nested type: TracksHeader - - /// Contains list of optical disc tracks - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct TracksHeader - { - /// Identifier, - public BlockType identifier; - /// How many entries follow this header - public ushort entries; - /// CRC64-ECMA of the block - public ulong crc64; - } - -#endregion -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Tape.cs b/Aaru.Images/AaruFormatOld/Tape.cs deleted file mode 100644 index 0b97192da..000000000 --- a/Aaru.Images/AaruFormatOld/Tape.cs +++ /dev/null @@ -1,90 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Tape.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Manages Aaru Format tape images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -using System.Collections.Generic; -using System.Linq; -using Aaru.CommonTypes.Structs; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ -#region IWritableTapeImage Members - - /// - public List Files { get; private set; } - - /// - public List TapePartitions { get; private set; } - - /// - public bool IsTape { get; private set; } - - /// - public bool AddFile(TapeFile file) - { - if(Files.Any(f => f.File == file.File)) - { - TapeFile removeMe = Files.FirstOrDefault(f => f.File == file.File); - Files.Remove(removeMe); - } - - Files.Add(file); - - return true; - } - - /// - public bool AddPartition(TapePartition partition) - { - if(TapePartitions.Any(f => f.Number == partition.Number)) - { - TapePartition removeMe = TapePartitions.FirstOrDefault(f => f.Number == partition.Number); - TapePartitions.Remove(removeMe); - } - - TapePartitions.Add(partition); - - return true; - } - - /// - public bool SetTape() - { - Files = []; - TapePartitions = []; - - return IsTape = true; - } - -#endregion -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Verify.cs b/Aaru.Images/AaruFormatOld/Verify.cs deleted file mode 100644 index daf720515..000000000 --- a/Aaru.Images/AaruFormatOld/Verify.cs +++ /dev/null @@ -1,336 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Verify.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Verifies Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// ****************************************************************************/ - -using System; -using System.Collections.Generic; -using Aaru.Checksums; -using Aaru.CommonTypes.Enums; -using Aaru.Helpers; -using Aaru.Logging; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ -#region IVerifiableImage Members - - /// - public bool? VerifyMediaImage() - { - // This will traverse all blocks and check their CRC64 without uncompressing them - AaruLogging.Debug(MODULE_NAME, Localization.Checking_index_integrity_at_0, _header.indexOffset); - - _imageStream.Position = (long)_header.indexOffset; - - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - IndexHeader idxHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(idxHeader.identifier != BlockType.Index) - { - AaruLogging.Debug(MODULE_NAME, Localization.Incorrect_index_identifier); - - return false; - } - - AaruLogging.Debug(MODULE_NAME, - Localization.Index_at_0_contains_1_entries, - _header.indexOffset, - idxHeader.entries); - - _structureBytes = new byte[Marshal.SizeOf() * idxHeader.entries]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] verifyCrc); - - if(BitConverter.ToUInt64(verifyCrc, 0) != idxHeader.crc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Expected_index_CRC_0_X16_but_got_1_X16, - idxHeader.crc64, - BitConverter.ToUInt64(verifyCrc, 0)); - - return false; - } - - _imageStream.Position -= _structureBytes.Length; - - List vrIndex = []; - - for(ushort i = 0; i < idxHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - IndexEntry entry = Marshal.SpanToStructureLittleEndian(_structureBytes); - - AaruLogging.Debug(MODULE_NAME, - Localization.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()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - BlockHeader blockHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - crcVerify = new Crc64Context(); - readBytes = 0; - - AaruLogging.Debug(MODULE_NAME, - Localization.Verifying_data_block_type_0_at_position_1, - entry.dataType, - entry.offset); - - while(readBytes + verifySize < blockHeader.cmpLength) - { - verifyBytes = new byte[verifySize]; - _imageStream.EnsureRead(verifyBytes, 0, verifyBytes.Length); - crcVerify.Update(verifyBytes); - readBytes += (ulong)verifyBytes.LongLength; - } - - verifyBytes = new byte[blockHeader.cmpLength - readBytes]; - _imageStream.EnsureRead(verifyBytes, 0, verifyBytes.Length); - crcVerify.Update(verifyBytes); - - verifyCrc = crcVerify.Final(); - - if(BitConverter.ToUInt64(verifyCrc, 0) != blockHeader.cmpCrc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.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()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - DdtHeader ddtHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - crcVerify = new Crc64Context(); - readBytes = 0; - - AaruLogging.Debug(MODULE_NAME, - Localization.Verifying_deduplication_table_type_0_at_position_1, - entry.dataType, - entry.offset); - - while(readBytes + verifySize < ddtHeader.cmpLength) - { - verifyBytes = new byte[verifySize]; - _imageStream.EnsureRead(verifyBytes, 0, verifyBytes.Length); - crcVerify.Update(verifyBytes); - readBytes += (ulong)verifyBytes.LongLength; - } - - verifyBytes = new byte[ddtHeader.cmpLength - readBytes]; - _imageStream.EnsureRead(verifyBytes, 0, verifyBytes.Length); - crcVerify.Update(verifyBytes); - - verifyCrc = crcVerify.Final(); - - if(BitConverter.ToUInt64(verifyCrc, 0) != ddtHeader.cmpCrc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Expected_DDT_CRC_0_but_got_1, - ddtHeader.cmpCrc64, - BitConverter.ToUInt64(verifyCrc, 0)); - - return false; - } - - break; - case BlockType.TracksBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - TracksHeader trkHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - AaruLogging.Debug(MODULE_NAME, - Localization.Track_block_at_0_contains_1_entries, - _header.indexOffset, - trkHeader.entries); - - _structureBytes = new byte[Marshal.SizeOf() * trkHeader.entries]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out verifyCrc); - - if(BitConverter.ToUInt64(verifyCrc, 0) != trkHeader.crc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Expected_index_CRC_0_X16_but_got_1_X16, - trkHeader.crc64, - BitConverter.ToUInt64(verifyCrc, 0)); - - return false; - } - - break; - default: - AaruLogging.Debug(MODULE_NAME, Localization.Ignored_field_type_0, entry.blockType); - - break; - } - } - - return true; - } - -#endregion - -#region IWritableOpticalImage Members - - /// - public bool? VerifySector(ulong sectorAddress) - { - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) return null; - - ErrorNumber errno = ReadSectorLong(sectorAddress, out byte[] buffer); - - return errno != ErrorNumber.NoError ? null : CdChecksums.CheckCdSector(buffer); - } - - /// - public bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, - out List unknownLbas) - { - failingLbas = []; - unknownLbas = []; - - // Right now only CompactDisc sectors are verifiable - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) - { - for(ulong i = sectorAddress; i < sectorAddress + length; i++) unknownLbas.Add(i); - - return null; - } - - ErrorNumber errno = ReadSectorsLong(sectorAddress, length, out byte[] buffer); - - if(errno != ErrorNumber.NoError) return null; - - int bps = (int)(buffer.Length / length); - byte[] sector = new byte[bps]; - failingLbas = []; - unknownLbas = []; - - for(int i = 0; i < length; i++) - { - Array.Copy(buffer, i * bps, sector, 0, bps); - bool? sectorStatus = CdChecksums.CheckCdSector(sector); - - switch(sectorStatus) - { - case null: - unknownLbas.Add((ulong)i + sectorAddress); - - break; - case false: - failingLbas.Add((ulong)i + sectorAddress); - - break; - } - } - - if(unknownLbas.Count > 0) return null; - - return failingLbas.Count <= 0; - } - - /// - public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, - out List unknownLbas) - { - // Right now only CompactDisc sectors are verifiable - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) - { - failingLbas = []; - unknownLbas = []; - - for(ulong i = sectorAddress; i < sectorAddress + length; i++) unknownLbas.Add(i); - - return null; - } - - failingLbas = []; - unknownLbas = []; - - ErrorNumber errno = ReadSectorsLong(sectorAddress, length, track, out byte[] buffer); - - if(errno != ErrorNumber.NoError) return null; - - int bps = (int)(buffer.Length / length); - byte[] sector = new byte[bps]; - - for(int i = 0; i < length; i++) - { - Array.Copy(buffer, i * bps, sector, 0, bps); - bool? sectorStatus = CdChecksums.CheckCdSector(sector); - - switch(sectorStatus) - { - case null: - unknownLbas.Add((ulong)i + sectorAddress); - - break; - case false: - failingLbas.Add((ulong)i + sectorAddress); - - break; - } - } - - if(unknownLbas.Count > 0) return null; - - return failingLbas.Count <= 0; - } - -#endregion -} \ No newline at end of file diff --git a/Aaru.Images/AaruFormatOld/Write.cs b/Aaru.Images/AaruFormatOld/Write.cs deleted file mode 100644 index f052cd9b4..000000000 --- a/Aaru.Images/AaruFormatOld/Write.cs +++ /dev/null @@ -1,5617 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Write.cs -// Author(s) : Natalia Portillo -// -// Component : Disk image plugins. -// -// --[ Description ] ---------------------------------------------------------- -// -// Writes Aaru Format disk images. -// -// --[ License ] -------------------------------------------------------------- -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2025 Natalia Portillo -// Copyright © 2020-2025 Rebecca Wallander -// ****************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using System.Xml; -using System.Xml.Serialization; -using Aaru.Checksums; -using Aaru.CommonTypes; -using Aaru.CommonTypes.AaruMetadata; -using Aaru.CommonTypes.Enums; -using Aaru.CommonTypes.Structs; -using Aaru.Compression; -using Aaru.Decoders; -using Aaru.Decoders.CD; -using Aaru.Helpers; -using Aaru.Logging; -using Humanizer; -using Schemas; -using Marshal = Aaru.Helpers.Marshal; -using Partition = Aaru.CommonTypes.Partition; -using Session = Aaru.CommonTypes.Structs.Session; -using TapeFile = Aaru.CommonTypes.Structs.TapeFile; -using TapePartition = Aaru.CommonTypes.Structs.TapePartition; -using Track = Aaru.CommonTypes.Structs.Track; -using TrackType = Aaru.CommonTypes.Enums.TrackType; - -namespace Aaru.Images; - -public sealed partial class AaruFormatOld -{ -#region IWritableOpticalImage Members - - /// - public bool Create(string path, MediaType mediaType, Dictionary options, ulong sectors, - uint sectorSize) - { - uint sectorsPerBlock; - uint maxDdtSize; - bool doMd5; - bool doSha1; - bool doSha256; - bool doSpamsum; - - if(options != null) - { - if(options.TryGetValue("sectors_per_block", out string tmpValue)) - { - if(!uint.TryParse(tmpValue, out sectorsPerBlock)) - { - ErrorMessage = Localization.Invalid_value_for_sectors_per_block_option; - - return false; - } - } - else - sectorsPerBlock = 4096; - - if(options.TryGetValue("dictionary", out tmpValue)) - { - if(!uint.TryParse(tmpValue, out _dictionarySize)) - { - ErrorMessage = Localization.Invalid_value_for_dictionary_option; - - return false; - } - } - else - _dictionarySize = 1 << 25; - - if(options.TryGetValue("max_ddt_size", out tmpValue)) - { - if(!uint.TryParse(tmpValue, out maxDdtSize)) - { - ErrorMessage = Localization.Invalid_value_for_max_ddt_size_option; - - return false; - } - } - else - maxDdtSize = 256; - - if(options.TryGetValue("md5", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out doMd5)) - { - ErrorMessage = Localization.Invalid_value_for_md5_option; - - return false; - } - } - else - doMd5 = true; - - if(options.TryGetValue("sha1", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out doSha1)) - { - ErrorMessage = Localization.Invalid_value_for_sha1_option; - - return false; - } - } - else - doSha1 = true; - - if(options.TryGetValue("sha256", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out doSha256)) - { - ErrorMessage = Localization.Invalid_value_for_sha256_option; - - return false; - } - } - else - doSha256 = true; - - if(options.TryGetValue("spamsum", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out doSpamsum)) - { - ErrorMessage = Localization.Invalid_value_for_spamsum_option; - - return false; - } - } - else - doSpamsum = false; - - if(options.TryGetValue("deduplicate", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out _deduplicate)) - { - ErrorMessage = Localization.Invalid_value_for_deduplicate_option; - - return false; - } - } - else - _deduplicate = true; - - if(options.TryGetValue("compress", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out _compress)) - { - ErrorMessage = Localization.Invalid_value_for_compress_option; - - return false; - } - } - else - _compress = true; - } - else - { - sectorsPerBlock = 4096; - _dictionarySize = 1 << 25; - maxDdtSize = 256; - doMd5 = true; - doSha1 = true; - doSha256 = true; - doSpamsum = false; - _deduplicate = true; - _compress = true; - } - - _compressionAlgorithm = _compress ? CompressionType.Lzma : CompressionType.None; - - // This really, cannot happen - if(!SupportedMediaTypes.Contains(mediaType)) - { - ErrorMessage = string.Format(Localization.Unsupported_media_format_0, mediaType); - - return false; - } - - // Calculate shift - _shift = 0; - uint oldSectorsPerBlock = sectorsPerBlock; - - while(sectorsPerBlock > 1) - { - sectorsPerBlock >>= 1; - _shift++; - } - - AaruLogging.Debug(MODULE_NAME, - Localization.Got_a_shift_of_0_for_1_sectors_per_block, - _shift, - oldSectorsPerBlock); - - _imageInfo = new ImageInfo - { - MediaType = mediaType, - SectorSize = sectorSize, - Sectors = sectors, - MetadataMediaType = GetMetadataMediaType(mediaType) - }; - - try - { - _imageStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); - } - catch(IOException ex) - { - ErrorMessage = string.Format(Localization.Could_not_create_new_image_file_exception_0, ex.Message); - AaruLogging.Exception(ex, Localization.Could_not_create_new_image_file_exception_0, ex.Message); - - return false; - } - - // Check if appending to an existing image - if(_imageStream.Length > Marshal.SizeOf()) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - _header = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - if(_header.identifier != DIC_MAGIC && _header.identifier != AARU_MAGIC) - { - ErrorMessage = Localization.Cannot_append_to_a_non_Aaru_Format_image; - - return false; - } - - if(_header.imageMajorVersion > AARUFMT_VERSION) - { - ErrorMessage = string.Format(Localization.Cannot_append_to_an_unknown_image_version_0, - _header.imageMajorVersion); - - return false; - } - - if(_header.mediaType != mediaType) - { - ErrorMessage = string.Format(Localization.Cannot_write_a_media_with_type_0_to_an_image_with_type_1, - mediaType, - _header.mediaType); - - return false; - } - } - else - { - _header = new AaruHeader - { - identifier = AARU_MAGIC, - mediaType = mediaType, - creationTime = DateTime.UtcNow.ToFileTimeUtc() - }; - - _imageStream.Write(new byte[Marshal.SizeOf()], 0, Marshal.SizeOf()); - } - - _header.application = "Aaru"; - _header.imageMajorVersion = AARUFMT_VERSION_V1; - _header.imageMinorVersion = 0; - _header.applicationMajorVersion = (byte)typeof(AaruFormatOld).Assembly.GetName().Version.Major; - _header.applicationMinorVersion = (byte)typeof(AaruFormatOld).Assembly.GetName().Version.Minor; - - // Initialize tables - _index = []; - _mediaTags = new Dictionary(); - _checksumProvider = SHA256.Create(); - _deduplicationTable = new Dictionary(); - _trackIsrcs = new Dictionary(); - _trackFlags = new Dictionary(); - _imageInfo.ReadableSectorTags = []; - - // If there exists an index, we are appending, so read index - if(_header.indexOffset > 0) - { - List compactDiscIndexes = null; - - // Initialize caches - _blockCache = new Dictionary(); - _blockHeaderCache = new Dictionary(); - _currentCacheSize = 0; - - // Can't calculate checksum of an appended image - _md5Provider = null; - _sha1Provider = null; - _sha256Provider = null; - _spamsumProvider = null; - - _imageStream.Position = (long)_header.indexOffset; - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - IndexHeader idxHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(idxHeader.identifier != BlockType.Index) - { - ErrorMessage = Localization.Index_not_found_in_existing_image_cannot_continue; - - return false; - } - - AaruLogging.Debug(MODULE_NAME, - Localization.Index_at_0_contains_1_entries, - _header.indexOffset, - idxHeader.entries); - - for(ushort i = 0; i < idxHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - IndexEntry entry = Marshal.SpanToStructureLittleEndian(_structureBytes); - - AaruLogging.Debug(MODULE_NAME, - Localization.Block_type_0_with_data_type_1_is_indexed_to_be_at_2, - entry.blockType, - entry.dataType, - entry.offset); - - _index.Add(entry); - } - - // Invalidate previous checksum block - _index.RemoveAll(t => t is { blockType: BlockType.ChecksumBlock, dataType: DataType.NoData }); - - bool foundUserDataDdt = false; - - foreach(IndexEntry entry in _index) - { - _imageStream.Position = (long)entry.offset; - - switch(entry.blockType) - { - case BlockType.DataBlock: - // NOP block, skip - if(entry.dataType == DataType.NoData) break; - - _imageStream.Position = (long)entry.offset; - - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - BlockHeader blockHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - _imageInfo.ImageSize += blockHeader.cmpLength; - - // Unused, skip - if(entry.dataType == DataType.UserData) break; - - if(blockHeader.identifier != entry.blockType) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_identifier_for_data_block_at_position_0, - entry.offset); - - break; - } - - if(blockHeader.type != entry.dataType) - { - AaruLogging.Debug(MODULE_NAME, - Localization - .Expected_block_with_data_type_0_at_position_1_but_found_data_type_2, - entry.dataType, - entry.offset, - blockHeader.type); - - break; - } - - byte[] data; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_data_block_type_0_at_position_1, - entry.dataType, - entry.offset); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - // Decompress media tag - if(blockHeader.compression is CompressionType.Lzma - or CompressionType.LzmaClauniaSubchannelTransform) - { - if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform && - entry.dataType != DataType.CdSectorSubchannel) - { - AaruLogging.Debug(MODULE_NAME, - Localization - .Invalid_compression_type_0_for_block_with_data_type_1_continuing, - blockHeader.compression, - entry.dataType); - - break; - } - - var decompressStopwatch = new Stopwatch(); - decompressStopwatch.Restart(); - byte[] compressedTag = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.EnsureRead(compressedTag, 0, compressedTag.Length); - data = new byte[blockHeader.length]; - int decompressedLength = LZMA.DecodeBuffer(compressedTag, data, lzmaProperties); - - if(decompressedLength != blockHeader.length) - { - ErrorMessage = - string.Format(Localization - .Error_decompressing_block_should_be_0_bytes_but_got_1_bytes, - blockHeader.length, - decompressedLength); - - return false; - } - - if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform) - data = ClauniaSubchannelUntransform(data); - - decompressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_decompress_block, - decompressStopwatch.Elapsed.TotalSeconds); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - } - else if(blockHeader.compression == CompressionType.None) - { - data = new byte[blockHeader.length]; - _imageStream.EnsureRead(data, 0, (int)blockHeader.length); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - } - else - { - AaruLogging.Debug(MODULE_NAME, - Localization.Found_unknown_compression_type_0_continuing, - (ushort)blockHeader.compression); - - break; - } - - // Check CRC, if not correct, skip it - Crc64Context.Data(data, out byte[] blockCrc); - - if(BitConverter.ToUInt64(blockCrc, 0) != blockHeader.crc64 && blockHeader.crc64 != 0) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_CRC_found_0_X16_found_expected_1_X16_continuing, - BitConverter.ToUInt64(blockCrc, 0), - blockHeader.crc64); - - break; - } - - // Check if it's not a media tag, but a sector tag, and fill the appropriate table then - switch(entry.dataType) - { - case DataType.CdSectorPrefix: - case DataType.CdSectorPrefixCorrected: - if(entry.dataType == DataType.CdSectorPrefixCorrected) - { - _sectorPrefixMs = new MemoryStream(); - _sectorPrefixMs.Write(data, 0, data.Length); - } - else - _sectorPrefix = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.CdSectorSuffix: - case DataType.CdSectorSuffixCorrected: - if(entry.dataType == DataType.CdSectorSuffixCorrected) - { - _sectorSuffixMs = new MemoryStream(); - _sectorSuffixMs.Write(data, 0, data.Length); - } - else - _sectorSuffix = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.CdSectorSubchannel: - _sectorSubchannel = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.AppleProfileTag: - case DataType.AppleSonyTag: - case DataType.PriamDataTowerTag: - _sectorSubchannel = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.CompactDiscMode2Subheader: - _mode2Subheaders = data; - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorCprMai: - _sectorCprMai = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorCmi)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorCmi); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorTitleKey)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorTitleKey); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorTitleKeyDecrypted: - _sectorDecryptedTitleKey = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdTitleKeyDecrypted)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdTitleKeyDecrypted); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorId: - _sectorId = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorInformation)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorInformation); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorNumber)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorNumber); - - AaruLogging.Debug("Aaru Format plugin", - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorIed: - _sectorIed = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorIed)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorIed); - - AaruLogging.Debug("Aaru Format plugin", - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorEdc: - _sectorEdc = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorEdc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorEdc); - - AaruLogging.Debug("Aaru Format plugin", - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - default: - MediaTagType mediaTagType = GetMediaTagTypeForDataType(blockHeader.type); - - if(_mediaTags.ContainsKey(mediaTagType)) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Media_tag_type_0_duplicated_removing_previous_entry, - mediaTagType); - - _mediaTags.Remove(mediaTagType); - } - - _mediaTags.Add(mediaTagType, data); - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - - break; - } - - break; - case BlockType.DeDuplicationTable: - // Only user data deduplication tables are used right now - if(entry.dataType == DataType.UserData) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - DdtHeader ddtHeader = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - if(ddtHeader.identifier != BlockType.DeDuplicationTable) break; - - if(ddtHeader.entries != _imageInfo.Sectors && !IsTape) - { - ErrorMessage = - string.Format(Localization - .Trying_to_write_a_media_with_0_sectors_to_an_image_with_1_sectors_not_continuing, - _imageInfo.Sectors, - ddtHeader.entries); - - return false; - } - - _shift = ddtHeader.shift; - - switch(ddtHeader.compression) - { - case CompressionType.Lzma: - AaruLogging.Debug(MODULE_NAME, Localization.Decompressing_DDT); - - var ddtStopwatch = new Stopwatch(); - ddtStopwatch.Start(); - - byte[] compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.EnsureRead(compressedDdt, 0, compressedDdt.Length); - byte[] decompressedDdt = new byte[ddtHeader.length]; - - ulong decompressedLength = - (ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties); - - if(decompressedLength != ddtHeader.length) - { - ErrorMessage = - string.Format(Localization - .Error_decompressing_DDT_should_be_0_bytes_but_got_1_bytes, - ddtHeader.length, - decompressedLength); - - return false; - } - - _userDataDdt = MemoryMarshal.Cast(decompressedDdt).ToArray(); - ddtStopwatch.Stop(); - _inMemoryDdt = true; - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_decompress_DDT, - ddtStopwatch.Elapsed.TotalSeconds); - - break; - case CompressionType.None: - _inMemoryDdt = false; - _outMemoryDdtPosition = (long)entry.offset; - - break; - default: - ErrorMessage = string.Format(Localization.Found_unsupported_compression_algorithm_0, - (ushort)ddtHeader.compression); - - return false; - } - - if(IsTape) - { - _tapeDdt = new Dictionary(); - - for(long i = 0; i < _userDataDdt.LongLength; i++) - _tapeDdt.Add((ulong)i, _userDataDdt[i]); - - _userDataDdt = null; - } - - foundUserDataDdt = true; - } - else if(entry.dataType is DataType.CdSectorPrefixCorrected or DataType.CdSectorSuffixCorrected) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - DdtHeader ddtHeader = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - if(ddtHeader.identifier != BlockType.DeDuplicationTable) break; - - if(ddtHeader.entries != _imageInfo.Sectors) - { - ErrorMessage = - string.Format(Localization - .Trying_to_write_a_media_with_0_sectors_to_an_image_with_1_sectors_not_continuing, - _imageInfo.Sectors, - ddtHeader.entries); - - return false; - } - - byte[] decompressedDdt = new byte[ddtHeader.length]; - - switch(ddtHeader.compression) - { - case CompressionType.Lzma: - AaruLogging.Debug(MODULE_NAME, Localization.Decompressing_DDT); - - var ddtStopwatch = new Stopwatch(); - ddtStopwatch.Start(); - - byte[] compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.EnsureRead(compressedDdt, 0, compressedDdt.Length); - - ulong decompressedLength = - (ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties); - - if(decompressedLength != ddtHeader.length) - { - ErrorMessage = - string.Format(Localization - .Error_decompressing_DDT_should_be_0_bytes_but_got_1_bytes, - ddtHeader.length, - decompressedLength); - - return false; - } - - ddtStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_decompress_DDT, - ddtStopwatch.Elapsed.TotalSeconds); - - break; - case CompressionType.None: - _imageStream.EnsureRead(decompressedDdt, 0, decompressedDdt.Length); - - break; - default: - ErrorMessage = string.Format(Localization.Found_unsupported_compression_algorithm_0, - (ushort)ddtHeader.compression); - - return false; - } - - uint[] cdDdt = MemoryMarshal.Cast(decompressedDdt).ToArray(); - - switch(entry.dataType) - { - case DataType.CdSectorPrefixCorrected: - _sectorPrefixDdt = cdDdt; - - break; - case DataType.CdSectorSuffixCorrected: - _sectorSuffixDdt = cdDdt; - - break; - } - } - - break; - - // Logical geometry block. It doesn't have a CRC coz, well, it's not so important - case BlockType.GeometryBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - _geometryBlock = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(_geometryBlock.identifier == BlockType.GeometryBlock) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Geometry_set_to_0_cylinders_1_heads_2_sectors_per_track, - _geometryBlock.cylinders, - _geometryBlock.heads, - _geometryBlock.sectorsPerTrack); - - _imageInfo.Cylinders = _geometryBlock.cylinders; - _imageInfo.Heads = _geometryBlock.heads; - _imageInfo.SectorsPerTrack = _geometryBlock.sectorsPerTrack; - - AaruLogging.Debug(MODULE_NAME, - Localization.Memory_snapshot_0_bytes, - GC.GetTotalMemory(false)); - } - - break; - - // Metadata block - case BlockType.MetadataBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - MetadataBlock metadataBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(metadataBlock.identifier != entry.blockType) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_identifier_for_data_block_at_position_0, - entry.offset); - - break; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Found_metadata_block_at_position_0, entry.offset); - - byte[] metadata = new byte[metadataBlock.blockSize]; - _imageStream.Position = (long)entry.offset; - _imageStream.EnsureRead(metadata, 0, metadata.Length); - - if(metadataBlock is { mediaSequence: > 0, lastMediaSequence: > 0 }) - { - _imageInfo.MediaSequence = metadataBlock.mediaSequence; - _imageInfo.LastMediaSequence = metadataBlock.lastMediaSequence; - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_sequence_as_0_of_1, - _imageInfo.MediaSequence, - _imageInfo.LastMediaSequence); - } - - if(metadataBlock.creatorLength > 0 && - metadataBlock.creatorLength + metadataBlock.creatorOffset <= metadata.Length) - { - _imageInfo.Creator = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.creatorOffset, - (int)(metadataBlock.creatorLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_creator_0, _imageInfo.Creator); - } - - if(metadataBlock.commentsOffset > 0 && - metadataBlock.commentsLength + metadataBlock.commentsOffset <= metadata.Length) - { - _imageInfo.Comments = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.commentsOffset, - (int)(metadataBlock.commentsLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_comments_0, _imageInfo.Comments); - } - - if(metadataBlock.mediaTitleOffset > 0 && - metadataBlock.mediaTitleLength + metadataBlock.mediaTitleOffset <= metadata.Length) - { - _imageInfo.MediaTitle = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaTitleOffset, - (int)(metadataBlock.mediaTitleLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_media_title_0, _imageInfo.MediaTitle); - } - - if(metadataBlock.mediaManufacturerOffset > 0 && - metadataBlock.mediaManufacturerLength + metadataBlock.mediaManufacturerOffset <= - metadata.Length) - { - _imageInfo.MediaManufacturer = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaManufacturerOffset, - (int)(metadataBlock.mediaManufacturerLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_manufacturer_0, - _imageInfo.MediaManufacturer); - } - - if(metadataBlock.mediaModelOffset > 0 && - metadataBlock.mediaModelLength + metadataBlock.mediaModelOffset <= metadata.Length) - { - _imageInfo.MediaModel = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaModelOffset, - (int)(metadataBlock.mediaModelLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_media_model_0, _imageInfo.MediaModel); - } - - if(metadataBlock.mediaSerialNumberOffset > 0 && - metadataBlock.mediaSerialNumberLength + metadataBlock.mediaSerialNumberOffset <= - metadata.Length) - { - _imageInfo.MediaSerialNumber = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaSerialNumberOffset, - (int)(metadataBlock.mediaSerialNumberLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_serial_number_0, - _imageInfo.MediaSerialNumber); - } - - if(metadataBlock.mediaBarcodeOffset > 0 && - metadataBlock.mediaBarcodeLength + metadataBlock.mediaBarcodeOffset <= metadata.Length) - { - _imageInfo.MediaBarcode = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaBarcodeOffset, - (int)(metadataBlock.mediaBarcodeLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_barcode_0, - _imageInfo.MediaBarcode); - } - - if(metadataBlock.mediaPartNumberOffset > 0 && - metadataBlock.mediaPartNumberLength + metadataBlock.mediaPartNumberOffset <= metadata.Length) - { - _imageInfo.MediaPartNumber = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.mediaPartNumberOffset, - (int)(metadataBlock.mediaPartNumberLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_media_part_number_0, - _imageInfo.MediaPartNumber); - } - - if(metadataBlock.driveManufacturerOffset > 0 && - metadataBlock.driveManufacturerLength + metadataBlock.driveManufacturerOffset <= - metadata.Length) - { - _imageInfo.DriveManufacturer = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.driveManufacturerOffset, - (int)(metadataBlock.driveManufacturerLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_drive_manufacturer_0, - _imageInfo.DriveManufacturer); - } - - if(metadataBlock.driveModelOffset > 0 && - metadataBlock.driveModelLength + metadataBlock.driveModelOffset <= metadata.Length) - { - _imageInfo.DriveModel = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.driveModelOffset, - (int)(metadataBlock.driveModelLength - 2)); - - AaruLogging.Debug(MODULE_NAME, Localization.Setting_drive_model_0, _imageInfo.DriveModel); - } - - if(metadataBlock.driveSerialNumberOffset > 0 && - metadataBlock.driveSerialNumberLength + metadataBlock.driveSerialNumberOffset <= - metadata.Length) - { - _imageInfo.DriveSerialNumber = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.driveSerialNumberOffset, - (int)(metadataBlock.driveSerialNumberLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_drive_serial_number_0, - _imageInfo.DriveSerialNumber); - } - - if(metadataBlock.driveFirmwareRevisionOffset > 0 && - metadataBlock.driveFirmwareRevisionLength + metadataBlock.driveFirmwareRevisionOffset <= - metadata.Length) - { - _imageInfo.DriveFirmwareRevision = - Encoding.Unicode.GetString(metadata, - (int)metadataBlock.driveFirmwareRevisionOffset, - (int)(metadataBlock.driveFirmwareRevisionLength - 2)); - - AaruLogging.Debug(MODULE_NAME, - Localization.Setting_drive_firmware_revision_0, - _imageInfo.DriveFirmwareRevision); - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - - // Optical disc tracks block - case BlockType.TracksBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - TracksHeader tracksHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(tracksHeader.identifier != BlockType.TracksBlock) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_identifier_for_tracks_block_at_position_0, - entry.offset); - - break; - } - - _structureBytes = new byte[Marshal.SizeOf() * tracksHeader.entries]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] trksCrc); - - if(BitConverter.ToUInt64(trksCrc, 0) != tracksHeader.crc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_CRC_found_0_X16_found_expected_1_X16_continuing, - BitConverter.ToUInt64(trksCrc, 0), - tracksHeader.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - Tracks = []; - _trackFlags = new Dictionary(); - _trackIsrcs = new Dictionary(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_0_tracks_at_position_1, - tracksHeader.entries, - entry.offset); - - for(ushort i = 0; i < tracksHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - TrackEntry trackEntry = - Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - Tracks.Add(new Track - { - Sequence = trackEntry.sequence, - Type = trackEntry.type, - StartSector = (ulong)trackEntry.start, - EndSector = (ulong)trackEntry.end, - Pregap = (ulong)trackEntry.pregap, - Session = trackEntry.session, - FileType = "BINARY" - }); - - if(trackEntry.type == TrackType.Data) continue; - - _trackFlags.Add(trackEntry.sequence, trackEntry.flags); - - if(!string.IsNullOrEmpty(trackEntry.isrc)) - _trackIsrcs.Add(trackEntry.sequence, trackEntry.isrc); - } - - if(_trackFlags.Count > 0 && !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackFlags)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); - - if(_trackIsrcs.Count > 0 && !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc); - - _imageInfo.HasPartitions = true; - _imageInfo.HasSessions = true; - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - - // CICM XML metadata block - case BlockType.CicmBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - CicmMetadataBlock cicmBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(cicmBlock.identifier != BlockType.CicmBlock) break; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_CICM_XML_metadata_block_at_position_0, - entry.offset); - - byte[] cicmBytes = new byte[cicmBlock.length]; - _imageStream.EnsureRead(cicmBytes, 0, cicmBytes.Length); - var cicmMs = new MemoryStream(cicmBytes); - - // The converter to AaruMetadata basically overcomes this (should?) -#pragma warning disable IL2026 - var cicmXs = new XmlSerializer(typeof(CICMMetadataType)); -#pragma warning restore IL2026 - - try - { - var sr = new StreamReader(cicmMs); - - // The converter to AaruMetadata basically overcomes this (should?) -#pragma warning disable IL2026 - AaruMetadata = (CICMMetadataType)cicmXs.Deserialize(sr); -#pragma warning restore IL2026 - sr.Close(); - } - catch(XmlException ex) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Exception_0_processing_CICM_XML_metadata_block, - ex.Message); - - AaruLogging.Exception(ex, - Localization.Exception_0_processing_CICM_XML_metadata_block, - ex.Message); - - AaruMetadata = null; - } - - break; - - // Aaru Metadata JSON block - case BlockType.AaruMetadataJsonBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - AaruMetadataJsonBlock aaruMetadataBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(aaruMetadataBlock.identifier != BlockType.AaruMetadataJsonBlock) break; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_Aaru_Metadata_block_at_position_0, - entry.offset); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - byte[] jsonBytes = new byte[aaruMetadataBlock.length]; - _imageStream.EnsureRead(jsonBytes, 0, jsonBytes.Length); - - try - { - AaruMetadata = - (JsonSerializer.Deserialize(jsonBytes, - typeof(MetadataJson), - MetadataJsonContext.Default) as MetadataJson)?.AaruMetadata; - } - catch(JsonException ex) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Exception_0_processing_Aaru_Metadata_block, - ex.Message); - - AaruMetadata = null; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - - // Dump hardware block - case BlockType.DumpHardwareBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - DumpHardwareHeader dumpBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(dumpBlock.identifier != BlockType.DumpHardwareBlock) break; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_dump_hardware_block_at_position_0, - entry.offset); - - _structureBytes = new byte[dumpBlock.length]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] dumpCrc); - - if(BitConverter.ToUInt64(dumpCrc, 0) != dumpBlock.crc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_CRC_found_0_X16_found_expected_1_X16_continuing, - BitConverter.ToUInt64(dumpCrc, 0), - dumpBlock.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - DumpHardware = []; - - for(ushort i = 0; i < dumpBlock.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - DumpHardwareEntry dumpEntry = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - var dump = new DumpHardware - { - Software = new Software(), - Extents = [] - }; - - byte[] tmp; - - if(dumpEntry.manufacturerLength > 0) - { - tmp = new byte[dumpEntry.manufacturerLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Manufacturer = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.modelLength > 0) - { - tmp = new byte[dumpEntry.modelLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Model = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.revisionLength > 0) - { - tmp = new byte[dumpEntry.revisionLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Revision = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.firmwareLength > 0) - { - tmp = new byte[dumpEntry.firmwareLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Firmware = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.serialLength > 0) - { - tmp = new byte[dumpEntry.serialLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Serial = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareNameLength > 0) - { - tmp = new byte[dumpEntry.softwareNameLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Software.Name = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareVersionLength > 0) - { - tmp = new byte[dumpEntry.softwareVersionLength - 1]; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Software.Version = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareOperatingSystemLength > 0) - { - tmp = new byte[dumpEntry.softwareOperatingSystemLength - 1]; - _imageStream.Position += 1; - _imageStream.EnsureRead(tmp, 0, tmp.Length); - dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp); - } - - tmp = new byte[16]; - - for(uint j = 0; j < dumpEntry.extents; j++) - { - _imageStream.EnsureRead(tmp, 0, tmp.Length); - - dump.Extents.Add(new Extent - { - Start = BitConverter.ToUInt64(tmp, 0), - End = BitConverter.ToUInt64(tmp, 8) - }); - } - - dump.Extents = dump.Extents.OrderBy(t => t.Start).ToList(); - - if(dump.Extents.Count > 0) DumpHardware.Add(dump); - } - - if(DumpHardware.Count == 0) DumpHardware = null; - - break; - - // Tape partition block - case BlockType.TapePartitionBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - TapePartitionHeader partitionHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(partitionHeader.identifier != BlockType.TapePartitionBlock) break; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_tape_partition_block_at_position_0, - entry.offset); - - byte[] tapePartitionBytes = new byte[partitionHeader.length]; - _imageStream.EnsureRead(tapePartitionBytes, 0, tapePartitionBytes.Length); - - ReadOnlySpan tapePartitions = - MemoryMarshal.Cast(tapePartitionBytes); - - TapePartitions = []; - - foreach(TapePartitionEntry tapePartition in tapePartitions) - { - TapePartitions.Add(new TapePartition - { - FirstBlock = tapePartition.FirstBlock, - LastBlock = tapePartition.LastBlock, - Number = tapePartition.Number - }); - } - - IsTape = true; - - break; - - // Tape file block - case BlockType.TapeFileBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - TapeFileHeader fileHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(fileHeader.identifier != BlockType.TapeFileBlock) break; - - AaruLogging.Debug(MODULE_NAME, Localization.Found_tape_file_block_at_position_0, entry.offset); - - byte[] tapeFileBytes = new byte[fileHeader.length]; - _imageStream.EnsureRead(tapeFileBytes, 0, tapeFileBytes.Length); - ReadOnlySpan tapeFiles = MemoryMarshal.Cast(tapeFileBytes); - Files = []; - - foreach(TapeFileEntry file in tapeFiles) - { - Files.Add(new TapeFile - { - FirstBlock = file.FirstBlock, - LastBlock = file.LastBlock, - Partition = file.Partition, - File = file.File - }); - } - - IsTape = true; - - break; - - // Optical disc tracks block - case BlockType.CompactDiscIndexesBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - CompactDiscIndexesHeader indexesHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(indexesHeader.identifier != BlockType.CompactDiscIndexesBlock) - { - AaruLogging.Debug(MODULE_NAME, - Localization - .Incorrect_identifier_for_compact_disc_indexes_block_at_position_0, - entry.offset); - - break; - } - - _structureBytes = new byte[Marshal.SizeOf() * indexesHeader.entries]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] idsxCrc); - - if(BitConverter.ToUInt64(idsxCrc, 0) != indexesHeader.crc64) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Incorrect_CRC_found_0_X16_found_expected_1_X16_continuing, - BitConverter.ToUInt64(idsxCrc, 0), - indexesHeader.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - compactDiscIndexes = []; - - AaruLogging.Debug(MODULE_NAME, - Localization.Found_0_compact_disc_indexes_at_position_1, - indexesHeader.entries, - entry.offset); - - for(ushort i = 0; i < indexesHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.EnsureRead(_structureBytes, 0, _structureBytes.Length); - - compactDiscIndexes.Add(Marshal - .ByteArrayToStructureLittleEndian< - CompactDiscIndexEntry>(_structureBytes)); - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - break; - } - } - - if(!foundUserDataDdt) - { - ErrorMessage = Localization.Could_not_find_user_data_deduplication_table; - - return false; - } - - if(_sectorSuffixMs == null || - _sectorSuffixDdt == null || - _sectorPrefixMs == null || - _sectorPrefixDdt == null) - { - _sectorSuffixMs = null; - _sectorSuffixDdt = null; - _sectorPrefixMs = null; - _sectorPrefixDdt = null; - } - - if(!_inMemoryDdt) _ddtEntryCache = new Dictionary(); - - // Initialize tracks, sessions and partitions - if(_imageInfo.MetadataMediaType == MetadataMediaType.OpticalDisc) - { - if(Tracks != null && _mediaTags.TryGetValue(MediaTagType.CD_FullTOC, out byte[] fullToc)) - { - byte[] tmp = new byte[fullToc.Length + 2]; - Array.Copy(fullToc, 0, tmp, 2, fullToc.Length); - tmp[0] = (byte)(fullToc.Length >> 8); - tmp[1] = (byte)(fullToc.Length & 0xFF); - - FullTOC.CDFullTOC? decodedFullToc = FullTOC.Decode(tmp); - - if(decodedFullToc.HasValue) - { - Dictionary leadOutStarts = new(); // Lead-out starts - - foreach(FullTOC.TrackDataDescriptor trk in - decodedFullToc.Value.TrackDescriptors.Where(trk => trk.ADR is 1 or 4 && - trk.POINT == 0xA2)) - { - int phour, pmin, psec, pframe; - - if(trk.PFRAME == 0) - { - pframe = 74; - - if(trk.PSEC == 0) - { - psec = 59; - - if(trk.PMIN == 0) - { - pmin = 59; - phour = trk.PHOUR - 1; - } - else - { - pmin = trk.PMIN - 1; - phour = trk.PHOUR; - } - } - else - { - psec = trk.PSEC - 1; - pmin = trk.PMIN; - phour = trk.PHOUR; - } - } - else - { - pframe = trk.PFRAME - 1; - psec = trk.PSEC; - pmin = trk.PMIN; - phour = trk.PHOUR; - } - - int lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150; - leadOutStarts?.Add(trk.SessionNumber, lastSector + 1); - } - - foreach(KeyValuePair leadOuts in leadOutStarts) - { - var lastTrackInSession = new Track(); - - foreach(Track trk in Tracks.Where(trk => trk.Session == leadOuts.Key) - .Where(trk => trk.Sequence > lastTrackInSession.Sequence)) - lastTrackInSession = trk; - - if(lastTrackInSession.Sequence == 0 || - lastTrackInSession.EndSector == (ulong)leadOuts.Value - 1) - continue; - - lastTrackInSession.EndSector = (ulong)leadOuts.Value - 1; - } - } - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - if(Tracks == null || Tracks.Count == 0) - { - Tracks = - [ - new Track - { - BytesPerSector = (int)_imageInfo.SectorSize, - EndSector = _imageInfo.Sectors - 1, - FileType = "BINARY", - RawBytesPerSector = (int)_imageInfo.SectorSize, - Session = 1, - Sequence = 1, - Type = TrackType.Data - } - ]; - - _trackFlags = new Dictionary - { - { - 1, (byte)CdFlags.DataTrack - } - }; - - _trackIsrcs = new Dictionary(); - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - Sessions = []; - - for(int i = 1; i <= Tracks.Max(t => t.Session); i++) - { - Sessions.Add(new Session - { - Sequence = (ushort)i, - StartTrack = Tracks.Where(t => t.Session == i).Min(t => t.Sequence), - EndTrack = Tracks.Where(t => t.Session == i).Max(t => t.Sequence), - StartSector = Tracks.Where(t => t.Session == i).Min(t => t.StartSector), - EndSector = Tracks.Where(t => t.Session == i).Max(t => t.EndSector) - }); - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - foreach(Track track in Tracks.OrderBy(t => t.StartSector)) - { - if(track.Sequence == 1) - { - track.Pregap = 150; - track.Indexes[0] = -150; - track.Indexes[1] = (int)track.StartSector; - - continue; - } - - if(track.Pregap > 0) - { - track.Indexes[0] = (int)track.StartSector; - track.Indexes[1] = (int)(track.StartSector + track.Pregap); - } - else - track.Indexes[1] = (int)track.StartSector; - } - - ulong currentTrackOffset = 0; - Partitions = []; - - foreach(Track track in Tracks.OrderBy(t => t.StartSector)) - { - Partitions.Add(new Partition - { - Sequence = track.Sequence, - Type = track.Type.Humanize(), - Name = string.Format(Localization.Track_0, track.Sequence), - Offset = currentTrackOffset, - Start = (ulong)track.Indexes[1], - Size = (track.EndSector - (ulong)track.Indexes[1] + 1) * (ulong)track.BytesPerSector, - Length = track.EndSector - (ulong)track.Indexes[1] + 1, - Scheme = Localization.Optical_disc_track - }); - - currentTrackOffset += (track.EndSector - track.StartSector + 1) * (ulong)track.BytesPerSector; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - Track[] tracks = Tracks.ToArray(); - - foreach(Track trk in tracks) - { - ErrorNumber errno = ReadSector(trk.StartSector, out byte[] sector); - - if(errno != ErrorNumber.NoError) continue; - - trk.BytesPerSector = sector.Length; - - trk.RawBytesPerSector = - _sectorPrefix != null && _sectorSuffix != null || - _sectorPrefixDdt != null && _sectorSuffixDdt != null - ? 2352 - : sector.Length; - - if(_sectorSubchannel == null) continue; - - trk.SubchannelFile = trk.File; - trk.SubchannelFilter = trk.Filter; - trk.SubchannelType = TrackSubchannelType.Raw; - } - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - Tracks = tracks.ToList(); - - AaruLogging.Debug(MODULE_NAME, Localization.Memory_snapshot_0_bytes, GC.GetTotalMemory(false)); - - if(compactDiscIndexes != null) - { - foreach(CompactDiscIndexEntry compactDiscIndex in compactDiscIndexes.OrderBy(i => i.Track) - .ThenBy(i => i.Index)) - { - Track track = Tracks.FirstOrDefault(t => t.Sequence == compactDiscIndex.Track); - - if(track is null) continue; - - track.Indexes[compactDiscIndex.Index] = compactDiscIndex.Lba; - } - } - } - else - { - Tracks = null; - Sessions = null; - Partitions = null; - } - } - - // Creating new - else - { - // Checking that DDT is smaller than requested size - _inMemoryDdt = sectors <= maxDdtSize * 1024 * 1024 / sizeof(ulong); - - // If in memory, easy - if(_inMemoryDdt) - { - if(IsTape) - _tapeDdt = new Dictionary(); - else - _userDataDdt = new ulong[sectors]; - } - - // If not, create the block, add to index, and enlarge the file to allow the DDT to exist on-disk - else - { - _outMemoryDdtPosition = _imageStream.Position; - - _index.Add(new IndexEntry - { - blockType = BlockType.DeDuplicationTable, - dataType = DataType.UserData, - offset = (ulong)_outMemoryDdtPosition - }); - - // CRC64 will be calculated later - var ddtHeader = new DdtHeader - { - identifier = BlockType.DeDuplicationTable, - type = DataType.UserData, - compression = CompressionType.None, - shift = _shift, - entries = sectors, - cmpLength = sectors * sizeof(ulong), - length = sectors * sizeof(ulong) - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in ddtHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - _imageStream.Position += (long)(sectors * sizeof(ulong)) - 1; - _imageStream.WriteByte(0); - } - - if(doMd5) _md5Provider = new Md5Context(); - - if(doSha1) _sha1Provider = new Sha1Context(); - - if(doSha256) _sha256Provider = new Sha256Context(); - - if(doSpamsum) _spamsumProvider = new SpamSumContext(); - } - - AaruLogging.Debug(MODULE_NAME, Localization.In_memory_DDT_0, _inMemoryDdt); - - _imageStream.Seek(0, SeekOrigin.End); - - IsWriting = true; - ErrorMessage = null; - - return true; - } - - /// - public bool WriteMediaTag(byte[] data, MediaTagType tag) - { - if(!IsWriting) - { - ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image; - - return false; - } - - if(_mediaTags.ContainsKey(tag)) _mediaTags.Remove(tag); - - _mediaTags.Add(tag, data); - - ErrorMessage = ""; - - return true; - } - - /// - public bool WriteSector(byte[] data, ulong sectorAddress) - { - if(!IsWriting) - { - ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image; - - return false; - } - - if(sectorAddress >= Info.Sectors && !IsTape) - { - ErrorMessage = Localization.Tried_to_write_past_image_size; - - return false; - } - - if((_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc || !_writingLong) && !_rewinded) - { - if(sectorAddress <= _lastWrittenBlock && _alreadyWrittenZero) - { - _rewinded = true; - _md5Provider = null; - _sha1Provider = null; - _sha256Provider = null; - _spamsumProvider = null; - } - - _md5Provider?.Update(data); - _sha1Provider?.Update(data); - _sha256Provider?.Update(data); - _spamsumProvider?.Update(data); - _lastWrittenBlock = sectorAddress; - } - - if(sectorAddress == 0) _alreadyWrittenZero = true; - - byte[] hash = null; - _writtenSectors++; - - // Compute hash only if asked to deduplicate, or the sector is empty (those will always be deduplicated) - if(_deduplicate || ArrayHelpers.ArrayIsNullOrEmpty(data)) hash = _checksumProvider.ComputeHash(data); - - string hashString = null; - - if(hash != null) - { - var hashSb = new StringBuilder(); - - foreach(byte h in hash) hashSb.Append(h.ToString("x2")); - - hashString = hashSb.ToString(); - - if(_deduplicationTable.TryGetValue(hashString, out ulong pointer)) - { - SetDdtEntry(sectorAddress, pointer); - ErrorMessage = ""; - - return true; - } - } - - var trk = new Track(); - - // If optical disc check track - if(_imageInfo.MetadataMediaType == MetadataMediaType.OpticalDisc) - { - trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector) ?? - new Track(); - - if(trk.Sequence == 0 && trk.StartSector == 0 && trk.EndSector == 0) - trk.Type = TrackType.Data; // TODO: Check intersession data type - } - - // Close current block first - if(_writingBuffer != null && - - // When sector siz changes - (_currentBlockHeader.sectorSize != data.Length || - - // When block if filled - _currentBlockOffset == 1 << _shift || - - // When we change to/from CompactDisc audio - _currentBlockHeader.compression == CompressionType.Flac && trk.Type != TrackType.Audio)) - { - _currentBlockHeader.length = _currentBlockOffset * _currentBlockHeader.sectorSize; - _currentBlockHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); - - var cmpCrc64Context = new Crc64Context(); - - byte[] lzmaProperties = []; - int compressedLength = 0; - - switch(_currentBlockHeader.compression) - { - case CompressionType.Flac: - { - uint currentSamples = _currentBlockOffset * SAMPLES_PER_SECTOR; - uint flacBlockSize = _currentBlockOffset * SAMPLES_PER_SECTOR; - - if(flacBlockSize > MAX_FLAKE_BLOCK) flacBlockSize = MAX_FLAKE_BLOCK; - - if(flacBlockSize < MIN_FLAKE_BLOCK) flacBlockSize = MIN_FLAKE_BLOCK; - - long remaining = currentSamples % flacBlockSize; - - // Fill FLAC block - if(remaining != 0) - { - for(int r = 0; r < remaining * 4; r++) _writingBuffer[_writingBufferPosition + r] = 0; - } - - compressedLength = FLAC.EncodeBuffer(_writingBuffer, - _compressedBuffer, - flacBlockSize, - true, - false, - "hamming", - 12, - 15, - true, - false, - 0, - 8, - "Aaru"); - - if(compressedLength >= _writingBufferPosition) - _currentBlockHeader.compression = CompressionType.None; - - break; - } - case CompressionType.Lzma: - { - compressedLength = LZMA.EncodeBuffer(_writingBuffer, - _compressedBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - cmpCrc64Context.Update(lzmaProperties); - - if(compressedLength >= _writingBufferPosition) - _currentBlockHeader.compression = CompressionType.None; - - break; - } - case CompressionType.None: - break; // Do nothing - default: - throw new ArgumentOutOfRangeException(); - } - - if(_currentBlockHeader.compression == CompressionType.None) - { - _currentBlockHeader.cmpCrc64 = _currentBlockHeader.crc64; - _currentBlockHeader.cmpLength = (uint)_writingBufferPosition; - } - else - { - cmpCrc64Context.Update(_compressedBuffer, (uint)compressedLength); - _currentBlockHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - _currentBlockHeader.cmpLength = (uint)compressedLength; - } - - if(_currentBlockHeader.compression == CompressionType.Lzma) - _currentBlockHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - _index.Add(new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in _currentBlockHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_currentBlockHeader.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - if(_currentBlockHeader.compression == CompressionType.None) - _imageStream.Write(_writingBuffer, 0, _writingBufferPosition); - else - _imageStream.Write(_compressedBuffer, 0, compressedLength); - - _writingBufferPosition = 0; - GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized, false); - _currentBlockOffset = 0; - } - - // No block set - if(_writingBufferPosition == 0) - { - _currentBlockHeader = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.UserData, - compression = _compress ? _compressionAlgorithm : CompressionType.None, - sectorSize = (uint)data.Length - }; - - if(_imageInfo.MetadataMediaType == MetadataMediaType.OpticalDisc && - trk.Type == TrackType.Audio && - _compress) - _currentBlockHeader.compression = CompressionType.Flac; - - // JaguarCD stores data in audio tracks. FLAC is too inefficient, use LZMA there. - // VideoNow stores video in audio tracks, and LZMA works better too. - if((_imageInfo.MediaType == MediaType.JaguarCD && trk.Session > 1 || - _imageInfo.MediaType is MediaType.VideoNow or MediaType.VideoNowColor or MediaType.VideoNowXp) && - trk.Type == TrackType.Audio && - _compress && - _currentBlockHeader.compression == CompressionType.Flac) - _currentBlockHeader.compression = CompressionType.Lzma; - - int maxBufferSize = (1 << _shift) * data.Length + MAX_FLAKE_BLOCK * 4; - - if(_writingBuffer == null || _writingBuffer.Length < maxBufferSize) - { - _writingBuffer = new byte[maxBufferSize]; - _compressedBuffer = new byte[maxBufferSize * 2]; - } - - _writingBufferPosition = 0; - _crc64 = new Crc64Context(); - } - - ulong ddtEntry = (ulong)((_imageStream.Position << _shift) + _currentBlockOffset); - - if(hash != null) _deduplicationTable.Add(hashString, ddtEntry); - - Array.Copy(data, 0, _writingBuffer, _writingBufferPosition, data.Length); - _writingBufferPosition += data.Length; - - SetDdtEntry(sectorAddress, ddtEntry); - _crc64.Update(data); - _currentBlockOffset++; - - ErrorMessage = ""; - - return true; - } - - /// - public bool WriteSectors(byte[] data, ulong sectorAddress, uint length) - { - if(!IsWriting) - { - ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image; - - return false; - } - - if(sectorAddress + length > Info.Sectors) - { - ErrorMessage = Localization.Tried_to_write_past_image_size; - - return false; - } - - uint sectorSize = (uint)(data.Length / length); - - for(uint i = 0; i < length; i++) - { - byte[] tmp = new byte[sectorSize]; - Array.Copy(data, i * sectorSize, tmp, 0, sectorSize); - - if(!WriteSector(tmp, sectorAddress + i)) return false; - } - - ErrorMessage = ""; - - return true; - } - - /// - public bool WriteSectorLong(byte[] data, ulong sectorAddress) - { - if(!IsWriting) - { - ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image; - - return false; - } - - byte[] sector; - - switch(_imageInfo.MetadataMediaType) - { - case MetadataMediaType.OpticalDisc: - Track track = - Tracks.FirstOrDefault(trk => sectorAddress >= trk.StartSector && sectorAddress <= trk.EndSector); - - if(track is null) - { - ErrorMessage = Localization.Track_not_found; - - return false; - } - - if(track.Sequence == 0 && track.StartSector == 0 && track.EndSector == 0) track.Type = TrackType.Data; - - if(data.Length == 2064 && - _imageInfo.MediaType is MediaType.DVDROM - or MediaType.PS2DVD - or MediaType.SACD - or MediaType.PS3DVD - or MediaType.DVDR - or MediaType.DVDRW - or MediaType.DVDPR - or MediaType.DVDPRW - or MediaType.DVDPRWDL - or MediaType.DVDRDL - or MediaType.DVDPRDL - or MediaType.DVDRAM - or MediaType.DVDRWDL - or MediaType.DVDDownload - or MediaType.Nuon) - { - sector = new byte[2048]; - _sectorId ??= new byte[_imageInfo.Sectors * 4]; - _sectorIed ??= new byte[_imageInfo.Sectors * 2]; - _sectorCprMai ??= new byte[_imageInfo.Sectors * 6]; - _sectorEdc ??= new byte[_imageInfo.Sectors * 4]; - - Array.Copy(data, 0, _sectorId, (int)sectorAddress * 4, 4); - Array.Copy(data, 4, _sectorIed, (int)sectorAddress * 2, 2); - Array.Copy(data, 6, _sectorCprMai, (int)sectorAddress * 6, 6); - Array.Copy(data, 12, sector, 0, 2048); - Array.Copy(data, 2060, _sectorEdc, (int)sectorAddress * 4, 4); - - return WriteSector(sector, sectorAddress); - } - - if(data.Length != 2352) - { - ErrorMessage = Localization.Incorrect_data_size; - - return false; - } - - _writingLong = true; - - if(!_rewinded) - { - if(sectorAddress <= _lastWrittenBlock && _alreadyWrittenZero) - { - _rewinded = true; - _md5Provider = null; - _sha1Provider = null; - _sha256Provider = null; - _spamsumProvider = null; - } - - _md5Provider?.Update(data); - _sha1Provider?.Update(data); - _sha256Provider?.Update(data); - _spamsumProvider?.Update(data); - _lastWrittenBlock = sectorAddress; - } - - bool prefixCorrect; - int minute; - int second; - int frame; - int storedLba; - - // Split raw cd sector data in prefix (sync, header), user data and suffix (edc, ecc p, ecc q) - switch(track.Type) - { - case TrackType.Audio: - case TrackType.Data: - return WriteSector(data, sectorAddress); - case TrackType.CdMode1: - if(_sectorPrefix != null && _sectorSuffix != null) - { - sector = new byte[2048]; - Array.Copy(data, 0, _sectorPrefix, (int)sectorAddress * 16, 16); - Array.Copy(data, 16, sector, 0, 2048); - Array.Copy(data, 2064, _sectorSuffix, (int)sectorAddress * 288, 288); - - return WriteSector(sector, sectorAddress); - } - - _sectorSuffixMs ??= new MemoryStream(); - - _sectorPrefixMs ??= new MemoryStream(); - - if(_sectorSuffixDdt == null) - { - _sectorSuffixDdt = new uint[_imageInfo.Sectors]; - EccInit(); - } - - _sectorPrefixDdt ??= new uint[_imageInfo.Sectors]; - - sector = new byte[2048]; - - if(ArrayHelpers.ArrayIsNullOrEmpty(data)) - { - _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; - - return WriteSector(sector, sectorAddress); - } - - prefixCorrect = true; - - if(data[0x00] != 0x00 || - data[0x01] != 0xFF || - data[0x02] != 0xFF || - data[0x03] != 0xFF || - data[0x04] != 0xFF || - data[0x05] != 0xFF || - data[0x06] != 0xFF || - data[0x07] != 0xFF || - data[0x08] != 0xFF || - data[0x09] != 0xFF || - data[0x0A] != 0xFF || - data[0x0B] != 0x00 || - data[0x0F] != 0x01) - prefixCorrect = false; - - if(prefixCorrect) - { - minute = (data[0x0C] >> 4) * 10 + (data[0x0C] & 0x0F); - second = (data[0x0D] >> 4) * 10 + (data[0x0D] & 0x0F); - frame = (data[0x0E] >> 4) * 10 + (data[0x0E] & 0x0F); - storedLba = minute * 60 * 75 + second * 75 + frame - 150; - prefixCorrect = storedLba == (int)sectorAddress; - } - - if(prefixCorrect) - _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.Correct; - else - { - if((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - _sectorPrefixMs.Position = ((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16; - else - _sectorPrefixMs.Seek(0, SeekOrigin.End); - - _sectorPrefixDdt[sectorAddress] = (uint)(_sectorPrefixMs.Position / 16 + 1); - _sectorPrefixMs.Write(data, 0, 16); - } - - bool correct = SuffixIsCorrect(data); - - if(correct) - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Correct; - else - { - if((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - _sectorSuffixMs.Position = ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; - else - _sectorSuffixMs.Seek(0, SeekOrigin.End); - - _sectorSuffixDdt[sectorAddress] = (uint)(_sectorSuffixMs.Position / 288 + 1); - - _sectorSuffixMs.Write(data, 2064, 288); - } - - Array.Copy(data, 16, sector, 0, 2048); - - return WriteSector(sector, sectorAddress); - case TrackType.CdMode2Formless: - case TrackType.CdMode2Form1: - case TrackType.CdMode2Form2: - if(_sectorPrefix != null && _sectorSuffix != null) - { - sector = new byte[2336]; - Array.Copy(data, 0, _sectorPrefix, (int)sectorAddress * 16, 16); - Array.Copy(data, 16, sector, 0, 2336); - - return WriteSector(sector, sectorAddress); - } - - _sectorSuffixMs ??= new MemoryStream(); - - _sectorPrefixMs ??= new MemoryStream(); - - if(_sectorSuffixDdt == null) - { - _sectorSuffixDdt = new uint[_imageInfo.Sectors]; - EccInit(); - } - - _sectorPrefixDdt ??= new uint[_imageInfo.Sectors]; - - sector = new byte[2328]; - - if(ArrayHelpers.ArrayIsNullOrEmpty(data)) - { - _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; - - return WriteSector(sector, sectorAddress); - } - - prefixCorrect = true; - - if(data[0x00] != 0x00 || - data[0x01] != 0xFF || - data[0x02] != 0xFF || - data[0x03] != 0xFF || - data[0x04] != 0xFF || - data[0x05] != 0xFF || - data[0x06] != 0xFF || - data[0x07] != 0xFF || - data[0x08] != 0xFF || - data[0x09] != 0xFF || - data[0x0A] != 0xFF || - data[0x0B] != 0x00 || - data[0x0F] != 0x02) - prefixCorrect = false; - - if(prefixCorrect) - { - minute = (data[0x0C] >> 4) * 10 + (data[0x0C] & 0x0F); - second = (data[0x0D] >> 4) * 10 + (data[0x0D] & 0x0F); - frame = (data[0x0E] >> 4) * 10 + (data[0x0E] & 0x0F); - storedLba = minute * 60 * 75 + second * 75 + frame - 150; - prefixCorrect = storedLba == (int)sectorAddress; - } - - if(prefixCorrect) - _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.Correct; - else - { - if((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - _sectorPrefixMs.Position = ((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16; - else - _sectorPrefixMs.Seek(0, SeekOrigin.End); - - _sectorPrefixDdt[sectorAddress] = (uint)(_sectorPrefixMs.Position / 16 + 1); - - _sectorPrefixMs.Write(data, 0, 16); - } - - _mode2Subheaders ??= new byte[_imageInfo.Sectors * 8]; - - bool form2 = (data[18] & 0x20) == 0x20 || (data[22] & 0x20) == 0x20; - - if(form2) - { - uint computedEdc = ComputeEdc(0, data, 0x91C, 0x10); - uint edc = BitConverter.ToUInt32(data, 0x92C); - bool correctEdc = computedEdc == edc; - - sector = new byte[2324]; - - _sectorSuffixDdt ??= new uint[_imageInfo.Sectors]; - - Array.Copy(data, 24, sector, 0, 2324); - - if(correctEdc) - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form2Ok; - else if(BitConverter.ToUInt32(data, 0x92C) == 0) - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form2NoCrc; - else - { - if((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - { - _sectorSuffixMs.Position = - ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; - } - else - _sectorSuffixMs.Seek(0, SeekOrigin.End); - - _sectorSuffixDdt[sectorAddress] = (uint)(_sectorSuffixMs.Position / 288 + 1); - - _sectorSuffixMs.Write(data, 2348, 4); - } - } - else - { - bool correctEcc = SuffixIsCorrectMode2(data); - - uint computedEdc = ComputeEdc(0, data, 0x808, 0x10); - uint edc = BitConverter.ToUInt32(data, 0x818); - bool correctEdc = computedEdc == edc; - - sector = new byte[2048]; - Array.Copy(data, 24, sector, 0, 2048); - - if(correctEcc && correctEdc) - { - _sectorSuffixDdt ??= new uint[_imageInfo.Sectors]; - - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form1Ok; - } - else - { - if((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - { - _sectorSuffixMs.Position = - ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; - } - else - _sectorSuffixMs.Seek(0, SeekOrigin.End); - - _sectorSuffixDdt[sectorAddress] = (uint)(_sectorSuffixMs.Position / 288 + 1); - - _sectorSuffixMs.Write(data, 2072, 280); - } - } - - Array.Copy(data, 16, _mode2Subheaders, (int)sectorAddress * 8, 8); - - return WriteSector(sector, sectorAddress); - } - - break; - case MetadataMediaType.BlockMedia: - switch(_imageInfo.MediaType) - { - // Split user data from Apple tags - case MediaType.AppleFileWare: - case MediaType.AppleProfile: - case MediaType.AppleSonyDS: - case MediaType.AppleSonySS: - case MediaType.AppleWidget: - case MediaType.PriamDataTower: - byte[] oldTag; - byte[] newTag; - - switch(data.Length - 512) - { - // Sony tag, convert to Profile - case 12 when _imageInfo.MediaType is MediaType.AppleProfile or MediaType.AppleFileWare: - oldTag = new byte[12]; - Array.Copy(data, 512, oldTag, 0, 12); - newTag = LisaTag.DecodeSonyTag(oldTag)?.ToProfile().GetBytes(); - - break; - - // Sony tag, convert to Priam - case 12 when _imageInfo.MediaType == MediaType.PriamDataTower: - oldTag = new byte[12]; - Array.Copy(data, 512, oldTag, 0, 12); - newTag = LisaTag.DecodeSonyTag(oldTag)?.ToPriam().GetBytes(); - - break; - - // Sony tag, copy to Sony - case 12 when _imageInfo.MediaType is MediaType.AppleSonySS or MediaType.AppleSonySS: - newTag = new byte[12]; - Array.Copy(data, 512, newTag, 0, 12); - - break; - - // Profile tag, copy to Profile - case 20 when _imageInfo.MediaType is MediaType.AppleProfile or MediaType.AppleFileWare: - newTag = new byte[20]; - Array.Copy(data, 512, newTag, 0, 20); - - break; - - // Profile tag, convert to Priam - case 20 when _imageInfo.MediaType == MediaType.PriamDataTower: - oldTag = new byte[20]; - Array.Copy(data, 512, oldTag, 0, 20); - newTag = LisaTag.DecodeProfileTag(oldTag)?.ToPriam().GetBytes(); - - break; - - // Profile tag, convert to Sony - case 20 when _imageInfo.MediaType is MediaType.AppleSonySS or MediaType.AppleSonySS: - oldTag = new byte[20]; - Array.Copy(data, 512, oldTag, 0, 20); - newTag = LisaTag.DecodeProfileTag(oldTag)?.ToSony().GetBytes(); - - break; - - // Priam tag, convert to Profile - case 24 when _imageInfo.MediaType is MediaType.AppleProfile or MediaType.AppleFileWare: - oldTag = new byte[24]; - Array.Copy(data, 512, oldTag, 0, 24); - newTag = LisaTag.DecodePriamTag(oldTag)?.ToProfile().GetBytes(); - - break; - - // Priam tag, copy to Priam - case 12 when _imageInfo.MediaType == MediaType.PriamDataTower: - newTag = new byte[24]; - Array.Copy(data, 512, newTag, 0, 24); - - break; - - // Priam tag, convert to Sony - case 24 when _imageInfo.MediaType is MediaType.AppleSonySS or MediaType.AppleSonySS: - oldTag = new byte[24]; - Array.Copy(data, 512, oldTag, 0, 24); - newTag = LisaTag.DecodePriamTag(oldTag)?.ToSony().GetBytes(); - - break; - case 0: - newTag = null; - - break; - default: - ErrorMessage = Localization.Incorrect_data_size; - - return false; - } - - sector = new byte[512]; - Array.Copy(data, 0, sector, 0, 512); - - if(newTag == null) return WriteSector(sector, sectorAddress); - - _sectorSubchannel ??= new byte[newTag.Length * (int)_imageInfo.Sectors]; - - Array.Copy(newTag, 0, _sectorSubchannel, newTag.Length * (int)sectorAddress, newTag.Length); - - return WriteSector(sector, sectorAddress); - } - - break; - } - - ErrorMessage = Localization.Unknown_long_sector_type_cannot_write; - - return false; - } - - /// - public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length) - { - byte[] sector; - - switch(_imageInfo.MetadataMediaType) - { - case MetadataMediaType.OpticalDisc: - switch(_imageInfo.MediaType) - { - case MediaType.DVDROM: - case MediaType.PS2DVD: - case MediaType.SACD: - case MediaType.DVDR: - case MediaType.DVDRW: - case MediaType.DVDPR: - case MediaType.DVDPRW: - case MediaType.DVDPRWDL: - case MediaType.DVDRDL: - case MediaType.DVDPRDL: - case MediaType.DVDRAM: - case MediaType.DVDRWDL: - case MediaType.DVDDownload: - case MediaType.PS3DVD: - case MediaType.Nuon: - if(data.Length % 2064 != 0) - { - ErrorMessage = Localization.Incorrect_data_size; - - return false; - } - - sector = new byte[2064]; - - for(uint i = 0; i < length; i++) - { - Array.Copy(data, 2064 * i, sector, 0, 2064); - - if(!WriteSectorLong(sector, sectorAddress + i)) return false; - } - - ErrorMessage = ""; - - return true; - - default: - if(data.Length % 2352 != 0) - { - ErrorMessage = Localization.Incorrect_data_size; - - return false; - } - - sector = new byte[2352]; - - for(uint i = 0; i < length; i++) - { - Array.Copy(data, 2352 * i, sector, 0, 2352); - - if(!WriteSectorLong(sector, sectorAddress + i)) return false; - } - - ErrorMessage = ""; - - return true; - } - - case MetadataMediaType.BlockMedia: - switch(_imageInfo.MediaType) - { - case MediaType.AppleFileWare: - case MediaType.AppleProfile: - case MediaType.AppleSonyDS: - case MediaType.AppleSonySS: - case MediaType.AppleWidget: - case MediaType.PriamDataTower: - int sectorSize = 0; - - if(data.Length % 524 == 0) - sectorSize = 524; - else if(data.Length % 532 == 0) - sectorSize = 532; - else if(data.Length % 536 == 0) sectorSize = 536; - - if(sectorSize == 0) - { - ErrorMessage = Localization.Incorrect_data_size; - - return false; - } - - sector = new byte[sectorSize]; - - for(uint i = 0; i < length; i++) - { - Array.Copy(data, sectorSize * i, sector, 0, sectorSize); - - if(!WriteSectorLong(sector, sectorAddress + i)) return false; - } - - ErrorMessage = ""; - - return true; - } - - break; - } - - ErrorMessage = Localization.Unknown_long_sector_type_cannot_write; - - return false; - } - - /// - public bool SetTracks(List tracks) - { - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) - { - ErrorMessage = Localization.Unsupported_feature; - - return false; - } - - if(!IsWriting) - { - ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image; - - return false; - } - - Tracks = tracks; - ErrorMessage = ""; - - return true; - } - - /// - public bool Close() - { - if(!IsWriting) - { - ErrorMessage = Localization.Image_is_not_opened_for_writing; - - return false; - } - - // Close current block first - if(_writingBuffer != null) - { - _currentBlockHeader.length = _currentBlockOffset * _currentBlockHeader.sectorSize; - _currentBlockHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); - - var cmpCrc64Context = new Crc64Context(); - - byte[] lzmaProperties = []; - int compressedLength = 0; - - switch(_currentBlockHeader.compression) - { - case CompressionType.Flac: - { - uint currentSamples = _currentBlockOffset * SAMPLES_PER_SECTOR; - uint flacBlockSize = _currentBlockOffset * SAMPLES_PER_SECTOR; - - if(flacBlockSize > MAX_FLAKE_BLOCK) flacBlockSize = MAX_FLAKE_BLOCK; - - if(flacBlockSize < MIN_FLAKE_BLOCK) flacBlockSize = MIN_FLAKE_BLOCK; - - long remaining = currentSamples % flacBlockSize; - - // Fill FLAC block - if(remaining != 0) - { - for(int r = 0; r < remaining * 4; r++) _writingBuffer[_writingBufferPosition + r] = 0; - } - - compressedLength = FLAC.EncodeBuffer(_writingBuffer, - _compressedBuffer, - flacBlockSize, - true, - false, - "hamming", - 12, - 15, - true, - false, - 0, - 8, - "Aaru"); - - if(compressedLength >= _writingBufferPosition) - _currentBlockHeader.compression = CompressionType.None; - - break; - } - case CompressionType.Lzma: - { - compressedLength = LZMA.EncodeBuffer(_writingBuffer, - _compressedBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - cmpCrc64Context.Update(lzmaProperties); - - if(compressedLength >= _writingBufferPosition) - _currentBlockHeader.compression = CompressionType.None; - - break; - } - case CompressionType.None: - break; // Do nothing - default: - throw new ArgumentOutOfRangeException(); - } - - if(_currentBlockHeader.compression == CompressionType.None) - { - _currentBlockHeader.cmpCrc64 = _currentBlockHeader.crc64; - _currentBlockHeader.cmpLength = (uint)_writingBufferPosition; - } - else - { - cmpCrc64Context.Update(_compressedBuffer, (uint)compressedLength); - _currentBlockHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - _currentBlockHeader.cmpLength = (uint)compressedLength; - } - - if(_currentBlockHeader.compression == CompressionType.Lzma) - _currentBlockHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - _index.Add(new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in _currentBlockHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_currentBlockHeader.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - if(_currentBlockHeader.compression == CompressionType.None) - _imageStream.Write(_writingBuffer, 0, _writingBufferPosition); - else - _imageStream.Write(_compressedBuffer, 0, compressedLength); - - _writingBuffer = null; - } - - if(_deduplicate) - { - AaruLogging.Debug(MODULE_NAME, - Localization.Of_0_sectors_written_1_are_unique_2, - _writtenSectors, - _deduplicationTable.Count, - (double)_deduplicationTable.Count / _writtenSectors); - } - - IndexEntry idxEntry; - - // TODO: Reuse buffer - MemoryStream blockStream; - - // Write media tag blocks - foreach(KeyValuePair mediaTag in _mediaTags) - { - DataType dataType = GetDataTypeForMediaTag(mediaTag.Key); - - if(mediaTag.Value is null) - { - AaruLogging.Error(Localization.Tag_type_0_is_null_skipping, dataType); - - continue; - } - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = dataType, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_tag_type_0_to_position_1, - mediaTag.Key, - idxEntry.offset); - - Crc64Context.Data(mediaTag.Value, out byte[] tagCrc); - - var tagBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = dataType, - length = (uint)mediaTag.Value.Length, - crc64 = BitConverter.ToUInt64(tagCrc, 0) - }; - - byte[] cmpBuffer = new byte[mediaTag.Value.Length + 262144]; - - byte[] lzmaProperties = null; - bool doNotCompress = false; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - int cmpLen = LZMA.EncodeBuffer(mediaTag.Value, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - if(cmpLen + LZMA_PROPERTIES_LENGTH > mediaTag.Value.Length) doNotCompress = true; - - break; - case CompressionType.None: - doNotCompress = true; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - byte[] tagData; - - // Not compressible - if(doNotCompress) - { - tagBlock.cmpLength = tagBlock.length; - tagBlock.cmpCrc64 = tagBlock.crc64; - tagData = mediaTag.Value; - tagBlock.compression = CompressionType.None; - } - else - { - tagData = cmpBuffer; - var crc64Ctx = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) crc64Ctx.Update(lzmaProperties); - - crc64Ctx.Update(tagData); - tagCrc = crc64Ctx.Final(); - tagBlock.cmpLength = (uint)tagData.Length; - tagBlock.cmpCrc64 = BitConverter.ToUInt64(tagCrc, 0); - tagBlock.compression = _compressionAlgorithm; - - if(_compressionAlgorithm == CompressionType.Lzma) tagBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in tagBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(tagBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(tagData, 0, tagData.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == dataType); - - _index.Add(idxEntry); - } - - // If we have set the geometry block, write it - if(_geometryBlock.identifier == BlockType.GeometryBlock) - { - idxEntry = new IndexEntry - { - blockType = BlockType.GeometryBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_geometry_block_to_position_0, idxEntry.offset); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in _geometryBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.GeometryBlock, dataType: DataType.NoData }); - - _index.Add(idxEntry); - } - - // If we have dump hardware, write it - if(DumpHardware != null) - { - var dumpMs = new MemoryStream(); - - foreach(DumpHardware dump in DumpHardware) - { - byte[] dumpManufacturer = null; - byte[] dumpModel = null; - byte[] dumpRevision = null; - byte[] dumpFirmware = null; - byte[] dumpSerial = null; - byte[] dumpSoftwareName = null; - byte[] dumpSoftwareVersion = null; - byte[] dumpSoftwareOperatingSystem = null; - - if(!string.IsNullOrWhiteSpace(dump.Manufacturer)) - dumpManufacturer = Encoding.UTF8.GetBytes(dump.Manufacturer); - - if(!string.IsNullOrWhiteSpace(dump.Model)) dumpModel = Encoding.UTF8.GetBytes(dump.Model); - - if(!string.IsNullOrWhiteSpace(dump.Revision)) dumpRevision = Encoding.UTF8.GetBytes(dump.Revision); - - if(!string.IsNullOrWhiteSpace(dump.Firmware)) dumpFirmware = Encoding.UTF8.GetBytes(dump.Firmware); - - if(!string.IsNullOrWhiteSpace(dump.Serial)) dumpSerial = Encoding.UTF8.GetBytes(dump.Serial); - - if(!string.IsNullOrWhiteSpace(dump.Software?.Name)) - dumpSoftwareName = Encoding.UTF8.GetBytes(dump.Software.Name); - - if(!string.IsNullOrWhiteSpace(dump.Software?.Version)) - dumpSoftwareVersion = Encoding.UTF8.GetBytes(dump.Software.Version); - - if(!string.IsNullOrWhiteSpace(dump.Software?.OperatingSystem)) - dumpSoftwareOperatingSystem = Encoding.UTF8.GetBytes(dump.Software.OperatingSystem); - - var dumpEntry = new DumpHardwareEntry - { - manufacturerLength = (uint)(dumpManufacturer?.Length + 1 ?? 0), - modelLength = (uint)(dumpModel?.Length + 1 ?? 0), - revisionLength = (uint)(dumpRevision?.Length + 1 ?? 0), - firmwareLength = (uint)(dumpFirmware?.Length + 1 ?? 0), - serialLength = (uint)(dumpSerial?.Length + 1 ?? 0), - softwareNameLength = (uint)(dumpSoftwareName?.Length + 1 ?? 0), - softwareVersionLength = (uint)(dumpSoftwareVersion?.Length + 1 ?? 0), - softwareOperatingSystemLength = (uint)(dumpSoftwareOperatingSystem?.Length + 1 ?? 0), - extents = (uint)dump.Extents.Count - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in dumpEntry); - dumpMs.Write(_structureBytes, 0, _structureBytes.Length); - - if(dumpManufacturer != null) - { - dumpMs.Write(dumpManufacturer, 0, dumpManufacturer.Length); - dumpMs.WriteByte(0); - } - - if(dumpModel != null) - { - dumpMs.Write(dumpModel, 0, dumpModel.Length); - dumpMs.WriteByte(0); - } - - if(dumpRevision != null) - { - dumpMs.Write(dumpRevision, 0, dumpRevision.Length); - dumpMs.WriteByte(0); - } - - if(dumpFirmware != null) - { - dumpMs.Write(dumpFirmware, 0, dumpFirmware.Length); - dumpMs.WriteByte(0); - } - - if(dumpSerial != null) - { - dumpMs.Write(dumpSerial, 0, dumpSerial.Length); - dumpMs.WriteByte(0); - } - - if(dumpSoftwareName != null) - { - dumpMs.Write(dumpSoftwareName, 0, dumpSoftwareName.Length); - dumpMs.WriteByte(0); - } - - if(dumpSoftwareVersion != null) - { - dumpMs.Write(dumpSoftwareVersion, 0, dumpSoftwareVersion.Length); - dumpMs.WriteByte(0); - } - - if(dumpSoftwareOperatingSystem != null) - { - dumpMs.Write(dumpSoftwareOperatingSystem, 0, dumpSoftwareOperatingSystem.Length); - dumpMs.WriteByte(0); - } - - foreach(Extent extent in dump.Extents) - { - dumpMs.Write(BitConverter.GetBytes(extent.Start), 0, sizeof(ulong)); - dumpMs.Write(BitConverter.GetBytes(extent.End), 0, sizeof(ulong)); - } - } - - idxEntry = new IndexEntry - { - blockType = BlockType.DumpHardwareBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_dump_hardware_block_to_position_0, idxEntry.offset); - - Crc64Context.Data(dumpMs.ToArray(), out byte[] dumpCrc); - - var dumpBlock = new DumpHardwareHeader - { - identifier = BlockType.DumpHardwareBlock, - entries = (ushort)DumpHardware.Count, - crc64 = BitConverter.ToUInt64(dumpCrc, 0), - length = (uint)dumpMs.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in dumpBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(dumpMs.ToArray(), 0, (int)dumpMs.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.DumpHardwareBlock, dataType: DataType.NoData }); - - _index.Add(idxEntry); - } - - // If we have Aaru Metadata, write it - if(AaruMetadata != null) - { - var jsonMs = new MemoryStream(); - - JsonSerializer.Serialize(jsonMs, - new MetadataJson - { - AaruMetadata = AaruMetadata - }, - typeof(MetadataJson), - MetadataJsonContext.Default); - - idxEntry = new IndexEntry - { - blockType = BlockType.AaruMetadataJsonBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_Aaru_Metadata_block_to_position_0, idxEntry.offset); - - var jsonBlock = new AaruMetadataJsonBlock - { - identifier = BlockType.AaruMetadataJsonBlock, - length = (uint)jsonMs.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in jsonBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(jsonMs.ToArray(), 0, (int)jsonMs.Length); - - // Ensure no CICM XML block is recorded altogether - _index.RemoveAll(t => t is { blockType: BlockType.CicmBlock, dataType : DataType.NoData }); - _index.RemoveAll(t => t is { blockType: BlockType.AaruMetadataJsonBlock, dataType: DataType.NoData }); - - _index.Add(idxEntry); - } - - // If we have checksums, write it to disk - if(_md5Provider != null || _sha1Provider != null || _sha256Provider != null || _spamsumProvider != null) - { - var chkMs = new MemoryStream(); - - var chkHeader = new ChecksumHeader - { - identifier = BlockType.ChecksumBlock - }; - - if(_md5Provider != null) - { - byte[] md5 = _md5Provider.Final(); - - var md5Entry = new ChecksumEntry - { - type = ChecksumAlgorithm.Md5, - length = (uint)md5.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in md5Entry); - chkMs.Write(_structureBytes, 0, _structureBytes.Length); - chkMs.Write(md5, 0, md5.Length); - chkHeader.entries++; - } - - if(_sha1Provider != null) - { - byte[] sha1 = _sha1Provider.Final(); - - var sha1Entry = new ChecksumEntry - { - type = ChecksumAlgorithm.Sha1, - length = (uint)sha1.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in sha1Entry); - chkMs.Write(_structureBytes, 0, _structureBytes.Length); - chkMs.Write(sha1, 0, sha1.Length); - chkHeader.entries++; - } - - if(_sha256Provider != null) - { - byte[] sha256 = _sha256Provider.Final(); - - var sha256Entry = new ChecksumEntry - { - type = ChecksumAlgorithm.Sha256, - length = (uint)sha256.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in sha256Entry); - chkMs.Write(_structureBytes, 0, _structureBytes.Length); - chkMs.Write(sha256, 0, sha256.Length); - chkHeader.entries++; - } - - if(_spamsumProvider != null) - { - byte[] spamsum = Encoding.ASCII.GetBytes(_spamsumProvider.End()); - - var spamsumEntry = new ChecksumEntry - { - type = ChecksumAlgorithm.SpamSum, - length = (uint)spamsum.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in spamsumEntry); - chkMs.Write(_structureBytes, 0, _structureBytes.Length); - chkMs.Write(spamsum, 0, spamsum.Length); - chkHeader.entries++; - } - - if(chkHeader.entries > 0) - { - chkHeader.length = (uint)chkMs.Length; - - idxEntry = new IndexEntry - { - blockType = BlockType.ChecksumBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_checksum_block_to_position_0, idxEntry.offset); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in chkHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(chkMs.ToArray(), 0, (int)chkMs.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.ChecksumBlock, dataType: DataType.NoData }); - - _index.Add(idxEntry); - } - } - - if(IsTape) - { - ulong latestBlock = _tapeDdt.Max(b => b.Key); - - _userDataDdt = new ulong[latestBlock + 1]; - - foreach(KeyValuePair block in _tapeDdt) _userDataDdt[block.Key] = block.Value; - - _inMemoryDdt = true; - _tapeDdt.Clear(); - - idxEntry = new IndexEntry - { - blockType = BlockType.TapePartitionBlock, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_tape_partitions_to_position_0, idxEntry.offset); - - var tapePartitionEntries = new TapePartitionEntry[TapePartitions.Count]; - - for(int t = 0; t < TapePartitions.Count; t++) - { - tapePartitionEntries[t] = new TapePartitionEntry - { - Number = TapePartitions[t].Number, - FirstBlock = TapePartitions[t].FirstBlock, - LastBlock = TapePartitions[t].LastBlock - }; - } - - byte[] tapePartitionEntriesData = - MemoryMarshal.Cast(tapePartitionEntries).ToArray(); - - var tapePartitionHeader = new TapePartitionHeader - { - identifier = BlockType.TapePartitionBlock, - entries = (byte)tapePartitionEntries.Length, - length = (ulong)tapePartitionEntriesData.Length - }; - - _crc64 = new Crc64Context(); - _crc64.Update(tapePartitionEntriesData); - tapePartitionHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in tapePartitionHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - _imageStream.Write(tapePartitionEntriesData, 0, tapePartitionEntriesData.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.TapePartitionBlock, dataType: DataType.UserData }); - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.TapeFileBlock, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_tape_files_to_position_0, idxEntry.offset); - - var tapeFileEntries = new TapeFileEntry[Files.Count]; - - for(int t = 0; t < Files.Count; t++) - { - tapeFileEntries[t] = new TapeFileEntry - { - File = Files[t].File, - FirstBlock = Files[t].FirstBlock, - LastBlock = Files[t].LastBlock - }; - } - - byte[] tapeFileEntriesData = MemoryMarshal.Cast(tapeFileEntries).ToArray(); - - var tapeFileHeader = new TapeFileHeader - { - identifier = BlockType.TapeFileBlock, - entries = (uint)tapeFileEntries.Length, - length = (ulong)tapeFileEntriesData.Length - }; - - _crc64 = new Crc64Context(); - _crc64.Update(tapeFileEntriesData); - tapeFileHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in tapeFileHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - _imageStream.Write(tapeFileEntriesData, 0, tapeFileEntriesData.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.TapeFileBlock, dataType: DataType.UserData }); - _index.Add(idxEntry); - } - - // If the DDT is in-memory, write it to disk - if(_inMemoryDdt) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DeDuplicationTable, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_user_data_DDT_to_position_0, idxEntry.offset); - - var ddtHeader = new DdtHeader - { - identifier = BlockType.DeDuplicationTable, - type = DataType.UserData, - compression = _compressionAlgorithm, - shift = _shift, - entries = (ulong)_userDataDdt.LongLength, - length = (ulong)(_userDataDdt.LongLength * sizeof(ulong)) - }; - - _crc64 = new Crc64Context(); - byte[] ddtEntries = MemoryMarshal.Cast(_userDataDdt).ToArray(); - _crc64.Update(ddtEntries); - - byte[] cmpBuffer = new byte[ddtEntries.Length + 262144]; - - int cmpLen; - byte[] lzmaProperties = null; - - switch(_compressionAlgorithm) - { - case CompressionType.None: - cmpBuffer = ddtEntries; - cmpLen = cmpBuffer.Length; - - break; - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(ddtEntries, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - ddtHeader.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma && cmpBuffer != ddtEntries) - ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - var cmpCrc64Context = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma && cmpBuffer != ddtEntries) - cmpCrc64Context.Update(lzmaProperties); - - cmpCrc64Context.Update(blockStream.ToArray()); - ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in ddtHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_compressionAlgorithm == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t is { blockType: BlockType.DeDuplicationTable, dataType: DataType.UserData }); - - _index.Add(idxEntry); - } - - // Write the sector prefix, suffix and subchannels if present - switch(_imageInfo.MetadataMediaType) - { - case MetadataMediaType.OpticalDisc when Tracks is { Count: > 0 }: - var compressStopwatch = new Stopwatch(); - - // Old format - if(_sectorPrefix != null && _sectorSuffix != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorPrefix, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_CD_sector_prefix_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_sectorPrefix, out byte[] blockCrc); - - var prefixBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorPrefix, - length = (uint)_sectorPrefix.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 16 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - prefixBlock.compression = CompressionType.None; - prefixBlock.cmpCrc64 = prefixBlock.crc64; - prefixBlock.cmpLength = prefixBlock.length; - blockStream = new MemoryStream(_sectorPrefix); - } - else - { - compressStopwatch.Restart(); - - byte[] cmpBuffer = new byte[_sectorPrefix.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(_sectorPrefix, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = _sectorPrefix; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - prefixBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - prefixBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_prefix, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in prefixBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(prefixBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.CdSectorPrefix }); - - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorSuffix, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_CD_sector_suffix_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_sectorSuffix, out blockCrc); - - prefixBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorSuffix, - length = (uint)_sectorSuffix.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 288 - }; - - if(!_compress) - { - prefixBlock.compression = CompressionType.None; - prefixBlock.cmpCrc64 = prefixBlock.crc64; - prefixBlock.cmpLength = prefixBlock.length; - blockStream = new MemoryStream(_sectorSuffix); - } - else - { - compressStopwatch.Restart(); - - byte[] cmpBuffer = new byte[_sectorSuffix.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(_sectorSuffix, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = _sectorSuffix; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - prefixBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - prefixBlock.compression = CompressionType.Lzma; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_suffix, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in prefixBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(prefixBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.CdSectorSuffix }); - - _index.Add(idxEntry); - blockStream.Close(); - } - else if(_sectorSuffixMs != null && - _sectorSuffixDdt != null && - _sectorPrefixMs != null && - _sectorPrefixDdt != null) - { -#if DEBUG - uint notDumpedPrefixes = 0; - uint correctPrefixes = 0; - uint writtenPrefixes = 0; - uint notDumpedSuffixes = 0; - uint correctSuffixes = 0; - uint writtenSuffixes = 0; - uint correctMode2Form1 = 0; - uint correctMode2Form2 = 0; - uint emptyMode2Form1 = 0; - - for(long i = 0; i < _sectorPrefixDdt.LongLength; i++) - { - switch(_sectorPrefixDdt[i] & CD_XFIX_MASK) - { - case (uint)CdFixFlags.NotDumped: - notDumpedPrefixes++; - - break; - case (uint)CdFixFlags.Correct: - correctPrefixes++; - - break; - default: - { - if((_sectorPrefixDdt[i] & CD_DFIX_MASK) > 0) writtenPrefixes++; - - break; - } - } - } - - for(long i = 0; i < _sectorPrefixDdt.LongLength; i++) - { - switch(_sectorSuffixDdt[i] & CD_XFIX_MASK) - { - case (uint)CdFixFlags.NotDumped: - notDumpedSuffixes++; - - break; - case (uint)CdFixFlags.Correct: - correctSuffixes++; - - break; - case (uint)CdFixFlags.Mode2Form1Ok: - correctMode2Form1++; - - break; - case (uint)CdFixFlags.Mode2Form2Ok: - correctMode2Form2++; - - break; - case (uint)CdFixFlags.Mode2Form2NoCrc: - emptyMode2Form1++; - - break; - default: - { - if((_sectorSuffixDdt[i] & CD_DFIX_MASK) > 0) writtenSuffixes++; - - break; - } - } - } - - AaruLogging.Debug(MODULE_NAME, - Localization - ._0_1_prefixes_are_correct_2_3_prefixes_have_not_been_dumped_4_5_prefixes_have_been_written_to_image, - correctPrefixes, - correctPrefixes / _imageInfo.Sectors, - notDumpedPrefixes, - notDumpedPrefixes / _imageInfo.Sectors, - writtenPrefixes, - writtenPrefixes / _imageInfo.Sectors); - - AaruLogging.Debug(MODULE_NAME, - Localization - ._0_1_suffixes_are_correct_2_3_suffixes_have_not_been_dumped_4_5_suffixes_have_been_written_to_image, - correctSuffixes, - correctSuffixes / _imageInfo.Sectors, - notDumpedSuffixes, - notDumpedSuffixes / _imageInfo.Sectors, - writtenSuffixes, - writtenSuffixes / _imageInfo.Sectors); - - AaruLogging.Debug(MODULE_NAME, - Localization - ._0_1_MODE_2_Form_1_are_correct_2_3_MODE_2_Form_2_are_correct_4_5_MODE_2_Form_2_have_empty_CRC, - correctMode2Form1, - correctMode2Form1 / _imageInfo.Sectors, - correctMode2Form2, - correctMode2Form2 / _imageInfo.Sectors, - emptyMode2Form1, - emptyMode2Form1 / _imageInfo.Sectors); -#endif - - idxEntry = new IndexEntry - { - blockType = BlockType.DeDuplicationTable, - dataType = DataType.CdSectorPrefixCorrected, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_CompactDisc_sector_prefix_DDT_to_position_0, - idxEntry.offset); - - var ddtHeader = new DdtHeader - { - identifier = BlockType.DeDuplicationTable, - type = DataType.CdSectorPrefixCorrected, - compression = _compressionAlgorithm, - entries = (ulong)_sectorPrefixDdt.LongLength, - length = (ulong)(_sectorPrefixDdt.LongLength * sizeof(uint)) - }; - - _crc64 = new Crc64Context(); - byte[] ddtEntries = MemoryMarshal.Cast(_sectorPrefixDdt).ToArray(); - _crc64.Update(ddtEntries); - - byte[] cmpBuffer = new byte[ddtEntries.Length + 262144]; - - int cmpLen; - byte[] lzmaProperties = []; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(ddtEntries, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = ddtEntries; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - ddtHeader.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - var cmpCrc64Context = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc64Context.Update(lzmaProperties); - - cmpCrc64Context.Update(blockStream.ToArray()); - ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in ddtHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_compressionAlgorithm == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t is - { - blockType: BlockType.DeDuplicationTable, - dataType : DataType.CdSectorPrefixCorrected - }); - - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.DeDuplicationTable, - dataType = DataType.CdSectorSuffixCorrected, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_CompactDisc_sector_suffix_DDT_to_position_0, - idxEntry.offset); - - ddtHeader = new DdtHeader - { - identifier = BlockType.DeDuplicationTable, - type = DataType.CdSectorSuffixCorrected, - compression = _compressionAlgorithm, - entries = (ulong)_sectorSuffixDdt.LongLength, - length = (ulong)(_sectorSuffixDdt.LongLength * sizeof(uint)) - }; - - _crc64 = new Crc64Context(); - ddtEntries = MemoryMarshal.Cast(_sectorSuffixDdt).ToArray(); - _crc64.Update(ddtEntries); - - cmpBuffer = new byte[ddtEntries.Length + 262144]; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(ddtEntries, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = ddtEntries; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - ddtHeader.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - cmpCrc64Context = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc64Context.Update(lzmaProperties); - - cmpCrc64Context.Update(blockStream.ToArray()); - ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in ddtHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_compressionAlgorithm == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t is - { - blockType: BlockType.DeDuplicationTable, - dataType : DataType.CdSectorSuffixCorrected - }); - - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorPrefixCorrected, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_CD_sector_corrected_prefix_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_sectorPrefixMs.GetBuffer(), (uint)_sectorPrefixMs.Length, out byte[] blockCrc); - - var prefixBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorPrefixCorrected, - length = (uint)_sectorPrefixMs.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 16 - }; - - lzmaProperties = null; - - if(!_compress) - { - prefixBlock.compression = CompressionType.None; - prefixBlock.cmpCrc64 = prefixBlock.crc64; - prefixBlock.cmpLength = prefixBlock.length; - blockStream = _sectorPrefixMs; - } - else - { - compressStopwatch.Restart(); - - byte[] sectorPrefixBuffer = _sectorPrefixMs.ToArray(); - cmpBuffer = new byte[sectorPrefixBuffer.Length + 262144]; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(sectorPrefixBuffer, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = sectorPrefixBuffer; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - prefixBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - prefixBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_prefix, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in prefixBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(prefixBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t is - { - blockType: BlockType.DataBlock, - dataType : DataType.CdSectorPrefixCorrected - }); - - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorSuffixCorrected, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_CD_sector_corrected_suffix_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_sectorSuffixMs.GetBuffer(), (uint)_sectorSuffixMs.Length, out blockCrc); - - var suffixBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorSuffixCorrected, - length = (uint)_sectorSuffixMs.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 288 - }; - - lzmaProperties = null; - - if(!_compress) - { - suffixBlock.compression = CompressionType.None; - suffixBlock.cmpCrc64 = suffixBlock.crc64; - suffixBlock.cmpLength = suffixBlock.length; - blockStream = _sectorSuffixMs; - } - else - { - compressStopwatch.Restart(); - - byte[] sectorSuffixBuffer = _sectorPrefixMs.ToArray(); - cmpBuffer = new byte[sectorSuffixBuffer.Length + 262144]; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(sectorSuffixBuffer, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = sectorSuffixBuffer; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - suffixBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - suffixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - suffixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - suffixBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_suffix, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in suffixBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(suffixBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t is - { - blockType: BlockType.DataBlock, - dataType : DataType.CdSectorSuffixCorrected - }); - - _index.Add(idxEntry); - } - - if(_mode2Subheaders != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CompactDiscMode2Subheader, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_CD_MODE2_subheaders_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_mode2Subheaders, out byte[] blockCrc); - - var subheaderBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CompactDiscMode2Subheader, - length = (uint)_mode2Subheaders.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 8 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - subheaderBlock.compression = CompressionType.None; - subheaderBlock.cmpCrc64 = subheaderBlock.crc64; - subheaderBlock.cmpLength = subheaderBlock.length; - blockStream = new MemoryStream(_mode2Subheaders); - } - else - { - compressStopwatch.Restart(); - - byte[] cmpBuffer = new byte[_mode2Subheaders.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(_mode2Subheaders, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = _mode2Subheaders; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - subheaderBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - subheaderBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - subheaderBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - subheaderBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_MODE2_subheaders, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in subheaderBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(subheaderBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t is - { - blockType: BlockType.DataBlock, - dataType : DataType.CompactDiscMode2Subheader - }); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorSubchannel != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorSubchannel, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_CD_subchannel_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_sectorSubchannel, out byte[] blockCrc); - - var subchannelBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorSubchannel, - length = (uint)_sectorSubchannel.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 96 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - subchannelBlock.compression = CompressionType.None; - subchannelBlock.cmpCrc64 = subchannelBlock.crc64; - subchannelBlock.cmpLength = subchannelBlock.length; - blockStream = new MemoryStream(_sectorSubchannel); - } - else - { - compressStopwatch.Restart(); - byte[] transformedSubchannel = ClauniaSubchannelTransform(_sectorSubchannel); - - byte[] cmpBuffer = new byte[transformedSubchannel.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(transformedSubchannel, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = transformedSubchannel; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - subchannelBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - subchannelBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - - subchannelBlock.compression = _compressionAlgorithm == CompressionType.Lzma - ? CompressionType.LzmaClauniaSubchannelTransform - : _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_subchannel, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in subchannelBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(subchannelBlock.compression is CompressionType.Lzma - or CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t is - { - blockType: BlockType.DataBlock, dataType: DataType.CdSectorSubchannel - }); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorCprMai != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.DvdSectorCprMai, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_DVD_CPR_MAI_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_sectorCprMai, out byte[] blockCrc); - - var cprMaiBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.DvdSectorCprMai, - length = (uint)_sectorCprMai.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 6 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - cprMaiBlock.compression = CompressionType.None; - cprMaiBlock.cmpCrc64 = cprMaiBlock.crc64; - cprMaiBlock.cmpLength = cprMaiBlock.length; - blockStream = new MemoryStream(_sectorCprMai); - } - else - { - compressStopwatch.Restart(); - - byte[] cmpBuffer = new byte[_sectorCprMai.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(_sectorCprMai, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = _sectorCprMai; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - cprMaiBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - cprMaiBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - cprMaiBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - cprMaiBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_CPR_MAI, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in cprMaiBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(cprMaiBlock.compression is CompressionType.Lzma - or CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorCprMai }); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorId != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.DvdSectorId, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_DVD_ID_block_to_position_0, idxEntry.offset); - - Crc64Context.Data(_sectorId, out byte[] blockCrc); - - var idBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.DvdSectorId, - length = (uint)_sectorId.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 4 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - idBlock.compression = CompressionType.None; - idBlock.cmpCrc64 = idBlock.crc64; - idBlock.cmpLength = idBlock.length; - blockStream = new MemoryStream(_sectorId); - } - else - { - compressStopwatch.Restart(); - - byte[] cmpBuffer = new byte[_sectorId.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(_sectorId, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = _sectorId; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - idBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) idBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - idBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - idBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_ID, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in idBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(idBlock.compression is CompressionType.Lzma or CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorId }); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorIed != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.DvdSectorIed, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_DVD_IED_block_to_position_0, idxEntry.offset); - - Crc64Context.Data(_sectorIed, out byte[] blockCrc); - - var iedBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.DvdSectorIed, - length = (uint)_sectorIed.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 2 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - iedBlock.compression = CompressionType.None; - iedBlock.cmpCrc64 = iedBlock.crc64; - iedBlock.cmpLength = iedBlock.length; - blockStream = new MemoryStream(_sectorIed); - } - else - { - compressStopwatch.Restart(); - - byte[] cmpBuffer = new byte[_sectorIed.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(_sectorIed, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = _sectorIed; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - iedBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) iedBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - iedBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - iedBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_IED, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in iedBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(iedBlock.compression is CompressionType.Lzma or CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorIed }); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorEdc != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.DvdSectorEdc, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_DVD_EDC_block_to_position_0, idxEntry.offset); - - Crc64Context.Data(_sectorEdc, out byte[] blockCrc); - - var edcBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.DvdSectorEdc, - length = (uint)_sectorEdc.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 4 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - edcBlock.compression = CompressionType.None; - edcBlock.cmpCrc64 = edcBlock.crc64; - edcBlock.cmpLength = edcBlock.length; - blockStream = new MemoryStream(_sectorEdc); - } - else - { - compressStopwatch.Restart(); - - byte[] cmpBuffer = new byte[_sectorEdc.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(_sectorEdc, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = _sectorEdc; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - edcBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) edcBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - edcBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - edcBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_EDC, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in edcBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(edcBlock.compression is CompressionType.Lzma or CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorEdc }); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorDecryptedTitleKey != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.DvdSectorTitleKeyDecrypted, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_decrypted_DVD_title_key_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_sectorDecryptedTitleKey, out byte[] blockCrc); - - var titleKeyBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.DvdSectorTitleKeyDecrypted, - length = (uint)_sectorDecryptedTitleKey.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 5 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - titleKeyBlock.compression = CompressionType.None; - titleKeyBlock.cmpCrc64 = titleKeyBlock.crc64; - titleKeyBlock.cmpLength = titleKeyBlock.length; - blockStream = new MemoryStream(_sectorDecryptedTitleKey); - } - else - { - compressStopwatch.Restart(); - - byte[] cmpBuffer = new byte[_sectorDecryptedTitleKey.Length + 262144]; - - int cmpLen; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(_sectorDecryptedTitleKey, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273); - - break; - case CompressionType.None: - cmpBuffer = _sectorDecryptedTitleKey; - cmpLen = cmpBuffer.Length; - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - titleKeyBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - titleKeyBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - titleKeyBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - titleKeyBlock.compression = _compressionAlgorithm; - - compressStopwatch.Stop(); - - AaruLogging.Debug(MODULE_NAME, - Localization.Took_0_seconds_to_compress_decrypted_DVD_title_keys, - compressStopwatch.Elapsed.TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in titleKeyBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(titleKeyBlock.compression is CompressionType.Lzma - or CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t is - { - blockType: BlockType.DataBlock, - dataType : DataType.DvdSectorTitleKeyDecrypted - }); - - _index.Add(idxEntry); - blockStream.Close(); - } - - List trackEntries = []; - List compactDiscIndexEntries = []; - - foreach(Track track in Tracks) - { - _trackFlags.TryGetValue((byte)track.Sequence, out byte flags); - _trackIsrcs.TryGetValue((byte)track.Sequence, out string isrc); - - if((flags & (int)CdFlags.DataTrack) == 0 && track.Type != TrackType.Audio) - flags += (byte)CdFlags.DataTrack; - - trackEntries.Add(new TrackEntry - { - sequence = (byte)track.Sequence, - type = track.Type, - start = (long)track.StartSector, - end = (long)track.EndSector, - pregap = (long)track.Pregap, - session = (byte)track.Session, - isrc = isrc, - flags = flags - }); - - switch(track.Indexes.ContainsKey(0)) - { - case false when track.Pregap > 0: - track.Indexes[0] = (int)track.StartSector; - track.Indexes[1] = (int)(track.StartSector + track.Pregap); - - break; - case false when !track.Indexes.ContainsKey(1): - track.Indexes[0] = (int)track.StartSector; - - break; - } - - compactDiscIndexEntries.AddRange(track.Indexes.Select(trackIndex => new CompactDiscIndexEntry - { - Index = trackIndex.Key, - Lba = trackIndex.Value, - Track = (ushort)track.Sequence - })); - } - - // If there are tracks build the tracks block - if(trackEntries.Count > 0) - { - blockStream = new MemoryStream(); - - foreach(TrackEntry entry in trackEntries) - { - _structurePointer = - System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf()); - - _structureBytes = new byte[Marshal.SizeOf()]; - System.Runtime.InteropServices.Marshal.StructureToPtr(entry, _structurePointer, true); - - System.Runtime.InteropServices.Marshal.Copy(_structurePointer, - _structureBytes, - 0, - _structureBytes.Length); - - System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); - blockStream.Write(_structureBytes, 0, _structureBytes.Length); - } - - Crc64Context.Data(blockStream.ToArray(), out byte[] trksCrc); - - var trkHeader = new TracksHeader - { - identifier = BlockType.TracksBlock, - entries = (ushort)trackEntries.Count, - crc64 = BitConverter.ToUInt64(trksCrc, 0) - }; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_tracks_to_position_0, _imageStream.Position); - - _index.RemoveAll(t => t is { blockType: BlockType.TracksBlock, dataType: DataType.NoData }); - - _index.Add(new IndexEntry - { - blockType = BlockType.TracksBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in trkHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - } - - // If there are track indexes bigger than 1 - if(compactDiscIndexEntries.Any(i => i.Index > 1)) - { - blockStream = new MemoryStream(); - - foreach(CompactDiscIndexEntry entry in compactDiscIndexEntries) - { - _structurePointer = - System.Runtime.InteropServices.Marshal - .AllocHGlobal(Marshal.SizeOf()); - - _structureBytes = new byte[Marshal.SizeOf()]; - System.Runtime.InteropServices.Marshal.StructureToPtr(entry, _structurePointer, true); - - System.Runtime.InteropServices.Marshal.Copy(_structurePointer, - _structureBytes, - 0, - _structureBytes.Length); - - System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); - blockStream.Write(_structureBytes, 0, _structureBytes.Length); - } - - Crc64Context.Data(blockStream.ToArray(), out byte[] cdixCrc); - - var cdixHeader = new CompactDiscIndexesHeader - { - identifier = BlockType.CompactDiscIndexesBlock, - entries = (ushort)compactDiscIndexEntries.Count, - crc64 = BitConverter.ToUInt64(cdixCrc, 0) - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_compact_disc_indexes_to_position_0, - _imageStream.Position); - - _index.RemoveAll(t => t is - { - blockType: BlockType.CompactDiscIndexesBlock, - dataType : DataType.NoData - }); - - _index.Add(new IndexEntry - { - blockType = BlockType.CompactDiscIndexesBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in cdixHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - } - - break; - case MetadataMediaType.BlockMedia: - if(_sectorSubchannel != null && - _imageInfo.MediaType is MediaType.AppleFileWare - or MediaType.AppleSonySS - or MediaType.AppleSonyDS - or MediaType.AppleProfile - or MediaType.AppleWidget - or MediaType.PriamDataTower) - { - DataType tagType = _imageInfo.MediaType switch - { - MediaType.AppleSonySS or MediaType.AppleSonyDS => DataType.AppleSonyTag, - MediaType.AppleFileWare or MediaType.AppleProfile or MediaType.AppleWidget => - DataType.AppleProfileTag, - MediaType.PriamDataTower => DataType.PriamDataTowerTag, - _ => DataType.NoData - }; - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = tagType, - offset = (ulong)_imageStream.Position - }; - - AaruLogging.Debug(MODULE_NAME, - Localization.Writing_apple_sector_tag_block_to_position_0, - idxEntry.offset); - - Crc64Context.Data(_sectorSubchannel, out byte[] blockCrc); - - var subchannelBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = tagType, - length = (uint)_sectorSubchannel.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0) - }; - - subchannelBlock.sectorSize = _imageInfo.MediaType switch - { - MediaType.AppleSonySS or MediaType.AppleSonyDS => 12, - MediaType.AppleFileWare - or MediaType.AppleProfile - or MediaType.AppleWidget => 20, - MediaType.PriamDataTower => 24, - _ => subchannelBlock.sectorSize - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - subchannelBlock.compression = CompressionType.None; - subchannelBlock.cmpCrc64 = subchannelBlock.crc64; - subchannelBlock.cmpLength = subchannelBlock.length; - blockStream = new MemoryStream(_sectorSubchannel); - } - else - { - byte[] cmpBuffer = new byte[_sectorSubchannel.Length + 262144]; - - int cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(_sectorSubchannel, - cmpBuffer, - out lzmaProperties, - 9, - _dictionarySize, - 4, - 0, - 2, - 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - subchannelBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - subchannelBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - subchannelBlock.compression = _compressionAlgorithm; - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in subchannelBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(subchannelBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == tagType); - - _index.Add(idxEntry); - blockStream.Close(); - } - - break; - } - - // Write metadata if present - SetMetadataFromTags(); - var metadataBlock = new MetadataBlock(); - blockStream = new MemoryStream(); - blockStream.Write(new byte[Marshal.SizeOf()], 0, Marshal.SizeOf()); - byte[] tmpUtf16Le; - - if(_imageInfo is { MediaSequence: > 0, LastMediaSequence: > 0 }) - { - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaSequence = _imageInfo.MediaSequence; - metadataBlock.lastMediaSequence = _imageInfo.LastMediaSequence; - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.Creator)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.Creator); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.creatorOffset = (uint)blockStream.Position; - metadataBlock.creatorLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.Comments)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.Comments); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.commentsOffset = (uint)blockStream.Position; - metadataBlock.commentsLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaTitle)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaTitle); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaTitleOffset = (uint)blockStream.Position; - metadataBlock.mediaTitleLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaManufacturer)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaManufacturer); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaManufacturerOffset = (uint)blockStream.Position; - metadataBlock.mediaManufacturerLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaModel)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaModel); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaModelOffset = (uint)blockStream.Position; - metadataBlock.mediaModelLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaSerialNumber)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaSerialNumber); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaSerialNumberOffset = (uint)blockStream.Position; - metadataBlock.mediaSerialNumberLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaBarcode)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaBarcode); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaBarcodeOffset = (uint)blockStream.Position; - metadataBlock.mediaBarcodeLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaPartNumber)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaPartNumber); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaPartNumberOffset = (uint)blockStream.Position; - metadataBlock.mediaPartNumberLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.DriveManufacturer)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveManufacturer); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.driveManufacturerOffset = (uint)blockStream.Position; - metadataBlock.driveManufacturerLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.DriveModel)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveModel); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.driveModelOffset = (uint)blockStream.Position; - metadataBlock.driveModelLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveSerialNumber); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.driveSerialNumberOffset = (uint)blockStream.Position; - metadataBlock.driveSerialNumberLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveFirmwareRevision); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.driveFirmwareRevisionOffset = (uint)blockStream.Position; - metadataBlock.driveFirmwareRevisionLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write([0, 0], 0, 2); - } - - // Check if we set up any metadata earlier, then write its block - if(metadataBlock.identifier == BlockType.MetadataBlock) - { - AaruLogging.Debug(MODULE_NAME, Localization.Writing_metadata_to_position_0, _imageStream.Position); - - metadataBlock.blockSize = (uint)blockStream.Length; - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in metadataBlock); - blockStream.Position = 0; - blockStream.Write(_structureBytes, 0, _structureBytes.Length); - _index.RemoveAll(t => t is { blockType: BlockType.MetadataBlock, dataType: DataType.NoData }); - - _index.Add(new IndexEntry - { - blockType = BlockType.MetadataBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - } - - _header.indexOffset = (ulong)_imageStream.Position; - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_index_to_position_0, _header.indexOffset); - - blockStream = new MemoryStream(); - - // Write index to memory - foreach(IndexEntry entry in _index) - { - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, in entry); - blockStream.Write(_structureBytes, 0, _structureBytes.Length); - } - - Crc64Context.Data(blockStream.ToArray(), out byte[] idxCrc); - - if(_index.Count > ushort.MaxValue) - { - _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, in 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, in idxHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - } - - // Write index to disk - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - AaruLogging.Debug(MODULE_NAME, Localization.Writing_header); - _header.lastWrittenTime = DateTime.UtcNow.ToFileTimeUtc(); - _imageStream.Position = 0; - _structurePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf()); - _structureBytes = new byte[Marshal.SizeOf()]; - System.Runtime.InteropServices.Marshal.StructureToPtr(_header, _structurePointer, true); - System.Runtime.InteropServices.Marshal.Copy(_structurePointer, _structureBytes, 0, _structureBytes.Length); - System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - _imageStream.Flush(); - _imageStream.Close(); - GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true); - - IsWriting = false; - ErrorMessage = ""; - - return true; - } - - /// - public bool SetImageInfo(ImageInfo imageInfo) - { - _imageInfo.Creator = imageInfo.Creator; - _imageInfo.Comments = imageInfo.Comments; - _imageInfo.MediaManufacturer = imageInfo.MediaManufacturer; - _imageInfo.MediaModel = imageInfo.MediaModel; - _imageInfo.MediaSerialNumber = imageInfo.MediaSerialNumber; - _imageInfo.MediaBarcode = imageInfo.MediaBarcode; - _imageInfo.MediaPartNumber = imageInfo.MediaPartNumber; - _imageInfo.MediaSequence = imageInfo.MediaSequence; - _imageInfo.LastMediaSequence = imageInfo.LastMediaSequence; - _imageInfo.DriveManufacturer = imageInfo.DriveManufacturer; - _imageInfo.DriveModel = imageInfo.DriveModel; - _imageInfo.DriveSerialNumber = imageInfo.DriveSerialNumber; - _imageInfo.DriveFirmwareRevision = imageInfo.DriveFirmwareRevision; - _imageInfo.MediaTitle = imageInfo.MediaTitle; - - return true; - } - - /// - public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack) - { - if(!IsWriting) - { - ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image; - - return false; - } - - if(_imageInfo.MetadataMediaType != MetadataMediaType.BlockMedia) - { - ErrorMessage = Localization.Tried_to_set_geometry_on_a_media_that_doesnt_support_it; - - return false; - } - - _geometryBlock = new GeometryBlock - { - identifier = BlockType.GeometryBlock, - cylinders = cylinders, - heads = heads, - sectorsPerTrack = sectorsPerTrack - }; - - ErrorMessage = ""; - - return true; - } - - /// - public bool WriteSectorTag(byte[] data, ulong sectorAddress, SectorTagType tag) - { - if(!IsWriting) - { - ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image; - - return false; - } - - if(sectorAddress >= _imageInfo.Sectors) - { - ErrorMessage = Localization.Tried_to_write_past_image_size; - - return false; - } - - Track track; - - switch(tag) - { - case SectorTagType.CdTrackFlags: - case SectorTagType.CdTrackIsrc: - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) - { - ErrorMessage = Localization.Incorrect_tag_for_disk_type; - - return false; - } - - track = Tracks.FirstOrDefault(trk => sectorAddress == trk.Sequence); - - if(track is null || track.Sequence == 0 && track.StartSector == 0 && track.EndSector == 0) - { - ErrorMessage = string.Format(Localization.Cant_find_track_0, sectorAddress); - - return false; - } - - break; - case SectorTagType.CdSectorSubchannel: - if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc) - { - ErrorMessage = Localization.Incorrect_tag_for_disk_type; - - return false; - } - - track = Tracks.FirstOrDefault(trk => sectorAddress >= trk.StartSector && - sectorAddress <= trk.EndSector); - - if(track is { Sequence: 0, StartSector: 0, EndSector: 0 }) track.Type = TrackType.Data; - - break; - } - - switch(tag) - { - case SectorTagType.CdTrackFlags: - { - if(data.Length != 1) - { - ErrorMessage = Localization.Incorrect_data_size_for_track_flags; - - return false; - } - - _trackFlags[(byte)sectorAddress] = data[0]; - - return true; - } - - case SectorTagType.CdTrackIsrc: - { - if(data != null) _trackIsrcs[(byte)sectorAddress] = Encoding.UTF8.GetString(data); - - return true; - } - - case SectorTagType.CdSectorSubchannel: - { - if(data.Length != 96) - { - ErrorMessage = Localization.Incorrect_data_size_for_subchannel; - - return false; - } - - _sectorSubchannel ??= new byte[_imageInfo.Sectors * 96]; - - Array.Copy(data, 0, _sectorSubchannel, (int)(96 * sectorAddress), 96); - - return true; - } - - case SectorTagType.DvdSectorCmi: - { - if(data.Length != 1) - { - ErrorMessage = Localization.Incorrect_data_size_for_CMI; - - return false; - } - - _sectorCprMai ??= new byte[_imageInfo.Sectors * 6]; - - Array.Copy(data, 0, _sectorCprMai, (int)(6 * sectorAddress), 1); - - return true; - } - - case SectorTagType.DvdSectorTitleKey: - { - if(data.Length != 5) - { - ErrorMessage = Localization.Incorrect_data_size_for_title_key; - - return false; - } - - _sectorCprMai ??= new byte[_imageInfo.Sectors * 6]; - - Array.Copy(data, 0, _sectorCprMai, (int)(1 + 6 * sectorAddress), 5); - - return true; - } - - case SectorTagType.DvdSectorInformation: - { - if(data.Length != 1) - { - ErrorMessage = Localization.Incorrect_data_size_for_dvd_id_information; - - return false; - } - - _sectorId ??= new byte[_imageInfo.Sectors * 4]; - - Array.Copy(data, 0, _sectorId, (int)(4 * sectorAddress), 1); - - return true; - } - - case SectorTagType.DvdSectorNumber: - { - if(data.Length != 3) - { - ErrorMessage = Localization.Incorrect_data_size_for_dvd_id_number; - - return false; - } - - _sectorId ??= new byte[_imageInfo.Sectors * 4]; - - Array.Copy(data, 0, _sectorId, (int)(1 + 4 * sectorAddress), 3); - - return true; - } - - case SectorTagType.DvdSectorIed: - { - if(data.Length != 2) - { - ErrorMessage = Localization.Incorrect_data_size_for_ied; - - return false; - } - - _sectorIed ??= new byte[_imageInfo.Sectors * 2]; - - Array.Copy(data, 0, _sectorIed, (int)(2 * sectorAddress), 2); - - return true; - } - - case SectorTagType.DvdSectorEdc: - { - if(data.Length != 4) - { - ErrorMessage = Localization.Incorrect_data_size_for_edc; - - return false; - } - - _sectorEdc ??= new byte[_imageInfo.Sectors * 4]; - - Array.Copy(data, 0, _sectorEdc, (int)(4 * sectorAddress), 4); - - return true; - } - - case SectorTagType.DvdTitleKeyDecrypted: - { - if(data.Length != 5) - { - ErrorMessage = Localization.Incorrect_data_size_for_decrypted_title_key; - - return false; - } - - _sectorDecryptedTitleKey ??= new byte[_imageInfo.Sectors * 5]; - - Array.Copy(data, 0, _sectorDecryptedTitleKey, (int)(5 * sectorAddress), 5); - - return true; - } - - default: - ErrorMessage = string.Format(Localization.Dont_know_how_to_write_sector_tag_type_0, tag); - - return false; - } - } - - /// - public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag) - { - if(!IsWriting) - { - ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image; - - return false; - } - - if(sectorAddress + length > _imageInfo.Sectors) - { - ErrorMessage = Localization.Tried_to_write_past_image_size; - - return false; - } - - switch(tag) - { - case SectorTagType.CdTrackFlags: - case SectorTagType.CdTrackIsrc: - return WriteSectorTag(data, sectorAddress, tag); - case SectorTagType.CdSectorSubchannel: - { - if(data.Length % 96 != 0) - { - ErrorMessage = Localization.Incorrect_data_size_for_subchannel; - - return false; - } - - _sectorSubchannel ??= new byte[_imageInfo.Sectors * 96]; - - if(sectorAddress * 96 + length * 96 > (ulong)_sectorSubchannel.LongLength) - { - ErrorMessage = Localization.Tried_to_write_more_data_than_possible; - - return false; - } - - Array.Copy(data, 0, _sectorSubchannel, (int)(96 * sectorAddress), 96 * length); - - return true; - } - - default: - ErrorMessage = string.Format(Localization.Dont_know_how_to_write_sector_tag_type_0, tag); - - return false; - } - } - - /// - public bool SetDumpHardware(List dumpHardware) - { - DumpHardware = dumpHardware; - - return true; - } - - /// - public bool SetMetadata(Metadata metadata) - { - AaruMetadata = metadata; - - return true; - } - -#endregion -} \ No newline at end of file