From efcf1720e2665518f7235fb81a5308c5766f9d65 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Fri, 2 Feb 2018 18:44:28 +0000 Subject: [PATCH] Add option to skip more sectors than tried to read when a bad sector is found. --- DiscImageChef.Core/Devices/Dumping/ATA.cs | 31 +++++++++++-------- .../Devices/Dumping/CompactDisc.cs | 22 ++++++++----- DiscImageChef.Core/Devices/Dumping/MMC.cs | 12 +++---- DiscImageChef.Core/Devices/Dumping/NVMe.cs | 2 +- DiscImageChef.Core/Devices/Dumping/SBC.cs | 18 ++++++----- DiscImageChef.Core/Devices/Dumping/SCSI.cs | 6 ++-- .../Devices/Dumping/SecureDigital.cs | 19 +++++++----- DiscImageChef.Core/Devices/Dumping/XGD.cs | 28 ++++++++++------- DiscImageChef/Commands/DumpMedia.cs | 9 +++--- DiscImageChef/Options.cs | 5 ++- 10 files changed, 91 insertions(+), 61 deletions(-) diff --git a/DiscImageChef.Core/Devices/Dumping/ATA.cs b/DiscImageChef.Core/Devices/Dumping/ATA.cs index f158abe2..680e4cb9 100644 --- a/DiscImageChef.Core/Devices/Dumping/ATA.cs +++ b/DiscImageChef.Core/Devices/Dumping/ATA.cs @@ -81,7 +81,7 @@ namespace DiscImageChef.Core.Devices.Dumping DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, Dictionary - formatOptions, CICMMetadataType preSidecar) + formatOptions, CICMMetadataType preSidecar, uint skip) { bool aborted; @@ -98,10 +98,10 @@ namespace DiscImageChef.Core.Devices.Dumping } bool sense; - const ushort ATA_PROFILE = 0x0001; - const uint TIMEOUT = 5; - double imageWriteDuration = 0; - + const ushort ATA_PROFILE = 0x0001; + const uint TIMEOUT = 5; + double imageWriteDuration = 0; + dumpLog.WriteLine("Requesting ATA IDENTIFY DEVICE."); sense = dev.AtaIdentify(out byte[] cmdBuf, out _); if(!sense && Identify.Decode(cmdBuf).HasValue) @@ -232,6 +232,7 @@ namespace DiscImageChef.Core.Devices.Dumping if(ataReader.IsLba) { DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead); + if(skip < blocksToRead) skip = blocksToRead; mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead); ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE); @@ -270,15 +271,16 @@ namespace DiscImageChef.Core.Devices.Dumping } else { - for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b); + for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b); mhddLog.Write(i, duration < 500 ? 65535 : duration); ibgLog.Write(i, 0); DateTime writeStart = DateTime.Now; - outputPlugin.WriteSectors(new byte[blockSize * blocksToRead], i, blocksToRead); + outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i); + dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); + i += skip - blocksToRead; } double newSpeed = @@ -391,7 +393,7 @@ namespace DiscImageChef.Core.Devices.Dumping DateTime writeStart = DateTime.Now; outputPlugin.WriteSector(cmdBuf, (ulong)((cy * heads + hd) * sectors + (sc - 1))); - imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; + imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; extents.Add(currentBlock); dumpLog.WriteLine("Error reading cylinder {0} head {1} sector {2}.", cy, hd, sc); @@ -405,7 +407,7 @@ namespace DiscImageChef.Core.Devices.Dumping DateTime writeStart = DateTime.Now; outputPlugin.WriteSector(new byte[blockSize], (ulong)((cy * heads + hd) * sectors + (sc - 1))); - imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; + imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; } double newSpeed = @@ -428,7 +430,8 @@ namespace DiscImageChef.Core.Devices.Dumping dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000)); dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.", - (double)blockSize * (double)(blocks + 1) / 1024 / (imageWriteDuration / 1000)); + (double)blockSize * (double)(blocks + 1) / 1024 / + (imageWriteDuration / 1000)); } foreach(ulong bad in resume.BadBlocks) dumpLog.WriteLine("Sector {0} could not be read.", bad); @@ -594,8 +597,10 @@ namespace DiscImageChef.Core.Devices.Dumping DicConsole.WriteLine(); - DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).", - (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd -closeStart).TotalSeconds); + DicConsole + .WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).", + (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, + imageWriteDuration, (closeEnd - closeStart).TotalSeconds); DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs index e9c31462..a18c93fe 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs @@ -91,7 +91,7 @@ namespace DiscImageChef.Core.Devices.Dumping string outputPrefix, string outputPath, Dictionary formatOptions, CICMMetadataType - preSidecar) + preSidecar, uint skip) { uint subSize; DateTime start; @@ -661,7 +661,9 @@ namespace DiscImageChef.Core.Devices.Dumping if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock); double imageWriteDuration = 0; - + + if(skip < blocksToRead) skip = blocksToRead; + // Start reading start = DateTime.UtcNow; for(int t = 0; t < tracks.Length; t++) @@ -733,20 +735,22 @@ namespace DiscImageChef.Core.Devices.Dumping DateTime writeStart = DateTime.Now; if(supportedSubchannel != MmcSubchannel.None) { - outputPlugin.WriteSectorsLong(new byte[SECTOR_SIZE * blocksToRead], i, blocksToRead); - outputPlugin.WriteSectorsTag(new byte[subSize * blocksToRead], i, blocksToRead, + outputPlugin.WriteSectorsLong(new byte[SECTOR_SIZE * skip], i, skip); + outputPlugin.WriteSectorsTag(new byte[subSize * skip], i, skip, SectorTagType.CdSectorSubchannel); } - else outputPlugin.WriteSectorsLong(new byte[blockSize * blocksToRead], i, blocksToRead); + else outputPlugin.WriteSectorsLong(new byte[blockSize * skip], i, skip); + imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b); + for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b); DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Sense.PrettifySense(senseBuf)); mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); ibgLog.Write(i, 0); - dumpLog.WriteLine("Error reading {0} sectors from sector {1}.", blocksToRead, i); + dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); + i += skip - blocksToRead; } double newSpeed = @@ -963,7 +967,9 @@ namespace DiscImageChef.Core.Devices.Dumping DicConsole.WriteLine(); DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).", - (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd-closeStart).TotalSeconds); + (end - start).TotalSeconds, totalDuration / 1000, + totalChkDuration / 1000, + imageWriteDuration, (closeEnd - closeStart).TotalSeconds); DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); diff --git a/DiscImageChef.Core/Devices/Dumping/MMC.cs b/DiscImageChef.Core/Devices/Dumping/MMC.cs index 8e6d5f48..78238bb4 100644 --- a/DiscImageChef.Core/Devices/Dumping/MMC.cs +++ b/DiscImageChef.Core/Devices/Dumping/MMC.cs @@ -84,7 +84,7 @@ namespace DiscImageChef.Core.Devices.Dumping string outputPrefix, string outputPath, Dictionary formatOptions, CICMMetadataType - preSidecar) + preSidecar, uint skip) { bool sense; ulong blocks; @@ -200,7 +200,7 @@ namespace DiscImageChef.Core.Devices.Dumping { CompactDisc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath, - formatOptions, preSidecar); + formatOptions, preSidecar, skip); return; } @@ -602,13 +602,13 @@ namespace DiscImageChef.Core.Devices.Dumping { Xgd.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags, ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions, - preSidecar); + preSidecar, skip); return; } Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags, ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions, - preSidecar); + preSidecar, skip); } internal static void AddMediaTagToSidecar(string outputPath, @@ -798,8 +798,8 @@ namespace DiscImageChef.Core.Devices.Dumping { new BorderType { - Image = outputPath, - Size = tag.Value.Length, + Image = outputPath, + Size = tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() } }; diff --git a/DiscImageChef.Core/Devices/Dumping/NVMe.cs b/DiscImageChef.Core/Devices/Dumping/NVMe.cs index 3033124c..4342035e 100644 --- a/DiscImageChef.Core/Devices/Dumping/NVMe.cs +++ b/DiscImageChef.Core/Devices/Dumping/NVMe.cs @@ -50,7 +50,7 @@ namespace DiscImageChef.Core.Devices.Dumping DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, Dictionary - formatOptions, CICMMetadataType preSidecar) + formatOptions, CICMMetadataType preSidecar, uint skip) { throw new NotImplementedException("NVMe devices not yet supported."); } diff --git a/DiscImageChef.Core/Devices/Dumping/SBC.cs b/DiscImageChef.Core/Devices/Dumping/SBC.cs index 4ed73c89..1d901638 100644 --- a/DiscImageChef.Core/Devices/Dumping/SBC.cs +++ b/DiscImageChef.Core/Devices/Dumping/SBC.cs @@ -86,7 +86,8 @@ namespace DiscImageChef.Core.Devices.Dumping ref DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, Dictionary formatOptions, - CICMMetadataType preSidecar) + CICMMetadataType preSidecar, + uint skip) { bool sense; ulong blocks; @@ -287,9 +288,9 @@ namespace DiscImageChef.Core.Devices.Dumping return; } - start = DateTime.UtcNow; + start = DateTime.UtcNow; double imageWriteDuration = 0; - + if(opticalDisc) outputPlugin.SetTracks(new List { @@ -387,15 +388,16 @@ namespace DiscImageChef.Core.Devices.Dumping // Write empty data DateTime writeStart = DateTime.Now; - outputPlugin.WriteSectors(new byte[blockSize * blocksToRead], i, blocksToRead); + outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b); + for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b); mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); ibgLog.Write(i, 0); - dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i); + dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); + i += skip - blocksToRead; } double newSpeed = @@ -883,7 +885,9 @@ namespace DiscImageChef.Core.Devices.Dumping DicConsole.WriteLine(); DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).", - (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd -closeStart).TotalSeconds); + (end - start).TotalSeconds, totalDuration / 1000, + totalChkDuration / 1000, + imageWriteDuration, (closeEnd - closeStart).TotalSeconds); DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); diff --git a/DiscImageChef.Core/Devices/Dumping/SCSI.cs b/DiscImageChef.Core/Devices/Dumping/SCSI.cs index a69ee41c..a9decb0a 100644 --- a/DiscImageChef.Core/Devices/Dumping/SCSI.cs +++ b/DiscImageChef.Core/Devices/Dumping/SCSI.cs @@ -79,7 +79,7 @@ namespace DiscImageChef.Core.Devices.Dumping string outputPath, Dictionary formatOptions, CICMMetadataType - preSidecar) + preSidecar, uint skip) { MediaType dskType = MediaType.Unknown; int resets = 0; @@ -212,12 +212,12 @@ namespace DiscImageChef.Core.Devices.Dumping case PeripheralDeviceTypes.MultiMediaDevice: Mmc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath, - formatOptions, preSidecar); + formatOptions, preSidecar, skip); return; default: Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, null, ref dskType, false, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, - formatOptions, preSidecar); + formatOptions, preSidecar, skip); break; } } diff --git a/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs b/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs index 8e26e7c8..f03ab402 100644 --- a/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs +++ b/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs @@ -79,7 +79,7 @@ namespace DiscImageChef.Core.Devices.Dumping DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, Dictionary - formatOptions, CICMMetadataType preSidecar) + formatOptions, CICMMetadataType preSidecar, uint skip) { bool aborted; @@ -234,6 +234,8 @@ namespace DiscImageChef.Core.Devices.Dumping dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead); + if(skip < blocksToRead) skip = blocksToRead; + DumpHardwareType currentTry = null; ExtentsULong extents = null; ResumeSupport.Process(true, false, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformId, @@ -281,9 +283,9 @@ namespace DiscImageChef.Core.Devices.Dumping if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock); - start = DateTime.UtcNow; + start = DateTime.UtcNow; double imageWriteDuration = 0; - + for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead) { if(aborted) @@ -316,15 +318,16 @@ namespace DiscImageChef.Core.Devices.Dumping } else { - for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b); + for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b); mhddLog.Write(i, duration < 500 ? 65535 : duration); ibgLog.Write(i, 0); DateTime writeStart = DateTime.Now; - outputPlugin.WriteSectors(new byte[blockSize * blocksToRead], i, blocksToRead); + outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i); + dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); + i += skip - blocksToRead; } double newSpeed = @@ -598,7 +601,9 @@ namespace DiscImageChef.Core.Devices.Dumping DicConsole.WriteLine(); DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).", - (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd -closeStart).TotalSeconds); + (end - start).TotalSeconds, totalDuration / 1000, + totalChkDuration / 1000, + imageWriteDuration, (closeEnd - closeStart).TotalSeconds); DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); diff --git a/DiscImageChef.Core/Devices/Dumping/XGD.cs b/DiscImageChef.Core/Devices/Dumping/XGD.cs index 7c1651d2..3b8a2507 100644 --- a/DiscImageChef.Core/Devices/Dumping/XGD.cs +++ b/DiscImageChef.Core/Devices/Dumping/XGD.cs @@ -88,7 +88,7 @@ namespace DiscImageChef.Core.Devices.Dumping ref DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, Dictionary formatOptions, - CICMMetadataType preSidecar) + CICMMetadataType preSidecar, uint skip) { bool sense; ulong blocks; @@ -311,6 +311,8 @@ namespace DiscImageChef.Core.Devices.Dumping return; } + if(skip < blocksToRead) skip = blocksToRead; + bool ret = true; foreach(MediaTagType tag in mediaTags.Keys) @@ -346,9 +348,9 @@ namespace DiscImageChef.Core.Devices.Dumping return; } - start = DateTime.UtcNow; + start = DateTime.UtcNow; double imageWriteDuration = 0; - + double cmdDuration = 0; uint saveBlocksToRead = blocksToRead; DumpHardwareType currentTry = null; @@ -438,17 +440,18 @@ namespace DiscImageChef.Core.Devices.Dumping // Write empty data DateTime writeStart = DateTime.Now; - outputPlugin.WriteSectors(new byte[BLOCK_SIZE * blocksToRead], i, blocksToRead); + outputPlugin.WriteSectors(new byte[BLOCK_SIZE * skip], i, skip); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b); + for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b); DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Sense.PrettifySense(senseBuf)); mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); ibgLog.Write(i, 0); - dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i); + dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); + i += skip - blocksToRead; string[] senseLines = Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine}, StringSplitOptions .RemoveEmptyEntries); @@ -481,7 +484,7 @@ namespace DiscImageChef.Core.Devices.Dumping DateTime writeStart = DateTime.Now; outputPlugin.WriteSectors(new byte[BLOCK_SIZE * blocksToRead], i, blocksToRead); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - blocksToRead = saveBlocksToRead; + blocksToRead = saveBlocksToRead; extents.Add(i, blocksToRead, true); currentSector = i + 1; resume.NextBlock = currentSector; @@ -511,7 +514,7 @@ namespace DiscImageChef.Core.Devices.Dumping // Write empty data DateTime writeStart = DateTime.Now; outputPlugin.WriteSectors(new byte[BLOCK_SIZE * blocksToRead], middle + currentSector, blocksToRead); - imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; + imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; extents.Add(currentSector, blocksToRead, true); currentSector += blocksToRead; @@ -577,7 +580,7 @@ namespace DiscImageChef.Core.Devices.Dumping // Write empty data DateTime writeStart = DateTime.Now; - outputPlugin.WriteSectors(new byte[BLOCK_SIZE * blocksToRead], currentSector, blocksToRead); + outputPlugin.WriteSectors(new byte[BLOCK_SIZE * skip], currentSector, skip); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; // TODO: Handle errors in video partition @@ -587,7 +590,8 @@ namespace DiscImageChef.Core.Devices.Dumping mhddLog.Write(l1, cmdDuration < 500 ? 65535 : cmdDuration); ibgLog.Write(l1, 0); - dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, l1); + dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, l1); + l1 += skip - blocksToRead; string[] senseLines = Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries); foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine); @@ -861,7 +865,9 @@ namespace DiscImageChef.Core.Devices.Dumping DicConsole.WriteLine(); DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming, {3:F3} writing, {4:F3} closing).", - (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000, imageWriteDuration, (closeEnd -closeStart).TotalSeconds); + (end - start).TotalSeconds, totalDuration / 1000, + totalChkDuration / 1000, + imageWriteDuration, (closeEnd - closeStart).TotalSeconds); DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (double)BLOCK_SIZE * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); diff --git a/DiscImageChef/Commands/DumpMedia.cs b/DiscImageChef/Commands/DumpMedia.cs index 2c60ccf1..70e8175b 100644 --- a/DiscImageChef/Commands/DumpMedia.cs +++ b/DiscImageChef/Commands/DumpMedia.cs @@ -76,6 +76,7 @@ namespace DiscImageChef.Commands DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force); DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", options.Options); DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", options.CicmXml); + DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", options.Skip); Dictionary parsedOptions = Options.Parse(options.Options); DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:"); @@ -205,24 +206,24 @@ namespace DiscImageChef.Commands case DeviceType.ATA: Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix, - options.OutputFile, parsedOptions, sidecar); + options.OutputFile, parsedOptions, sidecar, options.Skip); break; case DeviceType.MMC: case DeviceType.SecureDigital: SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, - encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar); + encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, options.Skip); break; case DeviceType.NVMe: NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix, - options.OutputFile, parsedOptions, sidecar); + options.OutputFile, parsedOptions, sidecar, options.Skip); break; case DeviceType.ATAPI: case DeviceType.SCSI: Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, options.LeadIn, - encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar); + encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, options.Skip); break; default: dumpLog.WriteLine("Unknown device type."); diff --git a/DiscImageChef/Options.cs b/DiscImageChef/Options.cs index 17b73072..2aeb8ce2 100644 --- a/DiscImageChef/Options.cs +++ b/DiscImageChef/Options.cs @@ -308,6 +308,9 @@ namespace DiscImageChef [Option('x', "cicm-xml", Default = null, HelpText = "Take metadata from existing CICM XML sidecar.")] public string CicmXml { get; set; } + + [Option('k', "skip", Default = 512, HelpText = "When an unreadable sector is found skip this many sectors.")] + public uint Skip { get; set; } } [Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")] @@ -432,7 +435,7 @@ namespace DiscImageChef [Option('O', "options", Default = null, HelpText = "Comma separated name=value pairs of options to pass to output image plugin")] public string Options { get; set; } - + [Option('x', "cicm-xml", Default = null, HelpText = "Take metadata from existing CICM XML sidecar.")] public string CicmXml { get; set; }