diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs
index 734166e5e..2cca06f7c 100644
--- a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs
+++ b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs
@@ -47,6 +47,7 @@ using Aaru.Core.Logging;
using Aaru.Decoders.CD;
using Aaru.Decoders.SCSI;
using Aaru.Devices;
+using Aaru.Localization;
using Aaru.Logging;
using Humanizer;
using Track = Aaru.CommonTypes.Structs.Track;
@@ -762,6 +763,7 @@ partial class Dump
mhddLog.Write(i + r, _speedStopwatch.Elapsed.TotalMilliseconds);
extents.Add(i + r, 1, true);
_writeStopwatch.Restart();
+ SectorStatus sectorStatus = SectorStatus.Dumped;
if(supportedSubchannel != MmcSubchannel.None)
{
@@ -772,14 +774,33 @@ partial class Dump
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
+ if(_paranoia)
+ {
+ // Check valid sector
+ CdChecksums.CheckCdSector(data,
+ out bool? correctEccP,
+ out bool? correctEccQ,
+ out bool? correctEdc);
+
+ if(correctEdc != true || correctEccP != true || correctEccQ != true)
+ {
+ sectorStatus = SectorStatus.Errored;
+ _resume.BadBlocks.Add(i + r);
+
+ if(correctEdc != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_EDC_in_sector_0, i + r));
+
+ if(correctEccP != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_P_in_sector_0, i + r));
+
+ if(correctEccQ != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_Q_in_sector_0, i + r));
+ }
+ }
+
if(supportsLongSectors)
{
- outputFormat.WriteSectorsLong(data,
- i + r,
- false,
- 1,
- Enumerable.Repeat(SectorStatus.Dumped, (int)blocksToRead)
- .ToArray());
+ outputFormat.WriteSectorsLong(data, i + r, false, 1, [sectorStatus]);
}
else
{
@@ -797,8 +818,7 @@ partial class Dump
i,
false,
blocksToRead,
- Enumerable.Repeat(SectorStatus.Dumped, (int)blocksToRead)
- .ToArray());
+ Enumerable.Repeat(sectorStatus, (int)blocksToRead).ToArray());
}
bool indexesChanged = Media.CompactDisc.WriteSubchannelToImage(supportedSubchannel,
@@ -844,8 +864,32 @@ partial class Dump
}
else
{
+ if(_paranoia)
+ {
+ // Check valid sector
+ CdChecksums.CheckCdSector(cmdBuf,
+ out bool? correctEccP,
+ out bool? correctEccQ,
+ out bool? correctEdc);
+
+ if(correctEdc != true || correctEccP != true || correctEccQ != true)
+ {
+ sectorStatus = SectorStatus.Errored;
+ _resume.BadBlocks.Add(i + r);
+
+ if(correctEdc != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_EDC_in_sector_0, i + r));
+
+ if(correctEccP != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_P_in_sector_0, i + r));
+
+ if(correctEccQ != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_Q_in_sector_0, i + r));
+ }
+ }
+
if(supportsLongSectors)
- outputFormat.WriteSectorsLong(cmdBuf, i + r, false, 1, [SectorStatus.Dumped]);
+ outputFormat.WriteSectorsLong(cmdBuf, i + r, false, 1, [sectorStatus]);
else
{
var cooked = new MemoryStream();
@@ -862,8 +906,7 @@ partial class Dump
i,
false,
blocksToRead,
- Enumerable.Repeat(SectorStatus.Dumped, (int)blocksToRead)
- .ToArray());
+ Enumerable.Repeat(sectorStatus, (int)blocksToRead).ToArray());
}
}
@@ -987,29 +1030,53 @@ partial class Dump
if(supportedSubchannel != MmcSubchannel.None)
{
- var data = new byte[sectorSize * blocksToRead];
- var sub = new byte[subSize * blocksToRead];
+ var data = new byte[sectorSize * blocksToRead];
+ var sub = new byte[subSize * blocksToRead];
+ var sectorStatus = new SectorStatus[blocksToRead];
+ var sector = new byte[sectorSize];
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(cmdBuf, (int)(0 + b * blockSize), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(sectorSize + b * blockSize), sub, subSize * b, subSize);
+
+ Array.Copy(cmdBuf, (int)(0 + b * blockSize), sector, 0, sectorSize);
+
+ sectorStatus[b] = SectorStatus.Dumped;
+
+ if(inData && _paranoia)
+ {
+ // Check valid sector
+ CdChecksums.CheckCdSector(sector,
+ out bool? correctEccP,
+ out bool? correctEccQ,
+ out bool? correctEdc);
+
+ if(correctEdc != true || correctEccP != true || correctEccQ != true)
+ {
+ sectorStatus[b] = SectorStatus.Errored;
+ _resume.BadBlocks.Add(i + (ulong)b);
+
+ if(correctEdc != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_EDC_in_sector_0, i + (ulong)b));
+
+ if(correctEccP != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_P_in_sector_0, i + (ulong)b));
+
+ if(correctEccQ != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_Q_in_sector_0, i + (ulong)b));
+ }
+ }
}
if(supportsLongSectors)
{
- outputFormat.WriteSectorsLong(data,
- i,
- false,
- blocksToRead,
- Enumerable.Repeat(SectorStatus.Dumped, (int)blocksToRead)
- .ToArray());
+ outputFormat.WriteSectorsLong(data, i, false, blocksToRead, sectorStatus);
}
else
{
var cooked = new MemoryStream();
- var sector = new byte[sectorSize];
for(var b = 0; b < blocksToRead; b++)
{
@@ -1018,11 +1085,7 @@ partial class Dump
cooked.Write(cookedSector, 0, cookedSector.Length);
}
- outputFormat.WriteSectors(cooked.ToArray(),
- i,
- false,
- blocksToRead,
- Enumerable.Repeat(SectorStatus.Dumped, (int)blocksToRead).ToArray());
+ outputFormat.WriteSectors(cooked.ToArray(), i, false, blocksToRead, sectorStatus);
}
bool indexesChanged = Media.CompactDisc.WriteSubchannelToImage(supportedSubchannel,
diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs
index 996c322a8..3038cf7e7 100644
--- a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs
+++ b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs
@@ -47,6 +47,7 @@ using Aaru.Core.Logging;
using Aaru.Decoders.CD;
using Aaru.Decoders.SCSI;
using Aaru.Devices;
+using Aaru.Localization;
using Aaru.Logging;
using Track = Aaru.CommonTypes.Structs.Track;
using TrackType = Aaru.CommonTypes.Enums.TrackType;
@@ -466,8 +467,9 @@ partial class Dump
// MEDIUM ERROR, retry with ignore error below
if(decSense is { ASC: 0x11 })
- if(!sectorsNotEvenPartial.Contains(badSector))
- sectorsNotEvenPartial.Add(badSector);
+ {
+ if(!sectorsNotEvenPartial.Contains(badSector)) sectorsNotEvenPartial.Add(badSector);
+ }
}
// Because one block has been partially used to fix the offset
@@ -486,17 +488,61 @@ partial class Dump
false);
}
+ SectorStatus sectorStatus = SectorStatus.Dumped;
+
+
if(!sense && !_dev.Error)
{
- _resume.BadBlocks.Remove(badSector);
- extents.Add(badSector);
- _mediaGraph?.PaintSectorGood(badSector);
+ if(!audioExtents.Contains(badSector) && _paranoia)
+ {
+ var sector = new byte[sectorSize];
+ Array.Copy(cmdBuf, 0, sector, 0, sectorSize);
- UpdateStatus?.Invoke(string.Format(Localization.Core.Correctly_retried_sector_0_in_pass_1,
- badSector,
- pass));
+ // Check valid sector
+ CdChecksums.CheckCdSector(sector,
+ out bool? correctEccP,
+ out bool? correctEccQ,
+ out bool? correctEdc);
- sectorsNotEvenPartial.Remove(badSector);
+ if(correctEdc != true || correctEccP != true || correctEccQ != true)
+ {
+ sectorStatus = SectorStatus.Errored;
+ _mediaGraph?.PaintSectorBad(badSector);
+
+ if(correctEdc != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_EDC_in_sector_0, badSector));
+
+ if(correctEccP != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_P_in_sector_0, badSector));
+
+ if(correctEccQ != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_Q_in_sector_0, badSector));
+ }
+ else
+ {
+ _resume.BadBlocks.Remove(badSector);
+ extents.Add(badSector);
+ _mediaGraph?.PaintSectorGood(badSector);
+
+ UpdateStatus?.Invoke(string.Format(Localization.Core.Correctly_retried_sector_0_in_pass_1,
+ badSector,
+ pass));
+
+ sectorsNotEvenPartial.Remove(badSector);
+ }
+ }
+ else
+ {
+ _resume.BadBlocks.Remove(badSector);
+ extents.Add(badSector);
+ _mediaGraph?.PaintSectorGood(badSector);
+
+ UpdateStatus?.Invoke(string.Format(Localization.Core.Correctly_retried_sector_0_in_pass_1,
+ badSector,
+ pass));
+
+ sectorsNotEvenPartial.Remove(badSector);
+ }
}
else
_errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf.ToArray());
@@ -509,9 +555,9 @@ partial class Dump
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
if(supportsLongSectors)
- outputOptical.WriteSectorLong(data, badSector, false, SectorStatus.Dumped);
+ outputOptical.WriteSectorLong(data, badSector, false, sectorStatus);
else
- outputOptical.WriteSector(Sector.GetUserData(data), badSector, false, SectorStatus.Dumped);
+ outputOptical.WriteSector(Sector.GetUserData(data), badSector, false, sectorStatus);
bool indexesChanged = Media.CompactDisc.WriteSubchannelToImage(supportedSubchannel,
desiredSubchannel,
@@ -542,9 +588,9 @@ partial class Dump
else
{
if(supportsLongSectors)
- outputOptical.WriteSectorLong(cmdBuf, badSector, false, SectorStatus.Dumped);
+ outputOptical.WriteSectorLong(cmdBuf, badSector, false, sectorStatus);
else
- outputOptical.WriteSector(Sector.GetUserData(cmdBuf), badSector, false, SectorStatus.Dumped);
+ outputOptical.WriteSector(Sector.GetUserData(cmdBuf), badSector, false, sectorStatus);
}
}
@@ -697,10 +743,12 @@ partial class Dump
if(supportsLongSectors)
outputOptical.WriteSectorLong(cmdBuf, badSector, false, SectorStatus.Errored);
else
+ {
outputOptical.WriteSector(Sector.GetUserData(cmdBuf),
badSector,
false,
SectorStatus.Errored);
+ }
}
}
diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs
index 5d75d37cb..acec4fb0a 100644
--- a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs
+++ b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs
@@ -46,6 +46,7 @@ using Aaru.Core.Logging;
using Aaru.Decoders.CD;
using Aaru.Decoders.SCSI;
using Aaru.Devices;
+using Aaru.Localization;
using Humanizer;
using Track = Aaru.CommonTypes.Structs.Track;
@@ -392,11 +393,48 @@ partial class Dump
continue;
}
+ SectorStatus sectorStatus = SectorStatus.Dumped;
+
if(!sense && !_dev.Error)
{
- _resume.BadBlocks.Remove(badSector);
- extents.Add(badSector);
- _mediaGraph?.PaintSectorGood(badSector);
+ if(!audioExtents.Contains(badSector) && _paranoia)
+ {
+ var sector = new byte[sectorSize];
+ Array.Copy(cmdBuf, 0, sector, 0, sectorSize);
+
+ // Check valid sector
+ CdChecksums.CheckCdSector(sector,
+ out bool? correctEccP,
+ out bool? correctEccQ,
+ out bool? correctEdc);
+
+ if(correctEdc != true || correctEccP != true || correctEccQ != true)
+ {
+ sectorStatus = SectorStatus.Errored;
+ _mediaGraph?.PaintSectorBad(badSector);
+
+ if(correctEdc != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_EDC_in_sector_0, badSector));
+
+ if(correctEccP != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_P_in_sector_0, badSector));
+
+ if(correctEccQ != true)
+ UpdateStatus?.Invoke(string.Format(UI.Incorrect_ECC_Q_in_sector_0, badSector));
+ }
+ else
+ {
+ _resume.BadBlocks.Remove(badSector);
+ extents.Add(badSector);
+ _mediaGraph?.PaintSectorGood(badSector);
+ }
+ }
+ else
+ {
+ _resume.BadBlocks.Remove(badSector);
+ extents.Add(badSector);
+ _mediaGraph?.PaintSectorGood(badSector);
+ }
}
// Because one block has been partially used to fix the offset
@@ -415,6 +453,7 @@ partial class Dump
false);
}
+
if(supportedSubchannel != MmcSubchannel.None)
{
var data = new byte[sectorSize];
@@ -423,9 +462,9 @@ partial class Dump
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
if(supportsLongSectors)
- outputOptical.WriteSectorLong(data, badSector, false, SectorStatus.Dumped);
+ outputOptical.WriteSectorLong(data, badSector, false, sectorStatus);
else
- outputOptical.WriteSector(Sector.GetUserData(data), badSector, false, SectorStatus.Dumped);
+ outputOptical.WriteSector(Sector.GetUserData(data), badSector, false, sectorStatus);
ulong trkStartBefore = track.StartSector;
@@ -467,9 +506,9 @@ partial class Dump
}
if(supportsLongSectors)
- outputOptical.WriteSectorLong(cmdBuf, badSector, false, SectorStatus.Dumped);
+ outputOptical.WriteSectorLong(cmdBuf, badSector, false, sectorStatus);
else
- outputOptical.WriteSector(Sector.GetUserData(cmdBuf), badSector, false, SectorStatus.Dumped);
+ outputOptical.WriteSector(Sector.GetUserData(cmdBuf), badSector, false, sectorStatus);
}
_trimStopwatch.Stop();
diff --git a/Aaru.Core/Devices/Dumping/Dump.cs b/Aaru.Core/Devices/Dumping/Dump.cs
index 7a212edd5..0b7820f33 100644
--- a/Aaru.Core/Devices/Dumping/Dump.cs
+++ b/Aaru.Core/Devices/Dumping/Dump.cs
@@ -93,6 +93,7 @@ public partial class Dump
readonly string _outputPath;
readonly IBaseWritableImage _outputPlugin;
readonly string _outputPrefix;
+ readonly bool _paranoia;
readonly bool _persistent;
readonly Metadata _preSidecar;
readonly bool _private;
@@ -165,6 +166,7 @@ public partial class Dump
/// How many CD-R(W) run end sectors to ignore and regenerate
/// If set to true creates a graph of the dump.
/// Dimensions of graph in pixels for a square
+ /// Check sectors integrity before writing to image
public Dump(bool doResume, Device dev, string devicePath, IBaseWritableImage outputPlugin, ushort retryPasses,
bool force, bool dumpRaw, bool persistent, bool stopOnError, Resume resume, Encoding encoding,
string outputPrefix, string outputPath, Dictionary formatOptions, Metadata preSidecar,
@@ -172,7 +174,7 @@ public partial class Dump
DumpSubchannel subchannel, int speed, bool @private, bool fixSubchannelPosition, bool retrySubchannel,
bool fixSubchannel, bool fixSubchannelCrc, bool skipCdireadyHole, ErrorLog errorLog,
bool generateSubchannels, uint maximumReadable, bool useBufferedReads, bool storeEncrypted,
- bool titleKeys, uint ignoreCdrRunOuts, bool createGraph, uint dimensions)
+ bool titleKeys, uint ignoreCdrRunOuts, bool createGraph, uint dimensions, bool paranoia)
{
_doResume = doResume;
_dev = dev;
@@ -214,6 +216,7 @@ public partial class Dump
_ignoreCdrRunOuts = ignoreCdrRunOuts;
_createGraph = createGraph;
_dimensions = dimensions;
+ _paranoia = paranoia;
_dumpStopwatch = new Stopwatch();
_sidecarStopwatch = new Stopwatch();
_speedStopwatch = new Stopwatch();
diff --git a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
index f8769416e..c725cfb72 100644
--- a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
@@ -722,7 +722,8 @@ public sealed partial class MediaDumpViewModel : ViewModelBase
false,
10,
true,
- 1080);
+ 1080,
+ false);
new Thread(DoWork).Start();
}
diff --git a/Aaru.Localization/UI.Designer.cs b/Aaru.Localization/UI.Designer.cs
index 5fa3c8778..c65e8dce2 100644
--- a/Aaru.Localization/UI.Designer.cs
+++ b/Aaru.Localization/UI.Designer.cs
@@ -6621,5 +6621,29 @@ namespace Aaru.Localization {
return ResourceManager.GetString("Path_to_log_file", resourceCulture);
}
}
+
+ public static string Incorrect_EDC_in_sector_0 {
+ get {
+ return ResourceManager.GetString("Incorrect_EDC_in_sector_0", resourceCulture);
+ }
+ }
+
+ public static string Incorrect_ECC_P_in_sector_0 {
+ get {
+ return ResourceManager.GetString("Incorrect_ECC_P_in_sector_0", resourceCulture);
+ }
+ }
+
+ public static string Incorrect_ECC_Q_in_sector_0 {
+ get {
+ return ResourceManager.GetString("Incorrect_ECC_Q_in_sector_0", resourceCulture);
+ }
+ }
+
+ public static string Paranoia_help {
+ get {
+ return ResourceManager.GetString("Paranoia_help", resourceCulture);
+ }
+ }
}
}
diff --git a/Aaru.Localization/UI.es.resx b/Aaru.Localization/UI.es.resx
index 548df46d9..e6deb7a17 100644
--- a/Aaru.Localization/UI.es.resx
+++ b/Aaru.Localization/UI.es.resx
@@ -3311,4 +3311,16 @@ Probadores:
Ruta al archivo de registro.
+
+ [red]EDC incorrecto en el sector [violet]{0}[/][/]
+
+
+ [red]ECC P incorrecto en el sector [violet]{0}[/][/]
+
+
+ [red]ECC Q incorrecto en el sector [violet]{0}[/][/]
+
+
+ No confiar en la unidad, comprobar la integridad de los sectores antes de escribirlos en la imagen. Válido sólo para CD/GD.
+
\ No newline at end of file
diff --git a/Aaru.Localization/UI.resx b/Aaru.Localization/UI.resx
index 6a9df3646..7c73895f3 100644
--- a/Aaru.Localization/UI.resx
+++ b/Aaru.Localization/UI.resx
@@ -3386,4 +3386,16 @@ Do you want to continue?
Path to log file.
+
+ [red]Incorrect EDC in sector [violet]{0}[/][/]
+
+
+ [red]Incorrect ECC P in sector [violet]{0}[/][/]
+
+
+ [red]Incorrect ECC Q in sector [violet]{0}[/][/]
+
+
+ Do not trust the drive, check the sectors integrity before writing them to the image. Valid only for CD/GD.
+
\ No newline at end of file
diff --git a/Aaru/Commands/Media/Dump.cs b/Aaru/Commands/Media/Dump.cs
index c062fa55d..d6a730f1d 100644
--- a/Aaru/Commands/Media/Dump.cs
+++ b/Aaru/Commands/Media/Dump.cs
@@ -121,6 +121,7 @@ sealed class DumpMediaCommand : Command
AaruLogging.Debug(MODULE_NAME, "--create-graph={0}", settings.CreateGraph);
AaruLogging.Debug(MODULE_NAME, "--dimensions={0}", settings.Dimensions);
AaruLogging.Debug(MODULE_NAME, "--aaru-metadata={0}", Markup.Escape(settings.AaruMetadata ?? ""));
+ AaruLogging.Debug(MODULE_NAME, "--paranoia={0}", settings.Paranoia);
// TODO: Disabled temporarily
//AaruLogging.DebugWriteLine(MODULE_NAME, "--raw={0}", Markup.Escape(raw ?? ""));
@@ -524,7 +525,8 @@ sealed class DumpMediaCommand : Command
settings.TitleKeys,
(uint)settings.IgnoreCdrRunOuts,
settings.CreateGraph,
- (uint)settings.Dimensions);
+ (uint)settings.Dimensions,
+ settings.Paranoia);
AnsiConsole.Progress()
.AutoClear(true)
@@ -772,6 +774,10 @@ sealed class DumpMediaCommand : Command
[CommandOption("--aaru-metadata")]
[DefaultValue(null)]
public string AaruMetadata { get; init; }
+ [LocalizedDescription(nameof(UI.Paranoia_help))]
+ [CommandOption("--paranoia")]
+ [DefaultValue(false)]
+ public bool Paranoia { get; init; }
[LocalizedDescription(nameof(UI.Device_path))]
[CommandArgument(0, "")]
public string DevicePath { get; init; }