* 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,8 @@
2016-02-04 Natalia Portillo <claunia@claunia.com>
* commandline:
2016-02-03 Natalia Portillo <claunia@claunia.com>
* commandline:

View File

@@ -1,3 +1,11 @@
2016-02-04 Natalia Portillo <claunia@claunia.com>
* SCSI/Modes.cs:
* SCSI/ModesEncoders.cs:
* DiscImageChef.Decoders.csproj:
Added encoders for Mode 6 and 10, Mode pages 0x01 and 0x01
for MultiMedia Devices.
2016-02-03 Natalia Portillo <claunia@claunia.com>
* SCSI/Inquiry.cs:

View File

@@ -90,6 +90,7 @@
<Compile Include="SCSI\SSC\BlockLimits.cs" />
<Compile Include="SCSI\SSC\DensitySupport.cs" />
<Compile Include="SCSI\Types.cs" />
<Compile Include="SCSI\ModesEncoders.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

View File

@@ -41,7 +41,7 @@ using System.Collections.Generic;
namespace DiscImageChef.Decoders.SCSI
{
public static class Modes
public static partial class Modes
{
public struct BlockDescriptor
{

View File

@@ -0,0 +1,319 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : ModesEncoders.cs
// Version : 1.0
// Author(s) : Natalia Portillo
//
// Component : Component
//
// Revision : $Revision$
// Last change by : $Author$
// Date : $Date$
//
// --[ Description ] ----------------------------------------------------------
//
// Description
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright (C) 2011-2015 Claunia.com
// ****************************************************************************/
// //$Id$
using System;
namespace DiscImageChef.Decoders.SCSI
{
public static partial class Modes
{
public static byte[] EncodeModeHeader6(ModeHeader header, PeripheralDeviceTypes deviceType)
{
byte[] hdr;
if (header.BlockDescriptors != null)
hdr = new byte[4 + header.BlockDescriptors.Length * 8];
else
hdr = new byte[4];
hdr[1] = (byte)header.MediumType;
if (deviceType == PeripheralDeviceTypes.DirectAccess || deviceType == PeripheralDeviceTypes.MultiMediaDevice)
{
if (header.WriteProtected)
hdr[2] += 0x80;
if (header.DPOFUA)
hdr[2] += 0x10;
}
if (deviceType == PeripheralDeviceTypes.SequentialAccess)
{
if (header.WriteProtected)
hdr[2] += 0x80;
hdr[2] += (byte)(header.Speed & 0x0F);
hdr[2] += (byte)((header.BufferedMode << 4) & 0x70);
}
if (deviceType == PeripheralDeviceTypes.PrinterDevice)
hdr[2] += (byte)((header.BufferedMode << 4) & 0x70);
if (deviceType == PeripheralDeviceTypes.OpticalDevice)
{
if (header.WriteProtected)
hdr[2] += 0x80;
if (header.EBC)
hdr[2] += 0x01;
if (header.DPOFUA)
hdr[2] += 0x10;
}
if (header.BlockDescriptors != null)
{
hdr[3] = (byte)(header.BlockDescriptors.Length * 8);
for (int i = 0; i < header.BlockDescriptors.Length; i++)
{
hdr[0 + i * 8 + 4] = (byte)header.BlockDescriptors[i].Density;
hdr[1 + i * 8 + 4] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF0000) >> 16);
hdr[2 + i * 8 + 4] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF00) >> 8);
hdr[3 + i * 8 + 4] = (byte)(header.BlockDescriptors[i].Blocks & 0xFF);
hdr[5 + i * 8 + 4] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF0000) >> 16);
hdr[6 + i * 8 + 4] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF00) >> 8);
hdr[7 + i * 8 + 4] = (byte)(header.BlockDescriptors[i].BlockLength & 0xFF);
}
}
return hdr;
}
public static byte[] EncodeMode6(DecodedMode mode, PeripheralDeviceTypes deviceType)
{
int modeSize = 0;
if (mode.Pages != null)
{
foreach (ModePage page in mode.Pages)
modeSize += page.PageResponse.Length;
}
byte[] hdr = EncodeModeHeader6(mode.Header, deviceType);
modeSize += hdr.Length;
byte[] md = new byte[modeSize];
Array.Copy(hdr, 0, md, 0, hdr.Length);
if (mode.Pages != null)
{
int offset = hdr.Length;
foreach (ModePage page in mode.Pages)
{
Array.Copy(page.PageResponse, 0, md, offset, page.PageResponse.Length);
offset += page.PageResponse.Length;
}
}
return md;
}
public static byte[] EncodeMode10(DecodedMode mode, PeripheralDeviceTypes deviceType)
{
int modeSize = 0;
if (mode.Pages != null)
{
foreach (ModePage page in mode.Pages)
modeSize += page.PageResponse.Length;
}
byte[] hdr = EncodeModeHeader10(mode.Header, deviceType);
modeSize += hdr.Length;
byte[] md = new byte[modeSize];
Array.Copy(hdr, 0, md, 0, hdr.Length);
if (mode.Pages != null)
{
int offset = hdr.Length;
foreach (ModePage page in mode.Pages)
{
Array.Copy(page.PageResponse, 0, md, offset, page.PageResponse.Length);
offset += page.PageResponse.Length;
}
}
return md;
}
public static byte[] EncodeModeHeader10(ModeHeader header, PeripheralDeviceTypes deviceType)
{
return EncodeModeHeader10(header, deviceType, false);
}
public static byte[] EncodeModeHeader10(ModeHeader header, PeripheralDeviceTypes deviceType, bool longLBA)
{
byte[] hdr;
if (header.BlockDescriptors != null)
{
if (longLBA)
hdr = new byte[8 + header.BlockDescriptors.Length * 16];
else
hdr = new byte[8 + header.BlockDescriptors.Length * 8];
}
else
hdr = new byte[8];
hdr[2] = (byte)header.MediumType;
if (deviceType == PeripheralDeviceTypes.DirectAccess || deviceType == PeripheralDeviceTypes.MultiMediaDevice)
{
if (header.WriteProtected)
hdr[3] += 0x80;
if (header.DPOFUA)
hdr[3] += 0x10;
}
if (deviceType == PeripheralDeviceTypes.SequentialAccess)
{
if (header.WriteProtected)
hdr[3] += 0x80;
hdr[3] += (byte)(header.Speed & 0x0F);
hdr[3] += (byte)((header.BufferedMode << 4) & 0x70);
}
if (deviceType == PeripheralDeviceTypes.PrinterDevice)
hdr[3] += (byte)((header.BufferedMode << 4) & 0x70);
if (deviceType == PeripheralDeviceTypes.OpticalDevice)
{
if (header.WriteProtected)
hdr[3] += 0x80;
if (header.EBC)
hdr[3] += 0x01;
if (header.DPOFUA)
hdr[3] += 0x10;
}
if (longLBA)
hdr[4] += 0x01;
if (header.BlockDescriptors != null)
{
if (longLBA)
{
for (int i = 0; i < header.BlockDescriptors.Length; i++)
{
byte[] temp = BitConverter.GetBytes(header.BlockDescriptors[i].Blocks);
hdr[7 + i * 16 + 8] = temp[0];
hdr[6 + i * 16 + 8] = temp[1];
hdr[5 + i * 16 + 8] = temp[2];
hdr[4 + i * 16 + 8] = temp[3];
hdr[3 + i * 16 + 8] = temp[4];
hdr[2 + i * 16 + 8] = temp[5];
hdr[1 + i * 16 + 8] = temp[6];
hdr[0 + i * 16 + 8] = temp[7];
hdr[12 + i * 16 + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF000000) >> 24);
hdr[13 + i * 16 + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF0000) >> 16);
hdr[14 + i * 16 + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF00) >> 8);
hdr[15 + i * 16 + 8] = (byte)(header.BlockDescriptors[i].BlockLength & 0xFF);
}
}
else
{
for (int i = 0; i < header.BlockDescriptors.Length; i++)
{
if (deviceType != PeripheralDeviceTypes.DirectAccess)
hdr[0 + i * 8 + 8] = (byte)header.BlockDescriptors[i].Density;
else
hdr[0 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF000000) >> 24);
hdr[1 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF0000) >> 16);
hdr[2 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF00) >> 8);
hdr[3 + i * 8 + 8] = (byte)(header.BlockDescriptors[i].Blocks & 0xFF);
hdr[5 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF0000) >> 16);
hdr[6 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF00) >> 8);
hdr[7 + i * 8 + 8] = (byte)(header.BlockDescriptors[i].BlockLength & 0xFF);
}
}
}
return hdr;
}
public static byte[] EncodeModePage_01(ModePage_01 page)
{
byte[] pg = new byte[8];
pg[0] = 0x01;
pg[1] = 6;
if (page.PS)
pg[0] += 0x80;
if (page.AWRE)
pg[2] += 0x80;
if (page.ARRE)
pg[2] += 0x40;
if (page.TB)
pg[2] += 0x20;
if (page.RC)
pg[2] += 0x10;
if (page.EER)
pg[2] += 0x08;
if (page.PER)
pg[2] += 0x04;
if (page.DTE)
pg[2] += 0x02;
if (page.DCR)
pg[2] += 0x01;
pg[3] = page.ReadRetryCount;
pg[4] = page.CorrectionSpan;
pg[5] = (byte)page.HeadOffsetCount;
pg[6] = (byte)page.DataStrobeOffsetCount;
// This is from a newer version of SCSI unknown what happen for drives expecting an 8 byte page
/*
pg[8] = page.WriteRetryCount;
if (page.LBPERE)
pg[7] += 0x80;
pg[10] = (byte)((page.RecoveryTimeLimit & 0xFF00) << 8);
pg[11] = (byte)(page.RecoveryTimeLimit & 0xFF);*/
return pg;
}
public static byte[] EncodeModePage_01_MMC(ModePage_01_MMC page)
{
byte[] pg = new byte[12];
pg[0] = 0x01;
pg[1] = 10;
if (page.PS)
pg[0] += 0x80;
pg[2] = page.Parameter;
pg[3] = page.ReadRetryCount;
// This is from a newer version of SCSI unknown what happen for drives expecting an 8 byte page
pg[8] = page.WriteRetryCount;
pg[10] = (byte)((page.RecoveryTimeLimit & 0xFF00) << 8);
pg[11] = (byte)(page.RecoveryTimeLimit & 0xFF);
return pg;
}
}
}

