When dumping media if device returns "corrected error", consider it as a good read.

This commit is contained in:
2020-10-17 20:46:43 +01:00
parent ba8b98e6ec
commit 2d3720a9f5
8 changed files with 90 additions and 51 deletions

View File

@@ -3,6 +3,9 @@
<component name="ContentModelStore"> <component name="ContentModelStore">
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/extResources" t="IncludeRecursive" /> <e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/extResources" t="IncludeRecursive" />
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/resharper-host/local/Transient/Rider/v202/SolutionCaches/_Aaru.232757112.00" t="ExcludeRecursive" /> <e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/resharper-host/local/Transient/Rider/v202/SolutionCaches/_Aaru.232757112.00" t="ExcludeRecursive" />
<e p="$APPLICATION_CONFIG_DIR$/consoles/db" t="IncludeRecursive" />
<e p="$APPLICATION_CONFIG_DIR$/extensions" t="IncludeRecursive" />
<e p="$APPLICATION_CONFIG_DIR$/scratches" t="IncludeRecursive" />
<e p="$USER_HOME$/.config/git/ignore" t="IncludeRecursive" /> <e p="$USER_HOME$/.config/git/ignore" t="IncludeRecursive" />
<e p="$APPLICATION_PLUGINS_DIR$/puppet/lib/stubs" t="IncludeRecursive" /> <e p="$APPLICATION_PLUGINS_DIR$/puppet/lib/stubs" t="IncludeRecursive" />
<e p="$USER_HOME$/.nuget/packages/microsoft.net.test.sdk/16.4.0/build/netcoreapp2.1" t="Include"> <e p="$USER_HOME$/.nuget/packages/microsoft.net.test.sdk/16.4.0/build/netcoreapp2.1" t="Include">
@@ -13,6 +16,16 @@
<e p="$USER_HOME$/.nuget/packages/nunit3testadapter/3.15.1/build/netcoreapp2.0/nunit.engine.api.dll" t="Include" /> <e p="$USER_HOME$/.nuget/packages/nunit3testadapter/3.15.1/build/netcoreapp2.0/nunit.engine.api.dll" t="Include" />
<e p="$USER_HOME$/.nuget/packages/nunit3testadapter/3.15.1/build/netcoreapp2.0/nunit.engine.dll" t="Include" /> <e p="$USER_HOME$/.nuget/packages/nunit3testadapter/3.15.1/build/netcoreapp2.0/nunit.engine.dll" t="Include" />
<e p="$PROJECT_DIR$" t="IncludeFlat"> <e p="$PROJECT_DIR$" t="IncludeFlat">
<e p=".git/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Checksums/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.CommonTypes/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Console/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Decoders/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Dto/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/Aaru.Helpers/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/CICMMetadata/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/cuetools.net/info/exclude" t="IncludeRecursive" />
<e p=".git/modules/cuetoolsnet/info/exclude" t="IncludeRecursive" />
<e p=".github/CODE_OF_CONDUCT.md" t="Include" /> <e p=".github/CODE_OF_CONDUCT.md" t="Include" />
<e p=".github/ISSUE_TEMPLATE.md" t="Include" /> <e p=".github/ISSUE_TEMPLATE.md" t="Include" />
<e p=".github/PULL_REQUEST_TEMPLATE.md" t="Include" /> <e p=".github/PULL_REQUEST_TEMPLATE.md" t="Include" />

View File

