Separate trimming from retry pass fixes #172.

This commit is contained in:
2018-04-10 02:39:41 +01:00
parent 47e78ba0d4
commit 07f0dfe935
14 changed files with 281 additions and 80 deletions

View File

@@ -82,7 +82,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string outputPrefix, string outputPath, string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar, Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
uint skip, uint skip,
bool nometadata) bool nometadata, bool notrim)
{ {
bool aborted; bool aborted;
@@ -238,6 +238,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE); ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock); if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
bool newTrim = false;
start = DateTime.UtcNow; start = DateTime.UtcNow;
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead) for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
@@ -283,6 +284,7 @@ namespace DiscImageChef.Core.Devices.Dumping
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead; i += skip - blocksToRead;
newTrim = true;
} }
double newSpeed = double newSpeed =
@@ -303,6 +305,41 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.", dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration); (double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
totalDuration += duration;
if(error) continue;
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputPlugin.WriteSector(cmdBuf, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Trimming
#region Error handling #region Error handling
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0) if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
{ {

View File

@@ -91,7 +91,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string outputPrefix, string outputPath, string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions, Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar, uint skip, CICMMetadataType preSidecar, uint skip,
bool nometadata) bool nometadata, bool notrim)
{ {
uint subSize; uint subSize;
DateTime start; DateTime start;
@@ -783,6 +783,7 @@ namespace DiscImageChef.Core.Devices.Dumping
double imageWriteDuration = 0; double imageWriteDuration = 0;
if(skip < blocksToRead) skip = blocksToRead; if(skip < blocksToRead) skip = blocksToRead;
bool newTrim = false;
// Start reading // Start reading
start = DateTime.UtcNow; start = DateTime.UtcNow;
@@ -873,6 +874,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead; i += skip - blocksToRead;
newTrim = true;
} }
double newSpeed = double newSpeed =
@@ -894,6 +896,60 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.", dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration); (double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Compact Disc Error trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
if(readcd)
{
sense = true;
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)badSector, blockSize, 1,
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
true, MmcErrorField.None, supportedSubchannel, dev.Timeout,
out double cmdDuration);
totalDuration += cmdDuration;
}
if(sense || dev.Error) continue;
if(!sense && !dev.Error)
{
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
}
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[SECTOR_SIZE];
byte[] sub = new byte[subSize];
Array.Copy(readBuffer, 0, data, 0, SECTOR_SIZE);
Array.Copy(readBuffer, SECTOR_SIZE, sub, 0, subSize);
outputPlugin.WriteSectorLong(data, badSector);
outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel);
}
else outputPlugin.WriteSectorLong(readBuffer, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Compact Disc Error trimming
#region Compact Disc Error handling #region Compact Disc Error handling
// TODO: Pass 0 should be called differently, splitting, or something like that, because we are just // TODO: Pass 0 should be called differently, splitting, or something like that, because we are just
// separating skipped good sectors from really bad sectors and it's getting too chatty on log there... // separating skipped good sectors from really bad sectors and it's getting too chatty on log there...

View File

@@ -75,16 +75,16 @@ namespace DiscImageChef.Core.Devices.Dumping
/// <param name="outputPath">Path to output file</param> /// <param name="outputPath">Path to output file</param>
/// <param name="formatOptions">Formats to pass to output file plugin</param> /// <param name="formatOptions">Formats to pass to output file plugin</param>
/// <exception cref="NotImplementedException">If trying to dump GOD or WOD, or XGDs without a Kreon drive</exception> /// <exception cref="NotImplementedException">If trying to dump GOD or WOD, or XGDs without a Kreon drive</exception>
internal static void Dump(Device dev, string devicePath, IWritableImage outputPlugin, ushort retryPasses, internal static void Dump(Device dev, string devicePath,
bool force, bool dumpRaw, bool persistent, bool stopOnError, IWritableImage outputPlugin, ushort retryPasses,
ref MediaType dskType, bool force, bool dumpRaw,
ref bool persistent, bool stopOnError, ref MediaType dskType,
Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, ref Resume resume, ref DumpLog dumpLog,
Encoding encoding, bool dumpLeadIn, Encoding encoding,
string string outputPrefix, string outputPath,
outputPrefix, string outputPath, Dictionary<string, string> formatOptions, Dictionary<string, string> formatOptions,
CICMMetadataType CICMMetadataType preSidecar, uint skip,
preSidecar, uint skip, bool nometadata) bool nometadata, bool notrim)
{ {
bool sense; bool sense;
ulong blocks; ulong blocks;
@@ -200,7 +200,7 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
CompactDisc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, CompactDisc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath, ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
formatOptions, preSidecar, skip, nometadata); formatOptions, preSidecar, skip, nometadata, notrim);
return; return;
} }
@@ -602,13 +602,13 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
Xgd.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags, Xgd.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions, ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
preSidecar, skip, nometadata); preSidecar, skip, nometadata, notrim);
return; return;
} }
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags, Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions, ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
preSidecar, skip, nometadata); preSidecar, skip, nometadata, notrim);
} }
internal static void AddMediaTagToSidecar(string outputPath, internal static void AddMediaTagToSidecar(string outputPath,

View File

@@ -50,7 +50,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DumpLog dumpLog, Encoding encoding, string outputPrefix, DumpLog dumpLog, Encoding encoding, string outputPrefix,
string outputPath, string outputPath,
Dictionary<string, string> Dictionary<string, string>
formatOptions, CICMMetadataType preSidecar, uint skip, bool nometadata) formatOptions, CICMMetadataType preSidecar, uint skip, bool nometadata, bool notrim)
{ {
throw new NotImplementedException("NVMe devices not yet supported."); throw new NotImplementedException("NVMe devices not yet supported.");
} }