View File

@@ -1,3 +1,8 @@
2016-02-04 Natalia Portillo <claunia@claunia.com>
* Device/ScsiCommands/SPC.cs:
Added MODE SELECT (6) and MODE SELECT (10) commands.
2016-02-03 Natalia Portillo <claunia@claunia.com>
* Device/Constructor.cs:

View File

@@ -690,6 +690,91 @@ namespace DiscImageChef.Devices
{
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, volume, partition, firstAttribute, cache, timeout, out duration);
}
/// <summary>
/// Sends the SPC MODE SELECT(6) command
/// </summary>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
/// <param name="buffer">Buffer with the data to be sent to the device</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ModeSelect(byte[] buffer, out byte[] senseBuffer, bool pageFormat, bool savePages, uint timeout, out double duration)
{
senseBuffer = new byte[32];
// Prevent overflows
if (buffer.Length > 255)
{
if (platformID != Interop.PlatformID.Win32NT && platformID != Interop.PlatformID.Win32S && platformID != Interop.PlatformID.Win32Windows && platformID != Interop.PlatformID.WinCE && platformID != Interop.PlatformID.WindowsPhone && platformID != Interop.PlatformID.Xbox)
lastError = 75;
else
lastError = 111;
error = true;
duration = 0;
return true;
}
byte[] cdb = new byte[6];
bool sense;
cdb[0] = (byte)ScsiCommands.ModeSelect;
if (pageFormat)
cdb[1] += 0x10;
if (savePages)
cdb[1] += 0x01;
cdb[4] = (byte)buffer.Length;
lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration, out sense);
error = lastError != 0;
DicConsole.DebugWriteLine("SCSI Device", "MODE SELECT(6) took {0} ms.", duration);
return sense;
}
/// <summary>
/// Sends the SPC MODE SELECT(10) command
/// </summary>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
/// <param name="buffer">Buffer with the data to be sent to the device</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ModeSelect10(byte[] buffer, out byte[] senseBuffer, bool pageFormat, bool savePages, uint timeout, out double duration)
{
senseBuffer = new byte[32];
// Prevent overflows
if (buffer.Length > 65535)
{
if (platformID != Interop.PlatformID.Win32NT && platformID != Interop.PlatformID.Win32S && platformID != Interop.PlatformID.Win32Windows && platformID != Interop.PlatformID.WinCE && platformID != Interop.PlatformID.WindowsPhone && platformID != Interop.PlatformID.Xbox)
lastError = 75;
else
lastError = 111;
error = true;
duration = 0;
return true;
}
byte[] cdb = new byte[10];
bool sense;
cdb[0] = (byte)ScsiCommands.ModeSelect10;
if (pageFormat)
cdb[1] += 0x10;
if (savePages)
cdb[1] += 0x01;
cdb[7] = (byte)((buffer.Length & 0xFF00) << 8);
cdb[8] = (byte)(buffer.Length & 0xFF);
lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration, out sense);
error = lastError != 0;
DicConsole.DebugWriteLine("SCSI Device", "MODE SELECT(10) took {0} ms.", duration);
return sense;
}
}
}