@@ -56,6 +56,8 @@ namespace Aaru.Core.Devices.Dumping
/// <summary>Dumps an ATA device</summary> /// <summary>Dumps an ATA device</summary>
void Ata() void Ata()
{ {
bool recoveredError;
if(_dumpRaw) if(_dumpRaw)
{ {
if(_force) if(_force)
@@ -288,7 +290,7 @@ namespace Aaru.Core.Devices.Dumping
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)",
(long)i, (long)blocks); (long)i, (long)blocks);
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration); bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration, out _);
if(!error) if(!error)
{ {
@@ -380,11 +382,12 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trimming sector {badSector}"); PulseProgress?.Invoke($"Trimming sector {badSector}");
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration); bool error =
ataReader.ReadBlock(out cmdBuf, badSector, out duration, out recoveredError);
totalDuration += duration; totalDuration += duration;
if(error) if(error && !recoveredError)
continue; continue;
_resume.BadBlocks.Remove(badSector); _resume.BadBlocks.Remove(badSector);
@@ -426,11 +429,12 @@ namespace Aaru.Core.Devices.Dumping
pass, forward ? "forward" : "reverse", pass, forward ? "forward" : "reverse",
_persistent ? "recovering partial data, " : "")); _persistent ? "recovering partial data, " : ""));
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration); bool error =
ataReader.ReadBlock(out cmdBuf, badSector, out duration, out recoveredError);
totalDuration += duration; totalDuration += duration;
if(!error) if(!error || recoveredError)
{ {
_resume.BadBlocks.Remove(badSector); _resume.BadBlocks.Remove(badSector);
extents.Add(badSector); extents.Add(badSector);
@@ -502,11 +506,12 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?. PulseProgress?.
Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)"); Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration); bool error =
ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out recoveredError);
totalDuration += duration; totalDuration += duration;
if(!error) if(!error || recoveredError)
{ {
mhddLog.Write(currentBlock, duration); mhddLog.Write(currentBlock, duration);
ibgLog.Write(currentBlock, currentSpeed * 1024); ibgLog.Write(currentBlock, currentSpeed * 1024);

View File

@@ -81,6 +81,7 @@ namespace Aaru.Core.Devices.Dumping
byte[] readBuffer; byte[] readBuffer;
Modes.DecodedMode? decMode = null; Modes.DecodedMode? decMode = null;
bool ret; bool ret;
bool recoveredError;
if(opticalDisc) if(opticalDisc)
switch(dskType) switch(dskType)
@@ -621,7 +622,7 @@ namespace Aaru.Core.Devices.Dumping
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i, UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
(long)blocks); (long)blocks);
sense = scsiReader.ReadBlocks(out readBuffer, i, blocksToRead, out double cmdDuration); sense = scsiReader.ReadBlocks(out readBuffer, i, blocksToRead, out double cmdDuration, out _);
totalDuration += cmdDuration; totalDuration += cmdDuration;
if(!sense && if(!sense &&
@@ -736,9 +737,10 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trimming sector {badSector}"); PulseProgress?.Invoke($"Trimming sector {badSector}");
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double _); sense = scsiReader.ReadBlock(out readBuffer, badSector, out double _, out recoveredError);
if(sense || _dev.Error) if((sense || _dev.Error) &&
!recoveredError)
continue; continue;
_resume.BadBlocks.Remove(badSector); _resume.BadBlocks.Remove(badSector);
@@ -785,9 +787,7 @@ namespace Aaru.Core.Devices.Dumping
if(dcMode10?.Pages != null) if(dcMode10?.Pages != null)
foreach(Modes.ModePage modePage in dcMode10.Value.Pages.Where(modePage => foreach(Modes.ModePage modePage in dcMode10.Value.Pages.Where(modePage =>
modePage.Page == modePage.Page == 0x01 && modePage.Subpage == 0x00))
0x01 && modePage.
Subpage == 0x00))
currentModePage = modePage; currentModePage = modePage;
} }
} }
@@ -796,8 +796,8 @@ namespace Aaru.Core.Devices.Dumping
Modes.DecodedMode? dcMode6 = Modes.DecodeMode6(readBuffer, _dev.ScsiType); Modes.DecodedMode? dcMode6 = Modes.DecodeMode6(readBuffer, _dev.ScsiType);
if(dcMode6?.Pages != null) if(dcMode6?.Pages != null)
foreach(var modePage in dcMode6.Value.Pages.Where(modePage => modePage.Page == 0x01 && foreach(Modes.ModePage modePage in dcMode6.Value.Pages.Where(modePage =>
modePage.Subpage == 0x00)) modePage.Page == 0x01 && modePage.Subpage == 0x00))
currentModePage = modePage; currentModePage = modePage;
} }
@@ -946,11 +946,10 @@ namespace Aaru.Core.Devices.Dumping
forward ? "forward" : "reverse", forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : "")); runningPersistent ? "recovering partial data, " : ""));
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration); sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration, out recoveredError);
totalDuration += cmdDuration; totalDuration += cmdDuration;
if(!sense && if((!sense && !_dev.Error) || recoveredError)
!_dev.Error)
{ {
_resume.BadBlocks.Remove(badSector); _resume.BadBlocks.Remove(badSector);
extents.Add(badSector); extents.Add(badSector);

View File

@@ -132,35 +132,40 @@ namespace Aaru.Core.Devices
} }
} }
internal bool ReadBlock(out byte[] buffer, ulong block, out double duration) => internal bool ReadBlock(out byte[] buffer, ulong block, out double duration, out bool recoveredError) =>
ReadBlocks(out buffer, block, 1, out duration); ReadBlocks(out buffer, block, 1, out duration, out recoveredError);
internal bool ReadBlocks(out byte[] buffer, ulong block, out double duration) => internal bool ReadBlocks(out byte[] buffer, ulong block, out double duration, out bool recoveredError) =>
ReadBlocks(out buffer, block, BlocksToRead, out duration); ReadBlocks(out buffer, block, BlocksToRead, out duration, out recoveredError);
internal bool ReadBlocks(out byte[] buffer, ulong block, uint count, out double duration) internal bool ReadBlocks(out byte[] buffer, ulong block, uint count, out double duration,
out bool recoveredError)
{ {
switch(_dev.Type) switch(_dev.Type)
{ {
case DeviceType.ATA: return AtaReadBlocks(out buffer, block, count, out duration); case DeviceType.ATA: return AtaReadBlocks(out buffer, block, count, out duration, out recoveredError);
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: return ScsiReadBlocks(out buffer, block, count, out duration); case DeviceType.SCSI: return ScsiReadBlocks(out buffer, block, count, out duration, out recoveredError);
default: default:
buffer = null; buffer = null;
duration = 0d; duration = 0d;
recoveredError = false;
return true; return true;
} }
} }
internal bool ReadChs(out byte[] buffer, ushort cylinder, byte head, byte sector, out double duration) internal bool ReadChs(out byte[] buffer, ushort cylinder, byte head, byte sector, out double duration,
out bool recoveredError)
{ {
switch(_dev.Type) switch(_dev.Type)
{ {
case DeviceType.ATA: return AtaReadChs(out buffer, cylinder, head, sector, out duration); case DeviceType.ATA:
return AtaReadChs(out buffer, cylinder, head, sector, out duration, out recoveredError);
default: default:
buffer = null; buffer = null;
duration = 0d; duration = 0d;
recoveredError = false;
return true; return true;
} }

View File

@@ -343,7 +343,7 @@ namespace Aaru.Core.Devices
return true; return true;
} }
bool AtaReadBlocks(out byte[] buffer, ulong block, uint count, out double duration) bool AtaReadBlocks(out byte[] buffer, ulong block, uint count, out double duration, out bool recoveredError)
{ {
bool error = true; bool error = true;
bool sense; bool sense;
@@ -352,6 +352,7 @@ namespace Aaru.Core.Devices
byte status = 0, errorByte = 0; byte status = 0, errorByte = 0;
buffer = null; buffer = null;
duration = 0; duration = 0;
recoveredError = false;
if(_ataReadDmaLba48) if(_ataReadDmaLba48)
{ {
@@ -416,13 +417,19 @@ namespace Aaru.Core.Devices
_errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba); _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba);
} }
if(error) if(!error)
return false;
if((status & 0x04) == 0x04)
recoveredError = true;
AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
return error; return true;
} }
bool AtaReadChs(out byte[] buffer, ushort cylinder, byte head, byte sector, out double duration) bool AtaReadChs(out byte[] buffer, ushort cylinder, byte head, byte sector, out double duration,
out bool recoveredError)
{ {
bool error = true; bool error = true;
bool sense; bool sense;
@@ -430,6 +437,7 @@ namespace Aaru.Core.Devices
byte status = 0, errorByte = 0; byte status = 0, errorByte = 0;
buffer = null; buffer = null;
duration = 0; duration = 0;
recoveredError = false;
if(_ataReadDmaRetry) if(_ataReadDmaRetry)
{ {
@@ -475,10 +483,15 @@ namespace Aaru.Core.Devices
_errorLog?.WriteLine(cylinder, head, sector, _dev.Error, _dev.LastError, errorChs); _errorLog?.WriteLine(cylinder, head, sector, _dev.Error, _dev.LastError, errorChs);
} }
if(error) if(!error)
return false;
if((status & 0x04) == 0x04)
recoveredError = true;
AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); AaruConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
return error; return true;
} }
bool AtaSeek(ulong block, out double duration) bool AtaSeek(ulong block, out double duration)

