diff --git a/.idea/.idea.Aaru/.idea/contentModel.xml b/.idea/.idea.Aaru/.idea/contentModel.xml
index c9f617210..ce5a26acc 100644
--- a/.idea/.idea.Aaru/.idea/contentModel.xml
+++ b/.idea/.idea.Aaru/.idea/contentModel.xml
@@ -5,8 +5,6 @@
-
-
@@ -16,6 +14,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -316,6 +324,7 @@
+
diff --git a/Aaru.Core/Aaru.Core.csproj b/Aaru.Core/Aaru.Core.csproj
index c0897963c..9cb70a684 100644
--- a/Aaru.Core/Aaru.Core.csproj
+++ b/Aaru.Core/Aaru.Core.csproj
@@ -77,6 +77,7 @@
+
diff --git a/Aaru.Core/Devices/Dumping/ATA.cs b/Aaru.Core/Devices/Dumping/ATA.cs
index fb434c6de..5cf7912d0 100644
--- a/Aaru.Core/Devices/Dumping/ATA.cs
+++ b/Aaru.Core/Devices/Dumping/ATA.cs
@@ -39,11 +39,12 @@ using Aaru.CommonTypes;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Extents;
using Aaru.CommonTypes.Interfaces;
-using Aaru.CommonTypes.Structs.Devices.ATA;
using Aaru.Core.Devices.Report;
using Aaru.Core.Logging;
+using Aaru.Decoders.ATA;
using Aaru.Decoders.PCMCIA;
using Schemas;
+using Identify = Aaru.CommonTypes.Structs.Devices.ATA.Identify;
using Tuple = Aaru.Decoders.PCMCIA.Tuple;
using Version = Aaru.CommonTypes.Interop.Version;
@@ -74,10 +75,11 @@ namespace Aaru.Core.Devices.Dumping
UpdateStatus?.Invoke("Requesting ATA IDENTIFY DEVICE.");
_dumpLog.WriteLine("Requesting ATA IDENTIFY DEVICE.");
- bool sense = _dev.AtaIdentify(out byte[] cmdBuf, out _);
+ bool sense = _dev.AtaIdentify(out byte[] cmdBuf, out AtaErrorRegistersChs errorChs);
- if(!sense &&
- Identify.Decode(cmdBuf).HasValue)
+ if(sense)
+ _errorLog?.WriteLine("ATA IDENTIFY DEVICE", _dev.Error, _dev.LastError, errorChs);
+ else if(Identify.Decode(cmdBuf).HasValue)
{
Identify.IdentifyDevice? ataIdNullable = Identify.Decode(cmdBuf);
@@ -97,7 +99,7 @@ namespace Aaru.Core.Devices.Dumping
// Initializate reader
UpdateStatus?.Invoke("Initializing reader.");
_dumpLog.WriteLine("Initializing reader.");
- var ataReader = new Reader(_dev, TIMEOUT, ataIdentify);
+ var ataReader = new Reader(_dev, TIMEOUT, ataIdentify, _errorLog);
// Fill reader blocks
ulong blocks = ataReader.GetDeviceBlocks();
diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/CdiReady.cs b/Aaru.Core/Devices/Dumping/CompactDisc/CdiReady.cs
index bfa17a88b..6d8614e5e 100644
--- a/Aaru.Core/Devices/Dumping/CompactDisc/CdiReady.cs
+++ b/Aaru.Core/Devices/Dumping/CompactDisc/CdiReady.cs
@@ -291,6 +291,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i + r, _dev.Error, _dev.LastError, senseBuf);
+
leadOutExtents.Add(i + r, firstTrack.TrackStartSector - 1);
UpdateStatus?.
@@ -388,6 +390,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i, _dev.Error, _dev.LastError, senseBuf);
+
_resume.NextBlock = firstTrack.TrackStartSector;
break;
diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs
index 443368e94..1f3d731cd 100644
--- a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs
+++ b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs
@@ -434,6 +434,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i + r, _dev.Error, _dev.LastError, senseBuf);
+
// Write empty data
DateTime writeStart = DateTime.Now;
@@ -574,6 +576,8 @@ namespace Aaru.Core.Devices.Dumping
continue;
}
+ _errorLog?.WriteLine(firstSectorToRead, _dev.Error, _dev.LastError, senseBuf);
+
// TODO: Reset device after X errors
if(_stopOnError)
return; // TODO: Return more cleanly
diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs
index 7359e50ff..c1614a5d8 100644
--- a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs
+++ b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs
@@ -247,6 +247,8 @@ namespace Aaru.Core.Devices.Dumping
if(sense || _dev.Error)
{
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
+
if(!runningPersistent)
continue;
@@ -279,6 +281,8 @@ namespace Aaru.Core.Devices.Dumping
_dumpLog.WriteLine("Correctly retried sector {0} in pass {1}.", badSector, pass);
sectorsNotEvenPartial.Remove(badSector);
}
+ else
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
if(supportedSubchannel != MmcSubchannel.None)
{
@@ -390,7 +394,11 @@ namespace Aaru.Core.Devices.Dumping
}
if(sense || _dev.Error)
+ {
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
+
continue;
+ }
_dumpLog.WriteLine("Got partial data for sector {0} in pass {1}.", badSector, pass);
@@ -541,7 +549,11 @@ namespace Aaru.Core.Devices.Dumping
}
if(sense || _dev.Error)
+ {
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
+
continue;
+ }
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, cmdBuf, badSector, 5, subLog, isrcs,
(byte)track.TrackSequence, ref mcn, tracks, subchannelExtents);
diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs b/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs
index b82061d90..c8eaf92e1 100644
--- a/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs
+++ b/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs
@@ -80,6 +80,7 @@ namespace Aaru.Core.Devices.Dumping
byte[] cmdBuf = null; // Data buffer
const uint sectorSize = 2352; // Full sector size
bool sense = true; // Sense indicator
+ byte[] senseBuf = null;
UpdateStatus?.Invoke("Reading lead-outs");
_dumpLog.WriteLine("Reading lead-outs");
@@ -117,23 +118,24 @@ namespace Aaru.Core.Devices.Dumping
if(readcd)
{
- sense = _dev.ReadCd(out cmdBuf, out _, (uint)i, blockSize, 1, MmcSectorTypes.AllTypes, false,
- false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
- supportedSubchannel, _dev.Timeout, out cmdDuration);
+ sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, MmcSectorTypes.AllTypes,
+ false, false, true, MmcHeaderCodes.AllHeaders, true, true,
+ MmcErrorField.None, supportedSubchannel, _dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if(read16)
- sense = _dev.Read16(out cmdBuf, out _, 0, false, true, false, i, blockSize, 0, 1, false,
+ sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, i, blockSize, 0, 1, false,
_dev.Timeout, out cmdDuration);
else if(read12)
- sense = _dev.Read12(out cmdBuf, out _, 0, false, true, false, false, (uint)i, blockSize, 0, 1,
- false, _dev.Timeout, out cmdDuration);
+ sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, blockSize,
+ 0, 1, false, _dev.Timeout, out cmdDuration);
else if(read10)
- sense = _dev.Read10(out cmdBuf, out _, 0, false, true, false, false, (uint)i, blockSize, 0, 1,
- _dev.Timeout, out cmdDuration);
+ sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, blockSize,
+ 0, 1, _dev.Timeout, out cmdDuration);
else if(read6)
- sense = _dev.Read6(out cmdBuf, out _, (uint)i, blockSize, 1, _dev.Timeout, out cmdDuration);
+ sense = _dev.Read6(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, _dev.Timeout,
+ out cmdDuration);
if(!sense &&
!_dev.Error)
@@ -178,6 +180,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i, _dev.Error, _dev.LastError, senseBuf);
+
// TODO: Reset device after X errors
if(_stopOnError)
return; // TODO: Return more cleanly
@@ -244,6 +248,7 @@ namespace Aaru.Core.Devices.Dumping
byte[] cmdBuf = null; // Data buffer
const uint sectorSize = 2352; // Full sector size
bool sense = true; // Sense indicator
+ byte[] senseBuf = null;
_dumpLog.WriteLine("Retrying lead-outs");
@@ -281,23 +286,24 @@ namespace Aaru.Core.Devices.Dumping
if(readcd)
{
- sense = _dev.ReadCd(out cmdBuf, out _, (uint)i, blockSize, 1, MmcSectorTypes.AllTypes, false,
- false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
- supportedSubchannel, _dev.Timeout, out cmdDuration);
+ sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, MmcSectorTypes.AllTypes,
+ false, false, true, MmcHeaderCodes.AllHeaders, true, true,
+ MmcErrorField.None, supportedSubchannel, _dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if(read16)
- sense = _dev.Read16(out cmdBuf, out _, 0, false, true, false, i, blockSize, 0, 1, false,
+ sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, i, blockSize, 0, 1, false,
_dev.Timeout, out cmdDuration);
else if(read12)
- sense = _dev.Read12(out cmdBuf, out _, 0, false, true, false, false, (uint)i, blockSize, 0, 1,
- false, _dev.Timeout, out cmdDuration);
+ sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, blockSize,
+ 0, 1, false, _dev.Timeout, out cmdDuration);
else if(read10)
- sense = _dev.Read10(out cmdBuf, out _, 0, false, true, false, false, (uint)i, blockSize, 0, 1,
- _dev.Timeout, out cmdDuration);
+ sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, blockSize,
+ 0, 1, _dev.Timeout, out cmdDuration);
else if(read6)
- sense = _dev.Read6(out cmdBuf, out _, (uint)i, blockSize, 1, _dev.Timeout, out cmdDuration);
+ sense = _dev.Read6(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, _dev.Timeout,
+ out cmdDuration);
if(!sense &&
!_dev.Error)
@@ -342,6 +348,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i, _dev.Error, _dev.LastError, senseBuf);
+
// TODO: Reset device after X errors
if(_stopOnError)
return; // TODO: Return more cleanly
diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs
index 5323cdc73..a0a098285 100644
--- a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs
+++ b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs
@@ -62,6 +62,7 @@ namespace Aaru.Core.Devices.Dumping
double cmdDuration = 0; // Command execution time
const uint sectorSize = 2352; // Full sector size
PlextorSubchannel supportedPlextorSubchannel;
+ byte[] senseBuf = null;
switch(supportedSubchannel)
{
@@ -135,32 +136,36 @@ namespace Aaru.Core.Devices.Dumping
if(_supportsPlextorD8 && audioExtents.Contains(badSector))
{
- sense = ReadPlextorWithSubchannel(out cmdBuf, out _, badSectorToRead, blockSize, sectorsToTrim,
- supportedPlextorSubchannel, out cmdDuration);
+ sense = ReadPlextorWithSubchannel(out cmdBuf, out senseBuf, badSectorToRead, blockSize,
+ sectorsToTrim, supportedPlextorSubchannel, out cmdDuration);
totalDuration += cmdDuration;
}
else if(readcd)
- sense = _dev.ReadCd(out cmdBuf, out _, badSectorToRead, blockSize, sectorsToTrim,
+ sense = _dev.ReadCd(out cmdBuf, out senseBuf, badSectorToRead, blockSize, sectorsToTrim,
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
true, MmcErrorField.None, supportedSubchannel, _dev.Timeout, out cmdDuration);
else if(read16)
- sense = _dev.Read16(out cmdBuf, out _, 0, false, true, false, badSectorToRead, blockSize, 0,
+ sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, badSectorToRead, blockSize, 0,
sectorsToTrim, false, _dev.Timeout, out cmdDuration);
else if(read12)
- sense = _dev.Read12(out cmdBuf, out _, 0, false, true, false, false, badSectorToRead, blockSize, 0,
- sectorsToTrim, false, _dev.Timeout, out cmdDuration);
+ sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, badSectorToRead,
+ blockSize, 0, sectorsToTrim, false, _dev.Timeout, out cmdDuration);
else if(read10)
- sense = _dev.Read10(out cmdBuf, out _, 0, false, true, false, false, badSectorToRead, blockSize, 0,
- sectorsToTrim, _dev.Timeout, out cmdDuration);
+ sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, badSectorToRead,
+ blockSize, 0, sectorsToTrim, _dev.Timeout, out cmdDuration);
else if(read6)
- sense = _dev.Read6(out cmdBuf, out _, badSectorToRead, blockSize, sectorsToTrim, _dev.Timeout,
- out cmdDuration);
+ sense = _dev.Read6(out cmdBuf, out senseBuf, badSectorToRead, blockSize, sectorsToTrim,
+ _dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
if(sense || _dev.Error)
+ {
+ _errorLog?.WriteLine(badSectorToRead, _dev.Error, _dev.LastError, senseBuf);
+
continue;
+ }
if(!sense &&
!_dev.Error)
diff --git a/Aaru.Core/Devices/Dumping/Dump.cs b/Aaru.Core/Devices/Dumping/Dump.cs
index 33771bef1..0b958f6f5 100644
--- a/Aaru.Core/Devices/Dumping/Dump.cs
+++ b/Aaru.Core/Devices/Dumping/Dump.cs
@@ -61,6 +61,7 @@ namespace Aaru.Core.Devices.Dumping
readonly DumpLog _dumpLog;
readonly bool _dumpRaw;
readonly Encoding _encoding;
+ readonly ErrorLog _errorLog;
readonly bool _fixSubchannel;
readonly bool _fixSubchannelCrc;
readonly bool _fixSubchannelPosition;
@@ -119,7 +120,7 @@ namespace Aaru.Core.Devices.Dumping
CICMMetadataType preSidecar, uint skip, bool metadata, bool trim, bool dumpFirstTrackPregap,
bool fixOffset, bool debug, DumpSubchannel subchannel, int speed, bool @private,
bool fixSubchannelPosition, bool retrySubchannel, bool fixSubchannel, bool fixSubchannelCrc,
- bool skipCdireadyHole)
+ bool skipCdireadyHole, ErrorLog errorLog)
{
_doResume = doResume;
_dev = dev;
@@ -154,6 +155,7 @@ namespace Aaru.Core.Devices.Dumping
_fixSubchannel = fixSubchannel;
_fixSubchannelCrc = fixSubchannelCrc;
_skipCdireadyHole = skipCdireadyHole;
+ _errorLog = errorLog;
}
/// Starts dumping with the stablished fields and autodetecting the device type
@@ -215,6 +217,7 @@ namespace Aaru.Core.Devices.Dumping
return;
}
+ _errorLog.Close();
_dumpLog.Close();
if(_resume == null ||
diff --git a/Aaru.Core/Devices/Dumping/MMC.cs b/Aaru.Core/Devices/Dumping/MMC.cs
index 79edd679d..1856f30f3 100644
--- a/Aaru.Core/Devices/Dumping/MMC.cs
+++ b/Aaru.Core/Devices/Dumping/MMC.cs
@@ -203,7 +203,7 @@ namespace Aaru.Core.Devices.Dumping
_speedMultiplier *= 150;
- var scsiReader = new Reader(_dev, _dev.Timeout, null, _dumpRaw);
+ var scsiReader = new Reader(_dev, _dev.Timeout, null, _errorLog, _dumpRaw);
ulong blocks = scsiReader.GetDeviceBlocks();
_dumpLog.WriteLine("Device reports disc has {0} blocks", blocks);
Dictionary mediaTags = new Dictionary();
diff --git a/Aaru.Core/Devices/Dumping/MiniDisc.cs b/Aaru.Core/Devices/Dumping/MiniDisc.cs
index fd65ac609..8fe635887 100644
--- a/Aaru.Core/Devices/Dumping/MiniDisc.cs
+++ b/Aaru.Core/Devices/Dumping/MiniDisc.cs
@@ -72,7 +72,7 @@ namespace Aaru.Core.Devices.Dumping
bool ret;
_dumpLog.WriteLine("Initializing reader.");
- var scsiReader = new Reader(_dev, _dev.Timeout, null);
+ var scsiReader = new Reader(_dev, _dev.Timeout, null, _errorLog);
ulong blocks = scsiReader.GetDeviceBlocks();
uint blockSize = scsiReader.LogicalBlockSize;
diff --git a/Aaru.Core/Devices/Dumping/PlayStationPortable/MemoryStick.cs b/Aaru.Core/Devices/Dumping/PlayStationPortable/MemoryStick.cs
index fbdc040d1..90f68e313 100644
--- a/Aaru.Core/Devices/Dumping/PlayStationPortable/MemoryStick.cs
+++ b/Aaru.Core/Devices/Dumping/PlayStationPortable/MemoryStick.cs
@@ -65,6 +65,7 @@ namespace Aaru.Core.Devices.Dumping
DateTime end;
MediaType dskType;
bool sense;
+ byte[] senseBuf;
sense = _dev.ReadCapacity(out byte[] readBuffer, out _, _dev.Timeout, out _);
@@ -195,7 +196,7 @@ namespace Aaru.Core.Devices.Dumping
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i, blocks);
- sense = _dev.Read12(out readBuffer, out _, 0, false, true, false, false, (uint)i, BLOCK_SIZE, 0,
+ sense = _dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, (uint)i, BLOCK_SIZE, 0,
blocksToRead, false, _dev.Timeout, out double cmdDuration);
totalDuration += cmdDuration;
@@ -212,6 +213,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i, _dev.Error, _dev.LastError, senseBuf);
+
// TODO: Reset device after X errors
if(_stopOnError)
return; // TODO: Return more cleanly
@@ -297,11 +300,15 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trimming sector {badSector}");
- sense = _dev.Read12(out readBuffer, out _, 0, false, true, false, false, (uint)badSector,
+ sense = _dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, (uint)badSector,
BLOCK_SIZE, 0, 1, false, _dev.Timeout, out double cmdDuration);
if(sense || _dev.Error)
+ {
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
+
continue;
+ }
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
@@ -397,7 +404,7 @@ namespace Aaru.Core.Devices.Dumping
UpdateStatus?.Invoke("Sending MODE SELECT to drive (return damaged blocks).");
_dumpLog.WriteLine("Sending MODE SELECT to drive (return damaged blocks).");
- sense = _dev.ModeSelect(md6, out byte[] senseBuf, true, false, _dev.Timeout, out _);
+ sense = _dev.ModeSelect(md6, out senseBuf, true, false, _dev.Timeout, out _);
if(sense)
{
@@ -431,11 +438,14 @@ namespace Aaru.Core.Devices.Dumping
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : ""));
- sense = _dev.Read12(out readBuffer, out _, 0, false, true, false, false, (uint)badSector,
+ sense = _dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, (uint)badSector,
BLOCK_SIZE, 0, 1, false, _dev.Timeout, out double cmdDuration);
totalDuration += cmdDuration;
+ if(sense || _dev.Error)
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
+
if(!sense &&
!_dev.Error)
{
diff --git a/Aaru.Core/Devices/Dumping/PlayStationPortable/UMD.cs b/Aaru.Core/Devices/Dumping/PlayStationPortable/UMD.cs
index b69657ed3..1705a10e1 100644
--- a/Aaru.Core/Devices/Dumping/PlayStationPortable/UMD.cs
+++ b/Aaru.Core/Devices/Dumping/PlayStationPortable/UMD.cs
@@ -61,6 +61,7 @@ namespace Aaru.Core.Devices.Dumping
double minSpeed = double.MaxValue;
DateTime start;
DateTime end;
+ byte[] senseBuf;
bool sense = _dev.Read12(out byte[] readBuffer, out _, 0, false, true, false, false, 0, 512, 0, 1, false,
_dev.Timeout, out _);
@@ -212,8 +213,9 @@ namespace Aaru.Core.Devices.Dumping
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
(long)blocks);
- sense = _dev.Read12(out readBuffer, out _, 0, false, true, false, false, (uint)(umdStart + (i * 4)),
- 512, 0, blocksToRead * 4, false, _dev.Timeout, out double cmdDuration);
+ sense = _dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false,
+ (uint)(umdStart + (i * 4)), 512, 0, blocksToRead * 4, false, _dev.Timeout,
+ out double cmdDuration);
totalDuration += cmdDuration;
@@ -229,6 +231,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i, _dev.Error, _dev.LastError, senseBuf);
+
// TODO: Reset device after X errors
if(_stopOnError)
return; // TODO: Return more cleanly
@@ -312,12 +316,16 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trimming sector {badSector}");
- sense = _dev.Read12(out readBuffer, out _, 0, false, true, false, false,
+ sense = _dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false,
(uint)(umdStart + (badSector * 4)), 512, 0, 4, false, _dev.Timeout,
out double cmdDuration);
if(sense || _dev.Error)
+ {
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
+
continue;
+ }
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
@@ -396,7 +404,7 @@ namespace Aaru.Core.Devices.Dumping
md6 = Modes.EncodeMode6(md, _dev.ScsiType);
_dumpLog.WriteLine("Sending MODE SELECT to drive (return damaged blocks).");
- sense = _dev.ModeSelect(md6, out byte[] senseBuf, true, false, _dev.Timeout, out _);
+ sense = _dev.ModeSelect(md6, out senseBuf, true, false, _dev.Timeout, out _);
if(sense)
{
@@ -429,12 +437,15 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.
Invoke($"Retrying sector {badSector}, pass {pass}, {(runningPersistent ? "recovering partial data, " : "")}{(forward ? "forward" : "reverse")}");
- sense = _dev.Read12(out readBuffer, out _, 0, false, true, false, false,
+ sense = _dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false,
(uint)(umdStart + (badSector * 4)), 512, 0, 4, false, _dev.Timeout,
out double cmdDuration);
totalDuration += cmdDuration;
+ if(sense || _dev.Error)
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
+
if(!sense &&
!_dev.Error)
{
diff --git a/Aaru.Core/Devices/Dumping/SBC.cs b/Aaru.Core/Devices/Dumping/SBC.cs
index bbffe8323..38a54b0bd 100644
--- a/Aaru.Core/Devices/Dumping/SBC.cs
+++ b/Aaru.Core/Devices/Dumping/SBC.cs
@@ -92,7 +92,7 @@ namespace Aaru.Core.Devices.Dumping
}
_dumpLog.WriteLine("Initializing reader.");
- var scsiReader = new Reader(_dev, _dev.Timeout, null, _dumpRaw);
+ var scsiReader = new Reader(_dev, _dev.Timeout, null, _errorLog, _dumpRaw);
ulong blocks = scsiReader.GetDeviceBlocks();
uint blockSize = scsiReader.LogicalBlockSize;
diff --git a/Aaru.Core/Devices/Dumping/SecureDigital.cs b/Aaru.Core/Devices/Dumping/SecureDigital.cs
index c6c299f3c..519a5aff0 100644
--- a/Aaru.Core/Devices/Dumping/SecureDigital.cs
+++ b/Aaru.Core/Devices/Dumping/SecureDigital.cs
@@ -82,6 +82,7 @@ namespace Aaru.Core.Devices.Dumping
byte[] scr = null;
uint physicalBlockSize = 0;
bool byteAddressed = true;
+ uint[] response;
Dictionary mediaTags = new Dictionary();
@@ -91,7 +92,7 @@ namespace Aaru.Core.Devices.Dumping
{
UpdateStatus?.Invoke("Reading Extended CSD");
_dumpLog.WriteLine("Reading Extended CSD");
- sense = _dev.ReadExtendedCsd(out ecsd, out _, TIMEOUT, out duration);
+ sense = _dev.ReadExtendedCsd(out ecsd, out response, TIMEOUT, out duration);
if(!sense)
{
@@ -110,11 +111,14 @@ namespace Aaru.Core.Devices.Dumping
mediaTags.Add(MediaTagType.MMC_ExtendedCSD, null);
}
else
+ {
+ _errorLog?.WriteLine("Read eCSD", _dev.Error, _dev.LastError, response);
ecsd = null;
+ }
UpdateStatus?.Invoke("Reading CSD");
_dumpLog.WriteLine("Reading CSD");
- sense = _dev.ReadCsd(out csd, out _, TIMEOUT, out duration);
+ sense = _dev.ReadCsd(out csd, out response, TIMEOUT, out duration);
if(!sense)
{
@@ -128,14 +132,20 @@ namespace Aaru.Core.Devices.Dumping
mediaTags.Add(MediaTagType.MMC_CSD, null);
}
else
+ {
+ _errorLog?.WriteLine("Read CSD", _dev.Error, _dev.LastError, response);
csd = null;
+ }
UpdateStatus?.Invoke("Reading OCR");
_dumpLog.WriteLine("Reading OCR");
- sense = _dev.ReadOcr(out ocr, out _, TIMEOUT, out duration);
+ sense = _dev.ReadOcr(out ocr, out response, TIMEOUT, out duration);
if(sense)
+ {
+ _errorLog?.WriteLine("Read OCR", _dev.Error, _dev.LastError, response);
ocr = null;
+ }
else
mediaTags.Add(MediaTagType.MMC_OCR, null);
@@ -146,7 +156,7 @@ namespace Aaru.Core.Devices.Dumping
{
UpdateStatus?.Invoke("Reading CSD");
_dumpLog.WriteLine("Reading CSD");
- sense = _dev.ReadCsd(out csd, out _, TIMEOUT, out duration);
+ sense = _dev.ReadCsd(out csd, out response, TIMEOUT, out duration);
if(!sense)
{
@@ -163,23 +173,32 @@ namespace Aaru.Core.Devices.Dumping
mediaTags.Add(MediaTagType.SD_CSD, null);
}
else
+ {
+ _errorLog?.WriteLine("Read CSD", _dev.Error, _dev.LastError, response);
csd = null;
+ }
UpdateStatus?.Invoke("Reading OCR");
_dumpLog.WriteLine("Reading OCR");
- sense = _dev.ReadSdocr(out ocr, out _, TIMEOUT, out duration);
+ sense = _dev.ReadSdocr(out ocr, out response, TIMEOUT, out duration);
if(sense)
+ {
+ _errorLog?.WriteLine("Read OCR", _dev.Error, _dev.LastError, response);
ocr = null;
+ }
else
mediaTags.Add(MediaTagType.SD_OCR, null);
UpdateStatus?.Invoke("Reading SCR");
_dumpLog.WriteLine("Reading SCR");
- sense = _dev.ReadScr(out scr, out _, TIMEOUT, out duration);
+ sense = _dev.ReadScr(out scr, out response, TIMEOUT, out duration);
if(sense)
+ {
+ _errorLog?.WriteLine("Read SCR", _dev.Error, _dev.LastError, response);
scr = null;
+ }
else
mediaTags.Add(MediaTagType.SD_SCR, null);
@@ -189,10 +208,13 @@ namespace Aaru.Core.Devices.Dumping
UpdateStatus?.Invoke("Reading CID");
_dumpLog.WriteLine("Reading CID");
- sense = _dev.ReadCid(out byte[] cid, out _, TIMEOUT, out duration);
+ sense = _dev.ReadCid(out byte[] cid, out response, TIMEOUT, out duration);
if(sense)
+ {
+ _errorLog?.WriteLine("Read CID", _dev.Error, _dev.LastError, response);
cid = null;
+ }
else
mediaTags.Add(_dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID : MediaTagType.MMC_CID, null);
@@ -345,7 +367,7 @@ namespace Aaru.Core.Devices.Dumping
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
(long)blocks);
- error = _dev.Read(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, byteAddressed, TIMEOUT,
+ error = _dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, TIMEOUT,
out duration);
if(!error)
@@ -359,6 +381,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i, _dev.Error, _dev.LastError, byteAddressed, response);
+
if(i + _skip > blocks)
_skip = (uint)(blocks - i);
@@ -438,13 +462,17 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trimming sector {badSector}");
- error = _dev.Read(out cmdBuf, out _, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
+ error = _dev.Read(out cmdBuf, out response, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
out duration);
totalDuration += duration;
if(error)
+ {
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, byteAddressed, response);
+
continue;
+ }
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
@@ -486,11 +514,14 @@ namespace Aaru.Core.Devices.Dumping
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : ""));
- error = _dev.Read(out cmdBuf, out _, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
+ error = _dev.Read(out cmdBuf, out response, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
out duration);
totalDuration += duration;
+ if(error)
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, byteAddressed, response);
+
if(!error)
{
_resume.BadBlocks.Remove(badSector);
diff --git a/Aaru.Core/Devices/Dumping/XGD.cs b/Aaru.Core/Devices/Dumping/XGD.cs
index 0065a651f..0d349bd8b 100644
--- a/Aaru.Core/Devices/Dumping/XGD.cs
+++ b/Aaru.Core/Devices/Dumping/XGD.cs
@@ -151,6 +151,8 @@ namespace Aaru.Core.Devices.Dumping
if(sense)
{
+ _errorLog?.WriteLine("Kreon lock", _dev.Error, _dev.LastError, senseBuf);
+
_dumpLog.WriteLine("Cannot lock drive, not continuing.");
StoppingErrorMessage?.Invoke("Cannot lock drive, not continuing.");
@@ -251,6 +253,7 @@ namespace Aaru.Core.Devices.Dumping
if(sense)
{
+ _errorLog?.WriteLine("Kreon Xtreme unlock", _dev.Error, _dev.LastError, senseBuf);
_dumpLog.WriteLine("Cannot unlock drive, not continuing.");
StoppingErrorMessage?.Invoke("Cannot unlock drive, not continuing.");
@@ -282,6 +285,7 @@ namespace Aaru.Core.Devices.Dumping
if(sense)
{
+ _errorLog?.WriteLine("Kreon Wxripper unlock", _dev.Error, _dev.LastError, senseBuf);
_dumpLog.WriteLine("Cannot unlock drive, not continuing.");
StoppingErrorMessage?.Invoke("Cannot unlock drive, not continuing.");
@@ -600,6 +604,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(i, _dev.Error, _dev.LastError, senseBuf);
+
// TODO: Reset device after X errors
if(_stopOnError)
return; // TODO: Return more cleanly
@@ -794,6 +800,8 @@ namespace Aaru.Core.Devices.Dumping
}
else
{
+ _errorLog?.WriteLine(currentSector, _dev.Error, _dev.LastError, senseBuf);
+
// TODO: Reset device after X errors
if(_stopOnError)
return; // TODO: Return more cleanly
@@ -844,6 +852,7 @@ namespace Aaru.Core.Devices.Dumping
if(sense)
{
+ _errorLog?.WriteLine("Kreon Wxripper unlock", _dev.Error, _dev.LastError, senseBuf);
_dumpLog.WriteLine("Cannot unlock drive, not continuing.");
StoppingErrorMessage?.Invoke("Cannot unlock drive, not continuing.");
@@ -913,7 +922,11 @@ namespace Aaru.Core.Devices.Dumping
totalDuration += cmdDuration;
if(sense || _dev.Error)
+ {
+ _errorLog?.WriteLine(badSector, _dev.Error, _dev.LastError, senseBuf);
+
continue;
+ }
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
@@ -1062,6 +1075,9 @@ namespace Aaru.Core.Devices.Dumping
totalDuration += cmdDuration;
+ if(sense || _dev.Error)
+ _errorLog?.WriteLine(currentSector, _dev.Error, _dev.LastError, senseBuf);
+
if(!sense &&
!_dev.Error)
{
diff --git a/Aaru.Core/Devices/Reader.cs b/Aaru.Core/Devices/Reader.cs
index afc7ef4a7..f294da930 100644
--- a/Aaru.Core/Devices/Reader.cs
+++ b/Aaru.Core/Devices/Reader.cs
@@ -33,6 +33,7 @@
using System;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Structs.Devices.ATA;
+using Aaru.Core.Logging;
using Aaru.Devices;
namespace Aaru.Core.Devices
@@ -40,15 +41,17 @@ namespace Aaru.Core.Devices
/// Reduces common code used for scanning and dumping
internal partial class Reader
{
- readonly Device _dev;
- readonly uint _timeout;
+ readonly Device _dev;
+ readonly ErrorLog _errorLog;
+ readonly uint _timeout;
- internal Reader(Device dev, uint timeout, byte[] identification, bool raw = false)
+ internal Reader(Device dev, uint timeout, byte[] identification, ErrorLog errorLog, bool raw = false)
{
_dev = dev;
_timeout = timeout;
BlocksToRead = 64;
CanReadRaw = raw;
+ _errorLog = errorLog;
switch(dev.Type)
{
diff --git a/Aaru.Core/Devices/ReaderATA.cs b/Aaru.Core/Devices/ReaderATA.cs
index 4b1c56129..1947c6a55 100644
--- a/Aaru.Core/Devices/ReaderATA.cs
+++ b/Aaru.Core/Devices/ReaderATA.cs
@@ -361,6 +361,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorLba48.Status & 0x27) == 0 && errorLba48.Error == 0 && buffer.Length > 0);
status = errorLba48.Status;
errorByte = errorLba48.Error;
+
+ if(error)
+ _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba48);
}
else if(_ataReadLba48)
{
@@ -368,6 +371,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorLba48.Status & 0x27) == 0 && errorLba48.Error == 0 && buffer.Length > 0);
status = errorLba48.Status;
errorByte = errorLba48.Error;
+
+ if(error)
+ _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba48);
}
else if(_ataReadDmaRetryLba)
{
@@ -376,6 +382,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
status = errorLba.Status;
errorByte = errorLba.Error;
+
+ if(error)
+ _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba);
}
else if(_ataReadDmaLba)
{
@@ -384,6 +393,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
status = errorLba.Status;
errorByte = errorLba.Error;
+
+ if(error)
+ _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba);
}
else if(_ataReadRetryLba)
{
@@ -391,6 +403,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
status = errorLba.Status;
errorByte = errorLba.Error;
+
+ if(error)
+ _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba);
}
else if(_ataReadLba)
{
@@ -398,6 +413,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
status = errorLba.Status;
errorByte = errorLba.Error;
+
+ if(error)
+ _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba);
}
if(error)
@@ -422,6 +440,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
status = errorChs.Status;
errorByte = errorChs.Error;
+
+ if(error)
+ _errorLog?.WriteLine(cylinder, head, sector, _dev.Error, _dev.LastError, errorChs);
}
else if(_ataReadDma)
{
@@ -431,6 +452,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
status = errorChs.Status;
errorByte = errorChs.Error;
+
+ if(error)
+ _errorLog?.WriteLine(cylinder, head, sector, _dev.Error, _dev.LastError, errorChs);
}
else if(_ataReadRetry)
{
@@ -438,6 +462,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
status = errorChs.Status;
errorByte = errorChs.Error;
+
+ if(error)
+ _errorLog?.WriteLine(cylinder, head, sector, _dev.Error, _dev.LastError, errorChs);
}
else if(_ataRead)
{
@@ -445,6 +472,9 @@ namespace Aaru.Core.Devices
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
status = errorChs.Status;
errorByte = errorChs.Error;
+
+ if(error)
+ _errorLog?.WriteLine(cylinder, head, sector, _dev.Error, _dev.LastError, errorChs);
}
if(error)
@@ -457,6 +487,9 @@ namespace Aaru.Core.Devices
{
bool sense = _dev.Seek(out AtaErrorRegistersLba28 errorLba, (uint)block, _timeout, out duration);
+ if(!(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0))
+ _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, errorLba);
+
return !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0);
}
@@ -464,6 +497,9 @@ namespace Aaru.Core.Devices
{
bool sense = _dev.Seek(out AtaErrorRegistersChs errorChs, cylinder, head, sector, _timeout, out duration);
+ if(!(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0))
+ _errorLog?.WriteLine(cylinder, head, sector, _dev.Error, _dev.LastError, errorChs);
+
return !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0);
}
}
diff --git a/Aaru.Core/Devices/ReaderSCSI.cs b/Aaru.Core/Devices/ReaderSCSI.cs
index 20313642a..46bf31a22 100644
--- a/Aaru.Core/Devices/ReaderSCSI.cs
+++ b/Aaru.Core/Devices/ReaderSCSI.cs
@@ -622,6 +622,9 @@ namespace Aaru.Core.Devices
return true;
}
+ if(sense || _dev.Error)
+ _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, senseBuf);
+
if(!sense &&
!_dev.Error)
return false;
diff --git a/Aaru.Core/Devices/Scanning/ATA.cs b/Aaru.Core/Devices/Scanning/ATA.cs
index aa1b1a424..0fdcba477 100644
--- a/Aaru.Core/Devices/Scanning/ATA.cs
+++ b/Aaru.Core/Devices/Scanning/ATA.cs
@@ -56,7 +56,7 @@ namespace Aaru.Core.Devices.Scanning
Identify.Decode(cmdBuf).HasValue)
{
// Initializate reader
- var ataReader = new Reader(_dev, TIMEOUT, cmdBuf);
+ var ataReader = new Reader(_dev, TIMEOUT, cmdBuf, null);
// Fill reader blocks
results.Blocks = ataReader.GetDeviceBlocks();
@@ -204,8 +204,7 @@ namespace Aaru.Core.Devices.Scanning
mhddLog.Close();
ibgLog.Close(_dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
- (blockSize * (double)(results.Blocks + 1)) / 1024 /
- (results.ProcessingTime / 1000),
+ (blockSize * (double)(results.Blocks + 1)) / 1024 / (results.ProcessingTime / 1000),
_devicePath);
InitProgress?.Invoke();
@@ -325,8 +324,7 @@ namespace Aaru.Core.Devices.Scanning
mhddLog.Close();
ibgLog.Close(_dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
- (blockSize * (double)(results.Blocks + 1)) / 1024 /
- (results.ProcessingTime / 1000),
+ (blockSize * (double)(results.Blocks + 1)) / 1024 / (results.ProcessingTime / 1000),
_devicePath);
InitProgress?.Invoke();
diff --git a/Aaru.Core/Devices/Scanning/SCSI.cs b/Aaru.Core/Devices/Scanning/SCSI.cs
index 20c983be6..397131d1a 100644
--- a/Aaru.Core/Devices/Scanning/SCSI.cs
+++ b/Aaru.Core/Devices/Scanning/SCSI.cs
@@ -169,7 +169,7 @@ namespace Aaru.Core.Devices.Scanning
case PeripheralDeviceTypes.OpticalDevice:
case PeripheralDeviceTypes.SimplifiedDevice:
case PeripheralDeviceTypes.WriteOnceDevice:
- scsiReader = new Reader(_dev, _dev.Timeout, null);
+ scsiReader = new Reader(_dev, _dev.Timeout, null, null);
results.Blocks = scsiReader.GetDeviceBlocks();
if(scsiReader.FindReadCommand())
diff --git a/Aaru.Core/Logging/ErrorLog.cs b/Aaru.Core/Logging/ErrorLog.cs
new file mode 100644
index 000000000..70a61c0ed
--- /dev/null
+++ b/Aaru.Core/Logging/ErrorLog.cs
@@ -0,0 +1,554 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Aaru.Decoders.ATA;
+using Aaru.Decoders.SCSI;
+
+namespace Aaru.Core.Logging
+{
+ public class ErrorLog
+ {
+ readonly StreamWriter _logSw;
+
+ /// Initializes the error log
+ /// Output log file
+ public ErrorLog(string outputFile)
+ {
+ if(string.IsNullOrEmpty(outputFile))
+ return;
+
+ _logSw = new StreamWriter(outputFile, true);
+
+ _logSw.WriteLine("Start error logging at {0}", DateTime.Now);
+ _logSw.WriteLine("######################################################");
+ _logSw.Flush();
+ }
+
+ /// Finishes and closes the error log
+ public void Close()
+ {
+ _logSw.WriteLine("######################################################");
+ _logSw.WriteLine("End logging at {0}", DateTime.Now);
+ _logSw.Close();
+ }
+
+ /// Register an ATA error after sending a CHS command
+ /// Command
+ /// true if operating system returned an error status instead of the device
+ /// Operating system error number
+ /// Error registers
+ public void WriteLine(string command, bool osError, int errno, AtaErrorRegistersChs registers)
+ {
+ if(osError)
+ {
+ _logSw.WriteLine("ATA command {0} operating system error: {1}.", command, errno);
+ _logSw.Flush();
+ }
+ else
+ {
+ List error = new List();
+ List status = new List();
+
+ if((registers.Status & 0x01) == 0x01)
+ status.Add("ERR");
+
+ if((registers.Status & 0x02) == 0x02)
+ status.Add("IDX");
+
+ if((registers.Status & 0x04) == 0x04)
+ status.Add("CORR");
+
+ if((registers.Status & 0x08) == 0x08)
+ status.Add("DRQ");
+
+ if((registers.Status & 0x10) == 0x10)
+ status.Add("SRV");
+
+ if((registers.Status & 0x20) == 0x20)
+ status.Add("DF");
+
+ if((registers.Status & 0x40) == 0x40)
+ status.Add("RDY");
+
+ if((registers.Status & 0x80) == 0x80)
+ status.Add("BSY");
+
+ if((registers.Error & 0x01) == 0x01)
+ error.Add("AMNF");
+
+ if((registers.Error & 0x02) == 0x02)
+ error.Add("T0NF");
+
+ if((registers.Error & 0x04) == 0x04)
+ error.Add("ABRT");
+
+ if((registers.Error & 0x08) == 0x08)
+ error.Add("MCR");
+
+ if((registers.Error & 0x10) == 0x10)
+ error.Add("IDNF");
+
+ if((registers.Error & 0x20) == 0x20)
+ error.Add("MC");
+
+ if((registers.Error & 0x40) == 0x40)
+ error.Add("UNC");
+
+ if((registers.Error & 0x80) == 0x80)
+ error.Add("BBK");
+
+ _logSw.WriteLine("ATA command {0} error: status = {1}, error = {2}.", command, string.Join(' ', status),
+ string.Join(' ', error));
+
+ _logSw.Flush();
+ }
+ }
+
+ /// Register an ATA error after trying to read using CHS commands
+ /// Cylinder
+ /// Head
+ /// Sector
+ /// true if operating system returned an error status instead of the device
+ /// Operating system error number
+ /// Error registers
+ public void WriteLine(ushort cylinder, byte head, byte sector, bool osError, int errno,
+ AtaErrorRegistersChs registers)
+ {
+ if(osError)
+ {
+ _logSw.WriteLine("ATA reading C/H/S {0}/{1}/{2} operating system error: {3}.", cylinder, head, sector,
+ errno);
+
+ _logSw.Flush();
+ }
+ else
+ {
+ List error = new List();
+ List status = new List();
+
+ if((registers.Status & 0x01) == 0x01)
+ status.Add("ERR");
+
+ if((registers.Status & 0x02) == 0x02)
+ status.Add("IDX");
+
+ if((registers.Status & 0x04) == 0x04)
+ status.Add("CORR");
+
+ if((registers.Status & 0x08) == 0x08)
+ status.Add("DRQ");
+
+ if((registers.Status & 0x10) == 0x10)
+ status.Add("SRV");
+
+ if((registers.Status & 0x20) == 0x20)
+ status.Add("DF");
+
+ if((registers.Status & 0x40) == 0x40)
+ status.Add("RDY");
+
+ if((registers.Status & 0x80) == 0x80)
+ status.Add("BSY");
+
+ if((registers.Error & 0x01) == 0x01)
+ error.Add("AMNF");
+
+ if((registers.Error & 0x02) == 0x02)
+ error.Add("T0NF");
+
+ if((registers.Error & 0x04) == 0x04)
+ error.Add("ABRT");
+
+ if((registers.Error & 0x08) == 0x08)
+ error.Add("MCR");
+
+ if((registers.Error & 0x10) == 0x10)
+ error.Add("IDNF");
+
+ if((registers.Error & 0x20) == 0x20)
+ error.Add("MC");
+
+ if((registers.Error & 0x40) == 0x40)
+ error.Add("UNC");
+
+ if((registers.Error & 0x80) == 0x80)
+ error.Add("BBK");
+
+ _logSw.WriteLine("ATA reading C/H/S {0}/{1}/{2} error: status = {3}, error = {4}.", cylinder, head,
+ sector, string.Join(' ', status), string.Join(' ', error));
+
+ _logSw.Flush();
+ }
+ }
+
+ /// Register an ATA error after trying to read using 28-bit LBA commands
+ /// Starting block
+ /// true if operating system returned an error status instead of the device
+ /// Operating system error number
+ /// Error registers
+ public void WriteLine(ulong block, bool osError, int errno, AtaErrorRegistersLba28 registers)
+ {
+ if(osError)
+ {
+ _logSw.WriteLine("ATA reading LBA {0} operating system error: {1}.", block, errno);
+ _logSw.Flush();
+ }
+ else
+ {
+ List error = new List();
+ List status = new List();
+
+ if((registers.Status & 0x01) == 0x01)
+ status.Add("ERR");
+
+ if((registers.Status & 0x02) == 0x02)
+ status.Add("IDX");
+
+ if((registers.Status & 0x04) == 0x04)
+ status.Add("CORR");
+
+ if((registers.Status & 0x08) == 0x08)
+ status.Add("DRQ");
+
+ if((registers.Status & 0x10) == 0x10)
+ status.Add("SRV");
+
+ if((registers.Status & 0x20) == 0x20)
+ status.Add("DF");
+
+ if((registers.Status & 0x40) == 0x40)
+ status.Add("RDY");
+
+ if((registers.Status & 0x80) == 0x80)
+ status.Add("BSY");
+
+ if((registers.Error & 0x01) == 0x01)
+ error.Add("AMNF");
+
+ if((registers.Error & 0x02) == 0x02)
+ error.Add("T0NF");
+
+ if((registers.Error & 0x04) == 0x04)
+ error.Add("ABRT");
+
+ if((registers.Error & 0x08) == 0x08)
+ error.Add("MCR");
+
+ if((registers.Error & 0x10) == 0x10)
+ error.Add("IDNF");
+
+ if((registers.Error & 0x20) == 0x20)
+ error.Add("MC");
+
+ if((registers.Error & 0x40) == 0x40)
+ error.Add("UNC");
+
+ if((registers.Error & 0x80) == 0x80)
+ error.Add("BBK");
+
+ _logSw.WriteLine("ATA reading LBA {0} error: status = {1}, error = {2}.", block,
+ string.Join(' ', status), string.Join(' ', error));
+
+ _logSw.Flush();
+ }
+ }
+
+ /// Register an ATA error after trying to read using 48-bit LBA commands
+ /// Starting block
+ /// true if operating system returned an error status instead of the device
+ /// Operating system error number
+ /// Error registers
+ public void WriteLine(ulong block, bool osError, int errno, AtaErrorRegistersLba48 registers)
+ {
+ if(osError)
+ {
+ _logSw.WriteLine("ATA reading LBA {0} operating system error: {1}.", block, errno);
+ _logSw.Flush();
+ }
+ else
+ {
+ List error = new List();
+ List status = new List();
+
+ if((registers.Status & 0x01) == 0x01)
+ status.Add("ERR");
+
+ if((registers.Status & 0x02) == 0x02)
+ status.Add("IDX");
+
+ if((registers.Status & 0x04) == 0x04)
+ status.Add("CORR");
+
+ if((registers.Status & 0x08) == 0x08)
+ status.Add("DRQ");
+
+ if((registers.Status & 0x10) == 0x10)
+ status.Add("SRV");
+
+ if((registers.Status & 0x20) == 0x20)
+ status.Add("DF");
+
+ if((registers.Status & 0x40) == 0x40)
+ status.Add("RDY");
+
+ if((registers.Status & 0x80) == 0x80)
+ status.Add("BSY");
+
+ if((registers.Error & 0x01) == 0x01)
+ error.Add("AMNF");
+
+ if((registers.Error & 0x02) == 0x02)
+ error.Add("T0NF");
+
+ if((registers.Error & 0x04) == 0x04)
+ error.Add("ABRT");
+
+ if((registers.Error & 0x08) == 0x08)
+ error.Add("MCR");
+
+ if((registers.Error & 0x10) == 0x10)
+ error.Add("IDNF");
+
+ if((registers.Error & 0x20) == 0x20)
+ error.Add("MC");
+
+ if((registers.Error & 0x40) == 0x40)
+ error.Add("UNC");
+
+ if((registers.Error & 0x80) == 0x80)
+ error.Add("BBK");
+
+ _logSw.WriteLine("ATA reading LBA {0} error: status = {1}, error = {2}.", block,
+ string.Join(' ', status), string.Join(' ', error));
+
+ _logSw.Flush();
+ }
+ }
+
+ /// Register a SCSI error after sending a command
+ /// Command
+ /// true if operating system returned an error status instead of the device
+ /// Operating system error number
+ /// REQUEST SENSE response buffer
+ public void WriteLine(string command, bool osError, int errno, byte[] senseBuffer)
+ {
+ if(osError)
+ {
+ _logSw.WriteLine("SCSI command {0} operating system error: {1}.", command, errno);
+ _logSw.Flush();
+
+ return;
+ }
+
+ FixedSense? decodedFixedSense = Sense.DecodeFixed(senseBuffer);
+ DescriptorSense? decodedDescriptorSense = Sense.DecodeDescriptor(senseBuffer);
+ string prettySense = Sense.PrettifySense(senseBuffer);
+ string hexSense = string.Join(' ', senseBuffer.Select(b => $"{b:X2}"));
+
+ if(decodedFixedSense.HasValue)
+ {
+ if(prettySense != null)
+ {
+ if(prettySense.StartsWith("SCSI SENSE: "))
+ prettySense = prettySense.Substring(12);
+
+ if(prettySense.EndsWith("\n"))
+ prettySense = prettySense.Substring(0, prettySense.Length - 1);
+
+ prettySense = prettySense.Replace("\n", " - ");
+
+ _logSw.WriteLine("SCSI command {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}, {5}.", command,
+ decodedFixedSense?.SenseKey, decodedFixedSense?.ASC, decodedFixedSense?.ASCQ,
+ hexSense, prettySense);
+ }
+ else
+ {
+ _logSw.WriteLine("SCSI command {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}.", command,
+ decodedFixedSense?.SenseKey, decodedFixedSense?.ASC, decodedFixedSense?.ASCQ,
+ hexSense);
+ }
+ }
+ else if(decodedDescriptorSense.HasValue)
+ {
+ if(prettySense != null)
+ {
+ if(prettySense.StartsWith("SCSI SENSE: "))
+ prettySense = prettySense.Substring(12);
+
+ if(prettySense.EndsWith("\n"))
+ prettySense = prettySense.Substring(0, prettySense.Length - 1);
+
+ prettySense = prettySense.Replace("\n", " - ");
+
+ _logSw.WriteLine("SCSI command {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}, {5}.", command,
+ decodedDescriptorSense?.SenseKey, decodedDescriptorSense?.ASC,
+ decodedDescriptorSense?.ASCQ, hexSense, prettySense);
+ }
+ else
+ {
+ _logSw.WriteLine("SCSI command {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}.", command,
+ decodedDescriptorSense?.SenseKey, decodedDescriptorSense?.ASC,
+ decodedDescriptorSense?.ASCQ, hexSense);
+ }
+ }
+ else
+ {
+ if(prettySense != null)
+ {
+ if(prettySense.StartsWith("SCSI SENSE: "))
+ prettySense = prettySense.Substring(12);
+
+ if(prettySense.EndsWith("\n"))
+ prettySense = prettySense.Substring(0, prettySense.Length - 1);
+
+ prettySense = prettySense.Replace("\n", " - ");
+
+ _logSw.WriteLine("SCSI command {0} error: {1}, {2}.", command, hexSense, prettySense);
+ }
+ else
+ {
+ _logSw.WriteLine("SCSI command {0} error: {1}", command, hexSense);
+ }
+ }
+
+ _logSw.Flush();
+ }
+
+ /// Register an SCSI error after trying to read
+ /// Starting block
+ /// true if operating system returned an error status instead of the device
+ /// Operating system error number
+ /// REQUEST SENSE response buffer
+ public void WriteLine(ulong block, bool osError, int errno, byte[] senseBuffer)
+ {
+ if(osError)
+ {
+ _logSw.WriteLine("SCSI reading LBA {0} operating system error: {1}.", block, errno);
+ _logSw.Flush();
+
+ return;
+ }
+
+ FixedSense? decodedFixedSense = Sense.DecodeFixed(senseBuffer);
+ DescriptorSense? decodedDescriptorSense = Sense.DecodeDescriptor(senseBuffer);
+ string prettySense = Sense.PrettifySense(senseBuffer);
+ string hexSense = string.Join(' ', senseBuffer.Select(b => $"{b:X2}"));
+
+ if(decodedFixedSense.HasValue)
+ {
+ if(prettySense != null)
+ {
+ if(prettySense.StartsWith("SCSI SENSE: "))
+ prettySense = prettySense.Substring(12);
+
+ if(prettySense.EndsWith("\n"))
+ prettySense = prettySense.Substring(0, prettySense.Length - 1);
+
+ prettySense = prettySense.Replace("\n", " - ");
+
+ _logSw.WriteLine("SCSI reading LBA {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}, {5}.", block,
+ decodedFixedSense?.SenseKey, decodedFixedSense?.ASC, decodedFixedSense?.ASCQ,
+ hexSense, prettySense);
+ }
+ else
+ {
+ _logSw.WriteLine("SCSI reading LBA {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}.", block,
+ decodedFixedSense?.SenseKey, decodedFixedSense?.ASC, decodedFixedSense?.ASCQ,
+ hexSense);
+ }
+ }
+ else if(decodedDescriptorSense.HasValue)
+ {
+ if(prettySense != null)
+ {
+ if(prettySense.StartsWith("SCSI SENSE: "))
+ prettySense = prettySense.Substring(12);
+
+ if(prettySense.EndsWith("\n"))
+ prettySense = prettySense.Substring(0, prettySense.Length - 1);
+
+ prettySense = prettySense.Replace("\n", " - ");
+
+ _logSw.WriteLine("SCSI reading LBA {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}, {5}.", block,
+ decodedDescriptorSense?.SenseKey, decodedDescriptorSense?.ASC,
+ decodedDescriptorSense?.ASCQ, hexSense, prettySense);
+ }
+ else
+ {
+ _logSw.WriteLine("SCSI reading LBA {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}.", block,
+ decodedDescriptorSense?.SenseKey, decodedDescriptorSense?.ASC,
+ decodedDescriptorSense?.ASCQ, hexSense);
+ }
+ }
+ else
+ {
+ if(prettySense != null)
+ {
+ if(prettySense.StartsWith("SCSI SENSE: "))
+ prettySense = prettySense.Substring(12);
+
+ if(prettySense.EndsWith("\n"))
+ prettySense = prettySense.Substring(0, prettySense.Length - 1);
+
+ prettySense = prettySense.Replace("\n", " - ");
+
+ _logSw.WriteLine("SCSI reading LBA {0} error: {1}, {2}.", block, hexSense, prettySense);
+ }
+ else
+ {
+ _logSw.WriteLine("SCSI reading LBA {0} error: {1}", block, hexSense);
+ }
+ }
+
+ _logSw.Flush();
+ }
+
+ /// Register a SecureDigital / MultiMediaCard error after sending a command
+ /// Command
+ /// true if operating system returned an error status instead of the device
+ /// Operating system error number
+ /// Response
+ public void WriteLine(string command, bool osError, int errno, uint[] response)
+ {
+ if(osError)
+ {
+ _logSw.WriteLine("SD/MMC command {0} operating system error: {1}.", command, errno);
+ _logSw.Flush();
+
+ return;
+ }
+
+ // TODO: Decode response
+ _logSw.WriteLine("SD/MMC command {0} error: {1}", command,
+ string.Join(" - ", response.Select(r => $"0x{r:X8}")));
+
+ _logSw.Flush();
+ }
+
+ /// Register a SecureDigital / MultiMediaCard error after trying to read
+ /// Starting block
+ /// true if operating system returned an error status instead of the device
+ /// Operating system error number
+ /// Byte addressed
+ /// Response
+ public void WriteLine(ulong block, bool osError, int errno, bool byteAddressed, uint[] response)
+
+ {
+ if(osError)
+ {
+ _logSw.WriteLine("SD/MMC reading LBA {0} ({1}-addressed) operating system error: {2}.", block,
+ byteAddressed ? "byte" : "block", errno);
+
+ _logSw.Flush();
+
+ return;
+ }
+
+ _logSw.WriteLine("SD/MMC reading LBA {0} ({1}-addressed) error: {2}", block,
+ byteAddressed ? "byte" : "block", string.Join(" - ", response.Select(r => $"0x{r:X8}")));
+
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
index 1364f1a47..0af5da691 100644
--- a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
@@ -797,11 +797,13 @@ namespace Aaru.Gui.ViewModels.Windows
dumpLog.WriteLine("Output image format: {0}.", SelectedPlugin.Name);
+ var errorLog = new ErrorLog(_outputPrefix + ".error.log");
+
_dumper = new Dump(Resume, _dev, _devicePath, SelectedPlugin.Plugin, (ushort)Retries, Force, false,
Persistent, StopOnError, _resume, dumpLog, encoding, _outputPrefix, Destination,
parsedOptions, _sidecar, (uint)Skipped, ExistingMetadata == false, Trim == false,
Track1Pregap, true, false, DumpSubchannel.Any, 0, false, false, false, false, false,
- true);
+ true, errorLog);
new Thread(DoWork).Start();
}
diff --git a/Aaru/Commands/Media/Dump.cs b/Aaru/Commands/Media/Dump.cs
index 374a5dd4b..25b94a9b0 100644
--- a/Aaru/Commands/Media/Dump.cs
+++ b/Aaru/Commands/Media/Dump.cs
@@ -469,11 +469,13 @@ namespace Aaru.Commands.Media
AaruConsole.WriteLine("Output image format: {0}.", outputFormat.Name);
}
+ var errorLog = new ErrorLog(outputPrefix + ".error.log");
+
var dumper = new Dump(resume, dev, devicePath, outputFormat, retryPasses, force, false, persistent,
stopOnError, resumeClass, dumpLog, encodingClass, outputPrefix, outputPath,
parsedOptions, sidecar, skip, metadata, trim, firstPregap, fixOffset, debug,
wantedSubchannel, speed, @private, fixSubchannelPosition, retrySubchannel,
- fixSubchannel, fixSubchannelCrc, skipCdireadyHole);
+ fixSubchannel, fixSubchannelCrc, skipCdireadyHole, errorLog);
dumper.UpdateStatus += Progress.UpdateStatus;
dumper.ErrorMessage += Progress.ErrorMessage;
@@ -499,4 +501,4 @@ namespace Aaru.Commands.Media
return (int)ErrorNumber.NoError;
}
}
-}
+}
\ No newline at end of file