View File

@@ -1,3 +1,8 @@
2016-02-04 Natalia Portillo <claunia@claunia.com>
* FFS.cs:
Corrected array initialization.
2016-01-16 Natalia Portillo <claunia@claunia.com>
* FAT.cs:

View File

@@ -308,9 +308,11 @@ namespace DiscImageChef.Plugins
Array.Copy(ufs_sb_sectors, 0x00D4, strings_b, 0, 512);
ufs_sb.fs_fsmnt_ufs1 = StringHandlers.CToString(strings_b); /// <summary>0x00D4, 512 bytes, name mounted on
ufs_sb.fs_cgrotor_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); /// <summary>0x02D4 last cg searched
ufs_sb.fs_cs_ufs1 = new byte[124];
Array.Copy(ufs_sb_sectors, 0x02D8, ufs_sb.fs_cs_ufs1, 0, 124); /// <summary>0x02D8, 124 bytes, UInt32s, list of fs_cs info buffers
ufs_sb.fs_maxcluster_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0354); /// <summary>0x0354
ufs_sb.fs_cpc_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0358); /// <summary>0x0358 cyl per cycle in postbl
ufs_sb.fs_opostbl_ufs1 = new byte[256];
Array.Copy(ufs_sb_sectors, 0x035C, ufs_sb.fs_opostbl_ufs1, 0, 256); /// <summary>0x035C, 256 bytes, [16][8] matrix of UInt16s, old rotation block list head
#endregion UFS1
#region UFS2
@@ -323,6 +325,7 @@ namespace DiscImageChef.Plugins
ufs_sb.fs_swuid_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02C8); /// <summary>0x02C8 system-wide uid
ufs_sb.fs_pad_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02D0); /// <summary>0x02D0 due to alignment of fs_swuid
ufs_sb.fs_cgrotor_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02D4); /// <summary>0x02D4 last cg searched
ufs_sb.fs_ocsp_ufs2 = new byte[112];
Array.Copy(ufs_sb_sectors, 0x02D8, ufs_sb.fs_ocsp_ufs2, 0, 112); /// <summary>0x02D8, 112 bytes, UInt32s, list of fs_cs info buffers
ufs_sb.fs_contigdirs_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0348); /// <summary>0x0348 # of contiguously allocated dirs
ufs_sb.fs_csp_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x034C); /// <summary>0x034C cg summary info buffer for fs_cs
@@ -330,6 +333,7 @@ namespace DiscImageChef.Plugins
ufs_sb.fs_active_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0354); /// <summary>0x0354 used by snapshots to track fs
ufs_sb.fs_old_cpc_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0358); /// <summary>0x0358 cyl per cycle in postbl
ufs_sb.fs_maxbsize_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x035C); /// <summary>0x035C maximum blocking factor permitted
ufs_sb.fs_sparecon64_ufs2 = new byte[136];
Array.Copy(ufs_sb_sectors, 0x0360, ufs_sb.fs_sparecon64_ufs2, 0, 136); /// <summary>0x0360, 136 bytes, UInt64s, old rotation block list head
ufs_sb.fs_sblockloc_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x03E8); /// <summary>0x03E8 byte offset of standard superblock
//cylinder summary information*/
@@ -350,6 +354,7 @@ namespace DiscImageChef.Plugins
ufs_sb.fs_pendinginodes_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0458); /// <summary>0x0458 inodes in process of being freed
#endregion UFS2
#region Sun
ufs_sb.fs_sparecon_sun = new byte[212];
Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_sun, 0, 212); /// <summary>0x045C, 212 bytes, reserved for future constants
ufs_sb.fs_reclaim_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0530); /// <summary>0x0530
ufs_sb.fs_sparecon2_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0534); /// <summary>0x0534
@@ -360,6 +365,7 @@ namespace DiscImageChef.Plugins
ufs_sb.fs_qfmask1_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0548); /// <summary>0x0548 ~usb_fmask
#endregion Sun
#region Sunx86
ufs_sb.fs_sparecon_sun86 = new byte[212];
Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_sun86, 0, 212); /// <summary>0x045C, 212 bytes, reserved for future constants
ufs_sb.fs_reclaim_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0530); /// <summary>0x0530
ufs_sb.fs_sparecon2_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0534); /// <summary>0x0534
@@ -370,6 +376,7 @@ namespace DiscImageChef.Plugins
ufs_sb.fs_qfmask1_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0548); /// <summary>0x0548 ~usb_fmask
#endregion Sunx86
#region 44BSD
ufs_sb.fs_sparecon_44bsd = new byte[200];
Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_44bsd, 0, 200); /// <summary>0x045C, 200 bytes
ufs_sb.fs_contigsumsize_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0524); /// <summary>0x0524 size of cluster summary array
ufs_sb.fs_maxsymlinklen_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0528); /// <summary>0x0528 max length of an internal symlink

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,7 +886,6 @@ namespace DiscImageChef.Commands
ibgIntSpeed = 0;
ibgSnaps = 0;
ibgIntSector = 0;
ibgIntTime = 0;
switch (currentProfile)
{

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