View File

@@ -571,12 +571,13 @@ namespace Aaru.Core.Devices
return true; return true;
} }
bool ScsiReadBlocks(out byte[] buffer, ulong block, uint count, out double duration) bool ScsiReadBlocks(out byte[] buffer, ulong block, uint count, out double duration, out bool recoveredError)
{ {
bool sense; bool sense;
byte[] senseBuf; byte[] senseBuf;
buffer = null; buffer = null;
duration = 0; duration = 0;
recoveredError = false;
if(CanReadRaw) if(CanReadRaw)
if(_readLong16) if(_readLong16)
@@ -624,6 +625,9 @@ namespace Aaru.Core.Devices
!_dev.Error) !_dev.Error)
return false; return false;
recoveredError = Sense.DecodeFixed(senseBuf)?.SenseKey == SenseKeys.RecoveredError ||
Sense.DecodeDescriptor(senseBuf)?.SenseKey == SenseKeys.RecoveredError;
AaruConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf)); AaruConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf));
return sense; return sense;

View File

@@ -152,7 +152,7 @@ namespace Aaru.Core.Devices.Scanning
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)", UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
(long)i, (long)results.Blocks); (long)i, (long)results.Blocks);
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration); bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration, out _);
if(!error) if(!error)
{ {
@@ -268,7 +268,7 @@ namespace Aaru.Core.Devices.Scanning
PulseProgress?. PulseProgress?.
Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)"); Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration); bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out _);
if(!error) if(!error)
{ {

View File

@@ -481,7 +481,7 @@ namespace Aaru.Core.Devices.Scanning
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)", UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
(long)i, (long)results.Blocks); (long)i, (long)results.Blocks);
sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration); sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration, out _);
results.ProcessingTime += cmdDuration; results.ProcessingTime += cmdDuration;
if(!sense && if(!sense &&
@@ -563,7 +563,7 @@ namespace Aaru.Core.Devices.Scanning
if(scsiReader.CanSeek) if(scsiReader.CanSeek)
scsiReader.Seek(seekPos, out seekCur); scsiReader.Seek(seekPos, out seekCur);
else else
scsiReader.ReadBlock(out _, seekPos, out seekCur); scsiReader.ReadBlock(out _, seekPos, out seekCur, out _);
if(seekCur > results.SeekMax && if(seekCur > results.SeekMax &&
seekCur > 0) seekCur > 0)