* DiscImageChef.Decoders/SCSI/Modes.cs:

* DiscImageChef.Decoders/SCSI/ModesEncoders.cs:
	* DiscImageChef.Decoders/DiscImageChef.Decoders.csproj:
	  Added encoders for Mode 6 and 10, Mode pages 0x01 and 0x01
	  for MultiMedia Devices.

	* commandline:

	* DiscImageChef.Devices/Device/ScsiCommands/SPC.cs:
	  Added MODE SELECT (6) and MODE SELECT (10) commands.

	* DiscImageChef.Filesystems/FFS.cs:
	  Corrected array initialization.

	* DiscImageChef/Commands/Decode.cs:
	* DiscImageChef/Commands/Verify.cs:
	* DiscImageChef/Commands/Analyze.cs:
	* DiscImageChef/Commands/Entropy.cs:
	* DiscImageChef/Commands/Checksum.cs:
	* DiscImageChef/Commands/PrintHex.cs:
	* DiscImageChef/Commands/CreateSidecar.cs:
	  Check if image file exists before proceeding.

	* DiscImageChef/Commands/MediaInfo.cs:
	* DiscImageChef/Commands/MediaScan.cs:
	* DiscImageChef/Commands/DeviceInfo.cs:
	* DiscImageChef/Commands/DeviceReport.cs:
	  Check if device exists before proceeding.

	* DiscImageChef/Commands/DumpMedia.cs:
	  Check if device exists before proceeding.
	Removed unused code.
	Added error handling procedures for non CDs.

	* DiscImageChef/Options.cs:
	  Remove unused options.
	Added options to control dump-media error handling.
This commit is contained in:
2016-02-04 16:51:03 +00:00
parent d777061105
commit bd80a6246a
23 changed files with 744 additions and 17 deletions

View File

@@ -1,3 +1,29 @@
2016-02-04 Natalia Portillo <claunia@claunia.com>
* Commands/Decode.cs:
* Commands/Verify.cs:
* Commands/Analyze.cs:
* Commands/Entropy.cs:
* Commands/Checksum.cs:
* Commands/PrintHex.cs:
* Commands/CreateSidecar.cs:
Check if image file exists before proceeding.
* Commands/MediaInfo.cs:
* Commands/MediaScan.cs:
* Commands/DeviceInfo.cs:
* Commands/DeviceReport.cs:
Check if device exists before proceeding.
* Commands/DumpMedia.cs:
Check if device exists before proceeding.
Removed unused code.
Added error handling procedures for non CDs.
* Options.cs:
Remove unused options.
Added options to control dump-media error handling.
2016-02-03 Natalia Portillo <claunia@claunia.com>
* Commands/Configure.cs:

View File

@@ -56,7 +56,7 @@ namespace DiscImageChef.Commands
if (!System.IO.File.Exists(options.InputFile))
{
DicConsole.WriteLine("Specified file does not exist.");
DicConsole.ErrorWriteLine("Specified file does not exist.");
return;
}

View File

@@ -68,6 +68,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Checksum command", "--sha512={0}", options.DoSHA512);
DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", options.DoSpamSum);
if (!System.IO.File.Exists(options.InputFile))
{
DicConsole.ErrorWriteLine("Specified file does not exist.");
return;
}
ImagePlugin inputFormat = ImageFormat.Detect(options.InputFile);
if (inputFormat == null)

View File