View File

@@ -87,7 +87,7 @@ namespace DiscImageChef.Core.Devices.Dumping
Encoding encoding, string outputPrefix, Encoding encoding, string outputPrefix,
string outputPath, Dictionary<string, string> formatOptions, string outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar, uint skip, CICMMetadataType preSidecar, uint skip,
bool nometadata) bool nometadata, bool notrim)
{ {
bool sense; bool sense;
ulong blocks; ulong blocks;
@@ -347,6 +347,7 @@ namespace DiscImageChef.Core.Devices.Dumping
throw new InvalidOperationException("Could not process resume file, not continuing..."); throw new InvalidOperationException("Could not process resume file, not continuing...");
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock); if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
bool newTrim = false;
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead) for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
{ {
@@ -397,6 +398,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead; i += skip - blocksToRead;
newTrim = true;
} }
double newSpeed = double newSpeed =
@@ -417,6 +419,39 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.", dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration); (double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration);
if(sense || dev.Error) continue;
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputPlugin.WriteSector(readBuffer, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Trimming
#region Error handling #region Error handling
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0) if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
{ {

View File

@@ -70,16 +70,15 @@ namespace DiscImageChef.Core.Devices.Dumping
/// <param name="outputPath">Path to output file</param> /// <param name="outputPath">Path to output file</param>
/// <param name="formatOptions">Formats to pass to output file plugin</param> /// <param name="formatOptions">Formats to pass to output file plugin</param>
/// <exception cref="ArgumentException">If you asked to dump long sectors from a SCSI Streaming device</exception> /// <exception cref="ArgumentException">If you asked to dump long sectors from a SCSI Streaming device</exception>
public static void Dump(Device dev, string devicePath, IWritableImage outputPlugin, ushort retryPasses, public static void Dump(Device dev, string devicePath,
bool force, bool dumpRaw, bool persistent, bool stopOnError, IWritableImage outputPlugin, ushort retryPasses,
ref Resume resume, bool force, bool dumpRaw,
ref bool persistent, bool stopOnError, ref Resume resume,
DumpLog dumpLog, bool dumpLeadIn, Encoding encoding, ref DumpLog dumpLog, bool dumpLeadIn,
string outputPrefix, Encoding encoding, string outputPrefix,
string string outputPath, Dictionary<string, string> formatOptions,
outputPath, Dictionary<string, string> formatOptions, CICMMetadataType preSidecar, uint skip, bool nometadata,
CICMMetadataType bool notrim)
preSidecar, uint skip, bool nometadata)
{ {
MediaType dskType = MediaType.Unknown; MediaType dskType = MediaType.Unknown;
int resets = 0; int resets = 0;
@@ -212,12 +211,12 @@ namespace DiscImageChef.Core.Devices.Dumping
case PeripheralDeviceTypes.MultiMediaDevice: case PeripheralDeviceTypes.MultiMediaDevice:
Mmc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, Mmc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath, ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
formatOptions, preSidecar, skip, nometadata); formatOptions, preSidecar, skip, nometadata, notrim);
return; return;
default: default:
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, null, Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, null,
ref dskType, false, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, ref dskType, false, ref resume, ref dumpLog, encoding, outputPrefix, outputPath,
formatOptions, preSidecar, skip, nometadata); formatOptions, preSidecar, skip, nometadata, notrim);
break; break;
} }
} }

View File