@@ -58,6 +58,12 @@ namespace DiscImageChef.Commands
plugins.RegisterAllPlugins();
ImagePlugin _imageFormat;
if (!System.IO.File.Exists(options.InputFile))
{
DicConsole.ErrorWriteLine("Specified file does not exist.");
return;
}
try
{
_imageFormat = ImageFormat.Detect(options.InputFile);

View File

@@ -53,6 +53,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", options.DiskTags);
DicConsole.DebugWriteLine("Decode command", "--sector-tags={0}", options.SectorTags);
if (!System.IO.File.Exists(options.InputFile))
{
DicConsole.ErrorWriteLine("Specified file does not exist.");
return;
}
ImagePlugin inputFormat = ImageFormat.Detect(options.InputFile);
if (inputFormat == null)

View File

@@ -53,6 +53,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Device-Info command", "--device={0}", options.DevicePath);
DicConsole.DebugWriteLine("Device-Info command", "--output-prefix={0}", options.OutputPrefix);
if (!System.IO.File.Exists(options.DevicePath))
{
DicConsole.ErrorWriteLine("Specified device does not exist.");
return;
}
if (options.DevicePath.Length == 2 && options.DevicePath[1] == ':' &&
options.DevicePath[0] != '/' && Char.IsLetter(options.DevicePath[0]))
{

View File

@@ -52,6 +52,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Device-Report command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Device-Report command", "--device={0}", options.DevicePath);
if (!System.IO.File.Exists(options.DevicePath))
{
DicConsole.ErrorWriteLine("Specified device does not exist.");
return;
}
if (options.DevicePath.Length == 2 && options.DevicePath[1] == ':' &&
options.DevicePath[0] != '/' && Char.IsLetter(options.DevicePath[0]))
{

View File

@@ -52,7 +52,6 @@ namespace DiscImageChef.Commands
static FileStream mhddFs;
static FileStream dataFs;
// TODO: Implement dump map
static FileStream mapFs;
public static void doDumpMedia(DumpMediaSubOptions options)
{
@@ -63,7 +62,14 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", options.Raw);
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", options.StopOnError);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force);
DicConsole.DebugWriteLine("Dump-Media command", "--reset={0}", options.Reset);
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", options.RetryPasses);
DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", options.Persistent);
if (!System.IO.File.Exists(options.DevicePath))
{
DicConsole.ErrorWriteLine("Specified device does not exist.");
return;
}
if (options.DevicePath.Length == 2 && options.DevicePath[1] == ':' &&
options.DevicePath[0] != '/' && Char.IsLetter(options.DevicePath[0]))
@@ -123,8 +129,8 @@ namespace DiscImageChef.Commands
static void doSCSIMediaScan(DumpMediaSubOptions options, Device dev)
{
byte[] cmdBuf;
byte[] senseBuf;
byte[] cmdBuf = null;
byte[] senseBuf = null;
bool sense = false;
double duration;
ulong blocks = 0;
@@ -135,8 +141,6 @@ namespace DiscImageChef.Commands
if (dev.IsRemovable)
{
bool deviceReset = false;
retryTestReady:
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
if (sense)
{
@@ -1773,6 +1777,200 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine();
closeMHDDLogFile();
#region Error handling
if (unreadableSectors.Count > 0 && !aborted)
{
List<ulong> tmpList = new List<ulong>();
foreach (ulong ur in unreadableSectors)
{
for (ulong i = ur; i < ur + blocksToRead; i++)
tmpList.Add(i);
}
tmpList.Sort();
int pass = 0;
bool forward = true;
bool runningPersistent = false;
unreadableSectors = tmpList;
repeatRetry:
ulong [] tmpArray = unreadableSectors.ToArray();
foreach (ulong badSector in tmpArray)
{
if (aborted)
break;
double cmdDuration = 0;
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : "");
if(readLong16)
{
sense = dev.ReadLong16(out readBuffer, out senseBuf, false, badSector, blockSize, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if(readLong10)
{
sense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, (uint)badSector, (ushort)blockSize, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if(syqReadLong10)
{
sense = dev.SyQuestReadLong10(out readBuffer, out senseBuf, (uint)badSector, blockSize, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if(syqReadLong6)
{
sense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, (uint)badSector, blockSize, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if(hldtstReadRaw)
{
sense = dev.HlDtStReadRawDvd(out readBuffer, out senseBuf, (uint)badSector, blockSize, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if(plextorReadRaw)
{
sense = dev.PlextorReadRawDvd(out readBuffer, out senseBuf, (uint)badSector, blockSize, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if (read16)
{
sense = dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, badSector, blockSize, 0, 1, false, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if (read12)
{
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)badSector, blockSize, 0, 1, false, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if (read10)
{
sense = dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, (uint)badSector, blockSize, 0, (ushort)1, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
else if (read6)
{
sense = dev.Read6(out readBuffer, out senseBuf, (uint)badSector, blockSize, (byte)1, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
}
if (!sense && !dev.Error)
{
unreadableSectors.Remove(badSector);
writeToDataFileAtPosition(readBuffer, badSector, blockSize);
}
else if(runningPersistent)
writeToDataFileAtPosition(readBuffer, badSector, blockSize);
}
if (pass < options.RetryPasses && !aborted && unreadableSectors.Count > 0)
{
pass++;
forward = !forward;
unreadableSectors.Sort();
unreadableSectors.Reverse();
goto repeatRetry;
}
Decoders.SCSI.Modes.DecodedMode? currentMode = null;
Decoders.SCSI.Modes.ModePage? currentModePage = null;
byte [] md6 = null;
byte [] md10 = null;
if (!runningPersistent && options.Persistent)
{
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration);
if (sense)
{
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration);
if (!sense)
currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
}
else
currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
if (currentMode.HasValue)
currentModePage = currentMode.Value.Pages [0];
if (dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
{
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC = new Decoders.SCSI.Modes.ModePage_01_MMC();
pgMMC.PS = false;
pgMMC.ReadRetryCount = 255;
pgMMC.Parameter = 0x20;
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode();
md.Header = new Decoders.SCSI.Modes.ModeHeader();
md.Pages = new Decoders.SCSI.Modes.ModePage [1];
md.Pages [0] = new Decoders.SCSI.Modes.ModePage();
md.Pages [0].Page = 0x01;
md.Pages [0].Subpage = 0x00;
md.Pages [0].PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC);
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
}
else
{
Decoders.SCSI.Modes.ModePage_01 pg = new Decoders.SCSI.Modes.ModePage_01();
pg.PS = false;
pg.AWRE = false;
pg.ARRE = false;
pg.TB = true;
pg.RC = false;
pg.EER = true;
pg.PER = false;
pg.DTE = false;
pg.DCR = false;
pg.ReadRetryCount = 255;
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode();
md.Header = new Decoders.SCSI.Modes.ModeHeader();
md.Pages = new Decoders.SCSI.Modes.ModePage [1];
md.Pages [0] = new Decoders.SCSI.Modes.ModePage();
md.Pages [0].Page = 0x01;
md.Pages [0].Subpage = 0x00;
md.Pages [0].PageResponse = Decoders.SCSI.Modes.EncodeModePage_01(pg);
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
}
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
if (sense)
{
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
}
runningPersistent = true;
if (!sense && !dev.Error)
{
pass = 0;
goto repeatRetry;
}
}
else if (runningPersistent && options.Persistent && currentModePage.HasValue)
{
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode();
md.Header = new Decoders.SCSI.Modes.ModeHeader();
md.Pages = new Decoders.SCSI.Modes.ModePage [1];
md.Pages [0] = currentModePage.Value;
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
if (sense)
{
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
}
}
DicConsole.WriteLine();
}
#endregion Error handling
dataChk = new Core.Checksum();
dataFs.Seek(0, SeekOrigin.Begin);
blocksToRead = 500;
@@ -1917,7 +2115,7 @@ namespace DiscImageChef.Commands
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);
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
DicConsole.WriteLine("{0} sectors could not be read.", errored);
DicConsole.WriteLine("{0} sectors could not be read.", unreadableSectors.Count);
if (unreadableSectors.Count > 0)
{
foreach (ulong bad in unreadableSectors)
@@ -2061,6 +2259,12 @@ namespace DiscImageChef.Commands
dataFs.Write(data, 0, data.Length);
}
static void writeToDataFileAtPosition(byte[] data, ulong block, uint blockSize)
{
dataFs.Seek((long)(block * blockSize), SeekOrigin.Begin);
dataFs.Write(data, 0, data.Length);
}
static void closeDataFile()
{
if (dataFs != null)

View File

@@ -54,6 +54,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Entropy command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("Entropy command", "--duplicated-sectors={0}", options.DuplicatedSectors);
if (!System.IO.File.Exists(options.InputFile))
{
DicConsole.ErrorWriteLine("Specified file does not exist.");
return;
}
ImagePlugin inputFormat = ImageFormat.Detect(options.InputFile);
if (inputFormat == null)

View File

@@ -53,6 +53,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Media-Info command", "--device={0}", options.DevicePath);
DicConsole.DebugWriteLine("Media-Info command", "--output-prefix={0}", options.OutputPrefix);
if (!System.IO.File.Exists(options.DevicePath))
{
DicConsole.ErrorWriteLine("Specified device does not exist.");
return;
}
if (options.DevicePath.Length == 2 && options.DevicePath[1] == ':' &&
options.DevicePath[0] != '/' && Char.IsLetter(options.DevicePath[0]))
{

View File

@@ -61,7 +61,6 @@ namespace DiscImageChef.Commands
static double ibgIntSpeed;
static int ibgSnaps;
static ulong ibgIntSector = 0;
static double ibgIntTime = 0;
static int ibgSampleRate;
public static void doMediaScan(MediaScanSubOptions options)
@@ -72,6 +71,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Media-Scan command", "--mhdd-log={0}", options.MHDDLogPath);
DicConsole.DebugWriteLine("Media-Scan command", "--ibg-log={0}", options.IBGLogPath);
if (!System.IO.File.Exists(options.DevicePath))
{
DicConsole.ErrorWriteLine("Specified device does not exist.");
return;
}
if (options.DevicePath.Length == 2 && options.DevicePath[1] == ':' &&
options.DevicePath[0] != '/' && Char.IsLetter(options.DevicePath[0]))
{
@@ -881,8 +886,7 @@ namespace DiscImageChef.Commands
ibgIntSpeed = 0;
ibgSnaps = 0;
ibgIntSector = 0;
ibgIntTime = 0;
switch (currentProfile)
{
case 0x0001:

View File

@@ -53,6 +53,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", options.LongSectors);
DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", options.WidthBytes);
if (!System.IO.File.Exists(options.InputFile))
{
DicConsole.ErrorWriteLine("Specified file does not exist.");
return;
}
ImagePlugin inputFormat = ImageFormat.Detect(options.InputFile);
if (inputFormat == null)

View File

@@ -52,6 +52,12 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Verify command", "--verify-disc={0}", options.VerifyDisc);
DicConsole.DebugWriteLine("Verify command", "--verify-sectors={0}", options.VerifySectors);
if (!System.IO.File.Exists(options.InputFile))
{
DicConsole.ErrorWriteLine("Specified file does not exist.");
return;
}
ImagePlugin inputFormat = ImageFormat.Detect(options.InputFile);
if (inputFormat == null)

View File

@@ -263,7 +263,6 @@ namespace DiscImageChef
public string InputFile { get; set; }
}
// TODO: Add more options
public class DumpMediaSubOptions : CommonSubOptions
{
[Option('i', "device", Required = true, HelpText = "Device path.")]
@@ -277,16 +276,21 @@ namespace DiscImageChef
public bool Raw { get; set; }
[Option('s', "stop-on-error", DefaultValue = false,
HelpText = "Print sectors with tags included.")]
HelpText = "Stop media dump on first error.")]
public bool StopOnError { get; set; }
[Option('f', "force", DefaultValue = false,
HelpText = "Continue dump whatever happens.")]
public bool Force { get; set; }
[Option("reset", DefaultValue = (ushort)0,
HelpText = "Reset the device after these many errors. 0 to disable.")]
public ushort Reset { get; set; }
[Option('p', "retry-passes", DefaultValue = (ushort)5,
HelpText = "How many retry passes to do.")]
public ushort RetryPasses { get; set; }
[Option("persistent", DefaultValue = false,
HelpText = "Try to recover partial or incorrect data.")]
public bool Persistent { get; set; }
}
public class DeviceReportSubOptions : CommonSubOptions