@@ -80,7 +80,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string outputPrefix, string outputPath, string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar, Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
uint skip, uint skip,
bool nometadata) bool nometadata, bool notrim)
{ {
bool aborted; bool aborted;
@@ -280,6 +280,7 @@ namespace DiscImageChef.Core.Devices.Dumping
start = DateTime.UtcNow; start = DateTime.UtcNow;
double imageWriteDuration = 0; double imageWriteDuration = 0;
bool newTrim = false;
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead) for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
{ {
@@ -325,6 +326,7 @@ namespace DiscImageChef.Core.Devices.Dumping
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i); dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead; i += skip - blocksToRead;
newTrim = true;
} }
double newSpeed = double newSpeed =
@@ -345,6 +347,42 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.", dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration); (double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
error = dev.Read(out cmdBuf, out _, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
out duration);
totalDuration += duration;
if(error) continue;
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputPlugin.WriteSector(cmdBuf, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Trimming
#region Error handling #region Error handling
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0) if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
{ {

View File

@@ -90,7 +90,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string outputPrefix, string outputPath, string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar, Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
uint skip, uint skip,
bool nometadata) bool nometadata, bool notrim)
{ {
bool sense; bool sense;
ulong blocks; ulong blocks;
@@ -377,6 +377,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ulong currentSector = resume.NextBlock; ulong currentSector = resume.NextBlock;
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock); if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
bool newTrim = false;
dumpLog.WriteLine("Reading game partition."); dumpLog.WriteLine("Reading game partition.");
for(int e = 0; e <= 16; e++) for(int e = 0; e <= 16; e++)
@@ -473,6 +474,7 @@ namespace DiscImageChef.Core.Devices.Dumping
StringSplitOptions StringSplitOptions
.RemoveEmptyEntries); .RemoveEmptyEntries);
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine); foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
newTrim = true;
} }
double newSpeed = double newSpeed =
@@ -649,6 +651,41 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.", dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / imageWriteDuration); (double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)badSector,
BLOCK_SIZE, 0, 1, false, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
if(sense || dev.Error) continue;
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputPlugin.WriteSector(readBuffer, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Trimming
#region Error handling #region Error handling
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0) if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
{ {

View File

@@ -1 +0,0 @@
../../Changelog.md

View File

@@ -1 +0,0 @@
../../DONATING.md

View File

@@ -1 +0,0 @@
../../README.md

View File

@@ -1 +0,0 @@
../../TODO.md

View File

@@ -207,26 +207,28 @@ namespace DiscImageChef.Commands
case DeviceType.ATA: case DeviceType.ATA:
Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix, options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, options.NoMetadata); options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, options.NoMetadata,
options.NoTrim);
break; break;
case DeviceType.MMC: case DeviceType.MMC:
case DeviceType.SecureDigital: case DeviceType.SecureDigital:
SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog,
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar,
options.NoMetadata); (uint)options.Skip, options.NoMetadata, options.NoTrim);
break; break;
case DeviceType.NVMe: case DeviceType.NVMe:
NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix, options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, options.NoMetadata); options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, options.NoMetadata,
options.NoTrim);
break; break;
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI:
Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, options.LeadIn, options.Persistent, options.StopOnError, ref resume, ref dumpLog, options.LeadIn,
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
options.NoMetadata); options.NoMetadata, options.NoTrim);
break; break;
default: default:
dumpLog.WriteLine("Unknown device type."); dumpLog.WriteLine("Unknown device type.");

View File

@@ -93,12 +93,10 @@ namespace DiscImageChef
[Option("crc64", Default = false, HelpText = "Calculates CRC64 (ECMA).")] [Option("crc64", Default = false, HelpText = "Calculates CRC64 (ECMA).")]
public bool DoCrc64 { get; set; } public bool DoCrc64 { get; set; }
[Option("fletcher16", Default = false, [Option("fletcher16", Default = false, HelpText = "Calculates Fletcher-16.")]
HelpText = "Calculates Fletcher-16.")]
public bool DoFletcher16 { get; set; } public bool DoFletcher16 { get; set; }
[Option("fletcher32", Default = false, [Option("fletcher32", Default = false, HelpText = "Calculates Fletcher-32.")]
HelpText = "Calculates Fletcher-32.")]
public bool DoFletcher32 { get; set; } public bool DoFletcher32 { get; set; }
[Option('m', "md5", Default = true, HelpText = "Calculates MD5.")] [Option('m', "md5", Default = true, HelpText = "Calculates MD5.")]
@@ -314,6 +312,9 @@ namespace DiscImageChef
[Option("no-metadata", Default = false, HelpText = "Disables creating CICM XML sidecar.")] [Option("no-metadata", Default = false, HelpText = "Disables creating CICM XML sidecar.")]
public bool NoMetadata { get; set; } public bool NoMetadata { get; set; }
[Option("no-trim", Default = false, HelpText = "Disables trimming errored from skipped sectors.")]
public bool NoTrim { get; set; }
} }
[Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")] [Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")]