mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Added dump log creation.
This commit is contained in:
@@ -54,7 +54,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
public class ATA
|
||||
{
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
bool aborted;
|
||||
MHDDLog mhddLog;
|
||||
@@ -78,6 +78,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
uint timeout = 5;
|
||||
double duration;
|
||||
|
||||
dumpLog.WriteLine("Requesting ATA IDENTIFY DEVICE.");
|
||||
sense = dev.AtaIdentify(out byte[] cmdBuf, out Decoders.ATA.AtaErrorRegistersCHS errorChs);
|
||||
if(!sense && Decoders.ATA.Identify.Decode(cmdBuf).HasValue)
|
||||
{
|
||||
@@ -90,6 +91,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(dev.IsUSB)
|
||||
{
|
||||
dumpLog.WriteLine("Reading USB descriptors.");
|
||||
sidecar.BlockMedia[0].USB = new USBType
|
||||
{
|
||||
ProductID = dev.USBProductID,
|
||||
@@ -106,6 +108,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(dev.IsPCMCIA)
|
||||
{
|
||||
dumpLog.WriteLine("Reading PCMCIA CIS.");
|
||||
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
|
||||
{
|
||||
CIS = new DumpType
|
||||
@@ -116,6 +119,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
};
|
||||
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].PCMCIA.CIS.Image, dev.CIS);
|
||||
dumpLog.WriteLine("Decoding PCMCIA CIS.");
|
||||
Decoders.PCMCIA.Tuple[] tuples = CIS.GetTuples(dev.CIS);
|
||||
if(tuples != null)
|
||||
{
|
||||
@@ -178,12 +182,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DataFile dumpFile;
|
||||
|
||||
// Initializate reader
|
||||
dumpLog.WriteLine("Initializing reader.");
|
||||
Reader ataReader = new Reader(dev, timeout, cmdBuf);
|
||||
// Fill reader blocks
|
||||
ulong blocks = ataReader.GetDeviceBlocks();
|
||||
// Check block sizes
|
||||
if(ataReader.GetBlockSize())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get block size: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
@@ -191,12 +197,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
uint physicalsectorsize = ataReader.PhysicalBlockSize;
|
||||
if(ataReader.FindReadCommand())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot find correct read command: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
// Check how many blocks to read, if error show and return
|
||||
if(ataReader.GetBlocksToRead())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get blocks to read: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
@@ -205,6 +213,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
byte heads = ataReader.Heads;
|
||||
byte sectors = ataReader.Sectors;
|
||||
|
||||
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
||||
dumpLog.WriteLine("Device reports {0} cylinders {1} heads {2} sectors per track.", cylinders, heads, sectors);
|
||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per physical block.", physicalsectorsize);
|
||||
|
||||
bool removable = false || (!dev.IsCompactFlash && ataId.GeneralConfiguration.HasFlag(Decoders.ATA.Identify.GeneralConfigurationBit.Removable));
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
@@ -219,6 +233,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile);
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
@@ -227,6 +244,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -262,6 +280,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
@@ -276,11 +295,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
|
||||
#region Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||
{
|
||||
|
||||
int pass = 0;
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
@@ -292,6 +312,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -306,6 +327,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
@@ -344,6 +366,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -366,6 +389,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
ibgLog.Write(currentBlock, currentSpeed * 1024);
|
||||
dumpFile.Write(cmdBuf);
|
||||
extents.Add(currentBlock);
|
||||
dumpLog.WriteLine("Error reading cylinder {0} head {1} sector {2}.", Cy, Hd, Sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -394,15 +418,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
}
|
||||
dataChk = new Checksum();
|
||||
dumpFile.Seek(0, SeekOrigin.Begin);
|
||||
blocksToRead = 500;
|
||||
|
||||
dumpLog.WriteLine("Checksum starts.");
|
||||
for(ulong i = 0; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (byte)(blocks - i);
|
||||
@@ -423,6 +453,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
dumpFile.Close();
|
||||
end = DateTime.UtcNow;
|
||||
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins();
|
||||
@@ -452,8 +484,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(_imageFormat != null)
|
||||
{
|
||||
dumpLog.WriteLine("Getting partitions.");
|
||||
List<Partition> partitions = Partitions.GetAll(_imageFormat);
|
||||
Partitions.AddSchemesToStats(partitions);
|
||||
dumpLog.WriteLine("Found {0} partitions.", partitions.Count);
|
||||
|
||||
if(partitions.Count > 0)
|
||||
{
|
||||
@@ -470,6 +504,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Type = partitions[i].Type
|
||||
};
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme);
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -480,6 +516,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_plugin.GetInformation(_imageFormat, partitions[i], out string foo);
|
||||
lstFs.Add(_plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
}
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
@@ -496,6 +533,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
else
|
||||
{
|
||||
dumpLog.WriteLine("Getting filesystem for whole device.");
|
||||
|
||||
xmlFileSysInfo = new PartitionType[1];
|
||||
xmlFileSysInfo[0] = new PartitionType
|
||||
{
|
||||
@@ -520,6 +559,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_plugin.GetInformation(_imageFormat, wholePart, out string foo);
|
||||
lstFs.Add(_plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
}
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
internal class CompactDisc
|
||||
{
|
||||
// TODO: Add support for resume file
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
MHDDLog mhddLog;
|
||||
IBGLog ibgLog;
|
||||
@@ -84,6 +84,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
// We discarded all discs that falsify a TOC before requesting a real TOC
|
||||
// No TOC, no CD (or an empty one)
|
||||
dumpLog.WriteLine("Reading full TOC");
|
||||
bool tocSense = dev.ReadRawToc(out byte[] cmdBuf, out byte[] senseBuf, 1, dev.Timeout, out double duration);
|
||||
if(!tocSense)
|
||||
{
|
||||
@@ -101,6 +102,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].TOC.Image, tmpBuf);
|
||||
|
||||
// ATIP exists on blank CDs
|
||||
dumpLog.WriteLine("Reading ATIP");
|
||||
sense = dev.ReadAtip(out cmdBuf, out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -128,6 +130,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Disc Information");
|
||||
sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -153,6 +156,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
int sessions = 1;
|
||||
int firstTrackLastSession = 0;
|
||||
|
||||
dumpLog.WriteLine("Reading Session Information");
|
||||
sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -205,6 +209,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dskType = MediaType.CDV;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading PMA");
|
||||
sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -222,6 +227,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading CD-Text from Lead-In");
|
||||
sense = dev.ReadCdText(out cmdBuf, out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -395,10 +401,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
readBuffer = null;
|
||||
|
||||
dumpLog.WriteLine("Reading Lead-in");
|
||||
for(int leadInBlock = -150; leadInBlock < 0 && resume.NextBlock == 0; leadInBlock++)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > maxSpeed && currentSpeed != 0)
|
||||
@@ -454,6 +464,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.WriteLine("Got {0} lead-in sectors.", leadInSectorsGood);
|
||||
dumpLog.WriteLine("Got {0} Lead-in sectors.", leadInSectorsGood);
|
||||
|
||||
while(true)
|
||||
{
|
||||
@@ -471,12 +482,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(dev.Error)
|
||||
{
|
||||
DicConsole.WriteLine("Device error {0} trying to guess ideal transfer length.", dev.LastError);
|
||||
DicConsole.ErrorWriteLine("Device error {0} trying to guess ideal transfer length.", dev.LastError);
|
||||
return;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
|
||||
|
||||
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
|
||||
dumpLog.WriteLine("SCSI device type: {0}.", dev.SCSIType);
|
||||
dumpLog.WriteLine("Media identified as {0}.", dskType);
|
||||
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
DataFile subFile = null;
|
||||
if(separateSubchannel)
|
||||
@@ -488,9 +506,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(separateSubchannel)
|
||||
subFile.Seek(resume.NextBlock, subSize);
|
||||
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
for(int t = 0; t < tracks.Count(); t++)
|
||||
{
|
||||
dumpLog.WriteLine("Reading track {0}", t);
|
||||
|
||||
tracks[t].BytesPerSector = sectorSize;
|
||||
tracks[t].Image = new ImageType
|
||||
{
|
||||
@@ -527,6 +550,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -592,6 +616,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
dumpLog.WriteLine("Error reading {0} sectors from sector {1}.", blocksToRead, i);
|
||||
}
|
||||
|
||||
if(tracks[t].TrackType1 == TrackTypeTrackType.mode1 && !checkedDataFormat)
|
||||
@@ -630,6 +655,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
|
||||
#region Compact Disc Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||
@@ -645,6 +672,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -665,6 +693,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
dumpLog.WriteLine("Correctly retried sector {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
|
||||
if(separateSubchannel)
|
||||
@@ -728,6 +757,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
@@ -754,6 +784,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
@@ -773,6 +804,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
subFile.Seek(0, SeekOrigin.Begin);
|
||||
blocksToRead = 500;
|
||||
|
||||
dumpLog.WriteLine("Checksum starts.");
|
||||
for(int t = 0; t < tracks.Count(); t++)
|
||||
{
|
||||
Checksum trkChk = new Checksum();
|
||||
@@ -781,7 +813,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
for(ulong i = (ulong)tracks[t].StartSector; i <= (ulong)tracks[t].EndSector; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if(((ulong)tracks[t].EndSector + 1 - i) < blocksToRead)
|
||||
blocksToRead = (uint)((ulong)tracks[t].EndSector + 1 - i);
|
||||
@@ -828,6 +863,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
dumpFile.Close();
|
||||
end = DateTime.UtcNow;
|
||||
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
// TODO: Correct this
|
||||
sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray();
|
||||
|
||||
@@ -39,13 +39,14 @@ using System;
|
||||
using DiscImageChef.CommonTypes;
|
||||
using DiscImageChef.Console;
|
||||
using DiscImageChef.Devices;
|
||||
using DiscImageChef.Core.Logging;
|
||||
using Schemas;
|
||||
|
||||
namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal static class MMC
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
byte[] cmdBuf = null;
|
||||
byte[] senseBuf = null;
|
||||
@@ -60,11 +61,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecar.OpticalDisc = new OpticalDiscType[1];
|
||||
sidecar.OpticalDisc[0] = new OpticalDiscType();
|
||||
|
||||
// TODO: Log not only what is it reading, but if it was read correctly or not.
|
||||
|
||||
sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf);
|
||||
currentProfile = ftr.CurrentProfile;
|
||||
dumpLog.WriteLine("Device reports current profile is 0x{0:X4}", ftr.CurrentProfile);
|
||||
|
||||
switch(ftr.CurrentProfile)
|
||||
{
|
||||
@@ -163,16 +167,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(compactDisc)
|
||||
{
|
||||
CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume);
|
||||
CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog);
|
||||
return;
|
||||
}
|
||||
|
||||
Reader scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw);
|
||||
blocks = scsiReader.GetDeviceBlocks();
|
||||
dumpLog.WriteLine("Device reports disc has {0} blocks", blocks);
|
||||
|
||||
#region Nintendo
|
||||
if(dskType == MediaType.Unknown && blocks > 0)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Physical Format Information");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -182,6 +188,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(nintendoPfi.Value.DiskCategory == Decoders.DVD.DiskCategory.Nintendo &&
|
||||
nintendoPfi.Value.PartVersion == 15)
|
||||
{
|
||||
dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
||||
throw new NotImplementedException("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
||||
}
|
||||
}
|
||||
@@ -200,7 +207,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dskType == MediaType.HDDVDROM || dskType == MediaType.HDDVDRW ||
|
||||
dskType == MediaType.HDDVDRWDL)
|
||||
{
|
||||
|
||||
dumpLog.WriteLine("Reading Physical Format Information");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -279,6 +286,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Disc Manufacturing Information");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -301,7 +310,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(sense || !Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue ||
|
||||
(Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue && !Decoders.SCSI.Inquiry.Decode(inqBuf).Value.KreonPresent))
|
||||
{
|
||||
dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
||||
throw new NotImplementedException("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
||||
}
|
||||
|
||||
if(dumpRaw && !force)
|
||||
{
|
||||
@@ -332,6 +344,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#region DVD-ROM
|
||||
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Lead-in Copyright Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -359,6 +372,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM ||
|
||||
dskType == MediaType.HDDVDROM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Burst Cutting Area.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -378,6 +392,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#region DVD-RAM and HD DVD-RAM
|
||||
if(dskType == MediaType.DVDRAM || dskType == MediaType.HDDVDRAM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Disc Description Structure.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_DDS, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -395,6 +410,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Spare Area Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_SpareAreaInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -417,6 +433,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#region DVD-R and DVD-RW
|
||||
if(dskType == MediaType.DVDR || dskType == MediaType.DVDRW)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Pre-Recorded Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -436,6 +453,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#region DVD-R, DVD-RW and HD DVD-R
|
||||
if(dskType == MediaType.DVDR || dskType == MediaType.DVDRW || dskType == MediaType.HDDVDR)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Media Identifier.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_MediaIdentifier, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -450,6 +468,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].MediaID.Image, tmpBuf);
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Recordable Physical Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_PhysicalInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -470,6 +489,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL ||
|
||||
dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL)
|
||||
{
|
||||
dumpLog.WriteLine("Reading ADdress In Pregroove.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.ADIP, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -484,6 +504,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].ADIP.Image, tmpBuf);
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Disc Control Blocks.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DCB, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -503,6 +524,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#region HD DVD-ROM
|
||||
if(dskType == MediaType.HDDVDROM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Lead-in Copyright Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.HDDVD_CopyrightInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -523,6 +545,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.BDR || dskType == MediaType.BDRE || dskType == MediaType.BDROM ||
|
||||
dskType == MediaType.BDRXL || dskType == MediaType.BDREXL)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Disc Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -540,6 +563,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading PAC.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.PAC, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -560,6 +584,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#region BD-ROM only
|
||||
if(dskType == MediaType.BDROM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Burst Cutting Area.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_BurstCuttingArea, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -580,6 +605,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.BDR || dskType == MediaType.BDRE ||
|
||||
dskType == MediaType.BDRXL || dskType == MediaType.BDREXL)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Disc Definition Structure.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_DDS, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -594,6 +620,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].DDS.Image, tmpBuf);
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Spare Area Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_SpareAreaInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -612,11 +639,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(isXbox)
|
||||
{
|
||||
XGD.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, ref resume);
|
||||
XGD.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, ref resume, ref dumpLog);
|
||||
return;
|
||||
}
|
||||
|
||||
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, true, ref resume);
|
||||
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, true, ref resume, ref dumpLog);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,12 +37,13 @@
|
||||
// //$Id$
|
||||
using System;
|
||||
using DiscImageChef.Devices;
|
||||
using DiscImageChef.Core.Logging;
|
||||
|
||||
namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
public static class NVMe
|
||||
{
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
throw new NotImplementedException("NVMe devices not yet supported.");
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal static class SBC
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool opticalDisc, ref Metadata.Resume resume)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool opticalDisc, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
MHDDLog mhddLog;
|
||||
IBGLog ibgLog;
|
||||
@@ -87,11 +87,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
|
||||
dumpLog.WriteLine("Initializing reader.");
|
||||
Reader scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw);
|
||||
blocks = scsiReader.GetDeviceBlocks();
|
||||
blockSize = scsiReader.LogicalBlockSize;
|
||||
if(scsiReader.FindReadCommand())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot find correct read command: {0}.", scsiReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine("Unable to read medium.");
|
||||
return;
|
||||
}
|
||||
@@ -105,6 +107,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
// Check how many blocks to read, if error show and return
|
||||
if(scsiReader.GetBlocksToRead())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get blocks to read: {0}.", scsiReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(scsiReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
@@ -114,6 +117,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(blocks == 0)
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Unable to read medium or empty medium present...");
|
||||
DicConsole.ErrorWriteLine("Unable to read medium or empty medium present...");
|
||||
return;
|
||||
}
|
||||
@@ -126,6 +130,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
DicConsole.WriteLine("Media identified as {0}", dskType);
|
||||
|
||||
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per physical block.", scsiReader.LongBlockSize);
|
||||
dumpLog.WriteLine("SCSI device type: {0}.", dev.SCSIType);
|
||||
dumpLog.WriteLine("SCSI medium type: {0}.", scsiMediumType);
|
||||
dumpLog.WriteLine("SCSI density type: {0}.", scsiDensityCode);
|
||||
dumpLog.WriteLine("SCSI floppy mode page present: {0}.", containsFloppyPage);
|
||||
dumpLog.WriteLine("Media identified as {0}.", dskType);
|
||||
|
||||
if(!opticalDisc)
|
||||
{
|
||||
sidecar.BlockMedia = new BlockMediaType[1];
|
||||
@@ -136,6 +150,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
if(dev.IsUSB)
|
||||
{
|
||||
dumpLog.WriteLine("Reading USB descriptors.");
|
||||
sidecar.BlockMedia[0].USB = new USBType
|
||||
{
|
||||
ProductID = dev.USBProductID,
|
||||
@@ -152,6 +167,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(dev.Type == DeviceType.ATAPI)
|
||||
{
|
||||
dumpLog.WriteLine("Requesting ATAPI IDENTIFY PACKET DEVICE.");
|
||||
sense = dev.AtapiIdentify(out cmdBuf, out Decoders.ATA.AtaErrorRegistersCHS errorRegs);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -171,6 +187,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sense = dev.ScsiInquiry(out cmdBuf, out senseBuf);
|
||||
if(!sense)
|
||||
{
|
||||
dumpLog.WriteLine("Requesting SCSI INQUIRY.");
|
||||
sidecar.BlockMedia[0].SCSI = new SCSIType
|
||||
{
|
||||
Inquiry = new DumpType
|
||||
@@ -182,6 +199,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.BlockMedia[0].SCSI.Inquiry.Image, cmdBuf);
|
||||
|
||||
dumpLog.WriteLine("Reading SCSI Extended Vendor Page Descriptors.");
|
||||
sense = dev.ScsiInquiry(out cmdBuf, out senseBuf, 0x00);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -192,6 +210,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
List<EVPDType> evpds = new List<EVPDType>();
|
||||
foreach(byte page in pages)
|
||||
{
|
||||
dumpLog.WriteLine("Requesting page {0:X2}h.", page);
|
||||
sense = dev.ScsiInquiry(out cmdBuf, out senseBuf, page);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -212,6 +231,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Requesting MODE SENSE (10).");
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration);
|
||||
if(!sense || dev.Error)
|
||||
{
|
||||
@@ -235,6 +255,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Requesting MODE SENSE (6).");
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
if(sense || dev.Error)
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
@@ -327,12 +348,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(currentTry == null || extents == null)
|
||||
throw new Exception("Could not process resume file, not continuing...");
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -376,6 +400,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
@@ -389,6 +414,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
|
||||
#region Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||
@@ -404,6 +431,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -417,6 +445,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
@@ -507,6 +536,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
@@ -533,6 +563,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
@@ -550,10 +581,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpFile.Seek(0, SeekOrigin.Begin);
|
||||
blocksToRead = 500;
|
||||
|
||||
dumpLog.WriteLine("Checksum starts.");
|
||||
for(ulong i = 0; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (uint)(blocks - i);
|
||||
@@ -576,6 +611,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
dumpFile.Close();
|
||||
end = DateTime.UtcNow;
|
||||
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins();
|
||||
@@ -604,8 +641,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(_imageFormat != null)
|
||||
{
|
||||
dumpLog.WriteLine("Getting partitions.");
|
||||
List<Partition> partitions = Partitions.GetAll(_imageFormat);
|
||||
Partitions.AddSchemesToStats(partitions);
|
||||
dumpLog.WriteLine("Found {0} partitions.", partitions.Count);
|
||||
|
||||
if(partitions.Count > 0)
|
||||
{
|
||||
@@ -622,6 +661,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Type = partitions[i].Type
|
||||
};
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme);
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -632,6 +673,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_plugin.GetInformation(_imageFormat, partitions[i], out string foo);
|
||||
lstFs.Add(_plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
|
||||
if(_plugin.XmlFSType.Type == "Opera")
|
||||
dskType = MediaType.ThreeDO;
|
||||
@@ -657,6 +699,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
else
|
||||
{
|
||||
dumpLog.WriteLine("Getting filesystem for whole device.");
|
||||
xmlFileSysInfo = new PartitionType[1];
|
||||
xmlFileSysInfo[0] = new PartitionType
|
||||
{
|
||||
@@ -681,6 +724,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_plugin.GetInformation(_imageFormat, wholePart, out string foo);
|
||||
lstFs.Add(_plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
|
||||
if(_plugin.XmlFSType.Type == "Opera")
|
||||
dskType = MediaType.ThreeDO;
|
||||
|
||||
@@ -40,6 +40,7 @@ using System.IO;
|
||||
using DiscImageChef.CommonTypes;
|
||||
using DiscImageChef.Console;
|
||||
using DiscImageChef.Devices;
|
||||
using DiscImageChef.Core.Logging;
|
||||
using Schemas;
|
||||
|
||||
namespace DiscImageChef.Core.Devices.Dumping
|
||||
@@ -47,7 +48,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
public class SCSI
|
||||
{
|
||||
// TODO: Get cartridge serial number from Certance vendor EVPD
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, bool separateSubchannel, ref Metadata.Resume resume)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, bool separateSubchannel, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
byte[] senseBuf = null;
|
||||
bool sense = false;
|
||||
@@ -61,6 +62,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
if(decSense.Value.ASC == 0x3A)
|
||||
{
|
||||
int leftRetries = 5;
|
||||
@@ -72,6 +74,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
@@ -92,6 +97,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
@@ -125,6 +133,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
@@ -155,17 +166,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dumpRaw)
|
||||
throw new ArgumentException("Tapes cannot be dumped raw.");
|
||||
|
||||
SSC.Dump(dev, outputPrefix, devicePath, ref sidecar, ref resume);
|
||||
SSC.Dump(dev, outputPrefix, devicePath, ref sidecar, ref resume, ref dumpLog);
|
||||
return;
|
||||
}
|
||||
|
||||
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
MMC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume);
|
||||
MMC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog);
|
||||
return;
|
||||
}
|
||||
|
||||
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, false, ref resume);
|
||||
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, false, ref resume, ref dumpLog);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal static class SSC
|
||||
{
|
||||
internal static void Dump(Device dev, string outputPrefix, string devicePath, ref CICMMetadataType sidecar, ref Metadata.Resume resume)
|
||||
internal static void Dump(Device dev, string outputPrefix, string devicePath, ref CICMMetadataType sidecar, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
Decoders.SCSI.FixedSense? fxSense;
|
||||
bool aborted;
|
||||
@@ -73,6 +73,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(fxSense.HasValue && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.NoSense)
|
||||
{
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
DicConsole.ErrorWriteLine("Drive has status error, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
return;
|
||||
@@ -81,6 +82,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
// Not in BOM/P
|
||||
if(fxSense.HasValue && fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x00 && fxSense.Value.ASCQ != 0x04 && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.IllegalRequest)
|
||||
{
|
||||
dumpLog.WriteLine("Rewinding, please wait...");
|
||||
DicConsole.Write("Rewinding, please wait...");
|
||||
// Rewind, let timeout apply
|
||||
sense = dev.Rewind(out senseBuf, dev.Timeout, out duration);
|
||||
@@ -104,6 +106,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,6 +127,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Could not get position. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Could not get position. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -132,6 +138,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(cmdBuf[1] != 0)
|
||||
{
|
||||
DicConsole.Write("Drive not in partition 0. Rewinding, please wait...");
|
||||
dumpLog.WriteLine("Drive not in partition 0. Rewinding, please wait...");
|
||||
// Rewind, let timeout apply
|
||||
sense = dev.Locate(out senseBuf, false, 0, 0, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
@@ -139,6 +146,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -159,6 +168,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -168,6 +179,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,6 +188,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(cmdBuf[1] != 0)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind to partition 0 but no error occurred...");
|
||||
dumpLog.WriteLine("Drive could not rewind to partition 0 but no error occurred...");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -190,6 +204,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
byte scsiMediumTypeTape = 0;
|
||||
byte scsiDensityCodeTape = 0;
|
||||
|
||||
dumpLog.WriteLine("Requesting MODE SENSE (10).");
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration);
|
||||
if(!sense || dev.Error)
|
||||
{
|
||||
@@ -213,6 +228,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Requesting MODE SENSE (6).");
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
if(sense || dev.Error)
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
@@ -241,6 +257,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length >= 1)
|
||||
scsiDensityCodeTape = (byte)decMode.Value.Header.BlockDescriptors[0].Density;
|
||||
blockSize = decMode.Value.Header.BlockDescriptors[0].BlockLength;
|
||||
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
||||
}
|
||||
else
|
||||
blockSize = 1;
|
||||
@@ -250,6 +267,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
DicConsole.WriteLine("Media identified as {0}", dskType);
|
||||
|
||||
dumpLog.WriteLine("SCSI device type: {0}.", dev.SCSIType);
|
||||
dumpLog.WriteLine("SCSI medium type: {0}.", scsiMediumTypeTape);
|
||||
dumpLog.WriteLine("SCSI density type: {0}.", scsiDensityCodeTape);
|
||||
dumpLog.WriteLine("Media identified as {0}.", dskType);
|
||||
|
||||
bool endOfMedia = false;
|
||||
ulong currentBlock = 0;
|
||||
ulong currentFile = 0;
|
||||
@@ -279,6 +301,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not return back. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not return back. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -291,6 +315,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not read. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not read. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -299,6 +325,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not read. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not read. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -306,6 +334,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Cannot read device, don't know why, exiting...");
|
||||
dumpLog.WriteLine("Cannot read device, don't know why, exiting...");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -319,6 +348,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not return back. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not return back. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -374,12 +405,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
while(currentPartition < totalPartitions)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if(endOfMedia)
|
||||
{
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.WriteLine("Finished partition {0}", currentPartition);
|
||||
dumpLog.WriteLine("Finished partition {0}", currentPartition);
|
||||
currentTapePartition.File = files.ToArray();
|
||||
currentTapePartition.Checksums = partitionChk.End().ToArray();
|
||||
currentTapePartition.EndBlock = (long)(currentBlock - 1);
|
||||
@@ -451,6 +486,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.WriteLine("Blocksize changed to {0} bytes at block {1}", blockSize, currentBlock);
|
||||
dumpLog.WriteLine("Blocksize changed to {0} bytes at block {1}", blockSize, currentBlock);
|
||||
|
||||
sense = dev.Space(out senseBuf, SscSpaceCodes.LogicalBlock, -1, dev.Timeout, out duration);
|
||||
totalDuration += duration;
|
||||
@@ -462,6 +498,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Drive could not go back one block. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpFile.Close();
|
||||
dumpLog.WriteLine("Drive could not go back one block. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -475,6 +513,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Cannot dump a blank tape...");
|
||||
dumpFile.Close();
|
||||
dumpLog.WriteLine("Cannot dump a blank tape...");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -483,12 +522,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
// TODO: Detect end of partition
|
||||
endOfMedia = true;
|
||||
dumpLog.WriteLine("Found end-of-tape/partition...");
|
||||
continue;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.WriteLine("Blank block found, end of tape?");
|
||||
endOfMedia = true;
|
||||
dumpLog.WriteLine("Blank block found, end of tape?...");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -497,6 +538,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
// TODO: Detect end of partition
|
||||
endOfMedia = true;
|
||||
dumpLog.WriteLine("Found end-of-tape/partition...");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -527,6 +569,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.WriteLine("Changed to file {0} at block {1}", currentFile, currentBlock);
|
||||
dumpLog.WriteLine("Changed to file {0} at block {1}", currentFile, currentBlock);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -534,6 +577,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
DicConsole.ErrorWriteLine("Drive could not read block. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0} {1}", fxSense.Value.SenseKey, strSense);
|
||||
dumpLog.WriteLine("Drive could not read block. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0:X2}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -562,6 +607,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
end = DateTime.UtcNow;
|
||||
mhddLog.Close();
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).", (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
public class SecureDigital
|
||||
{
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
bool aborted;
|
||||
MHDDLog mhddLog;
|
||||
@@ -99,6 +99,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
ExtendedCSD ecsdDecoded = new ExtendedCSD();
|
||||
CSD csdDecoded = new CSD();
|
||||
|
||||
dumpLog.WriteLine("Reading Extended CSD");
|
||||
sense = dev.ReadExtendedCSD(out ecsd, out response, timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -116,6 +117,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
else
|
||||
ecsd = null;
|
||||
|
||||
dumpLog.WriteLine("Reading CSD");
|
||||
sense = dev.ReadCSD(out csd, out response, timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -129,6 +131,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
else
|
||||
csd = null;
|
||||
|
||||
dumpLog.WriteLine("Reading OCR");
|
||||
sense = dev.ReadOCR(out ocr, out response, timeout, out duration);
|
||||
if(sense)
|
||||
ocr = null;
|
||||
@@ -139,6 +142,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
Decoders.SecureDigital.CSD csdDecoded = new Decoders.SecureDigital.CSD();
|
||||
|
||||
dumpLog.WriteLine("Reading CSD");
|
||||
sense = dev.ReadCSD(out csd, out response, timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
@@ -151,10 +155,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
else
|
||||
csd = null;
|
||||
|
||||
dumpLog.WriteLine("Reading OCR");
|
||||
sense = dev.ReadSDOCR(out ocr, out response, timeout, out duration);
|
||||
if(sense)
|
||||
ocr = null;
|
||||
|
||||
dumpLog.WriteLine("Reading SCR");
|
||||
sense = dev.ReadSCR(out scr, out response, timeout, out duration);
|
||||
if(sense)
|
||||
scr = null;
|
||||
@@ -162,6 +168,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading CID");
|
||||
sense = dev.ReadCID(out cid, out response, timeout, out duration);
|
||||
if(sense)
|
||||
cid = null;
|
||||
@@ -253,9 +260,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(blocks == 0)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get device size.");
|
||||
DicConsole.ErrorWriteLine("Unable to get device size.");
|
||||
return;
|
||||
}
|
||||
dumpLog.WriteLine("Device reports {0} blocks.", blocks);
|
||||
|
||||
byte[] cmdBuf;
|
||||
bool error = true;
|
||||
@@ -274,12 +283,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(error)
|
||||
{
|
||||
blocksToRead = 1;
|
||||
dumpLog.WriteLine("ERROR: Cannot get blocks to read, device error {0}.", dev.LastError);
|
||||
DicConsole.ErrorWriteLine("Device error {0} trying to guess ideal transfer length.", dev.LastError);
|
||||
return;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||
|
||||
// bool removable = false || (!dev.IsCompactFlash && ataId.GeneralConfiguration.HasFlag(Decoders.ATA.Identify.GeneralConfigurationBit.Removable));
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
ResumeSupport.Process(true, false, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents);
|
||||
@@ -292,6 +302,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile);
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
@@ -299,6 +311,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -334,6 +347,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
@@ -348,6 +362,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
|
||||
#region Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||
@@ -364,6 +380,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -378,6 +395,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
@@ -402,10 +420,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpFile.Seek(0, SeekOrigin.Begin);
|
||||
blocksToRead = 500;
|
||||
|
||||
dumpLog.WriteLine("Checksum starts.");
|
||||
for(ulong i = 0; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (byte)(blocks - i);
|
||||
@@ -426,6 +448,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
dumpFile.Close();
|
||||
end = DateTime.UtcNow;
|
||||
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins();
|
||||
@@ -455,8 +479,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(_imageFormat != null)
|
||||
{
|
||||
dumpLog.WriteLine("Getting partitions.");
|
||||
List<Partition> partitions = Partitions.GetAll(_imageFormat);
|
||||
Partitions.AddSchemesToStats(partitions);
|
||||
dumpLog.WriteLine("Found {0} partitions.", partitions.Count);
|
||||
|
||||
if(partitions.Count > 0)
|
||||
{
|
||||
@@ -473,6 +499,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Type = partitions[i].Type
|
||||
};
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme);
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -483,6 +511,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_plugin.GetInformation(_imageFormat, partitions[i], out string foo);
|
||||
lstFs.Add(_plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
}
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
@@ -499,6 +528,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
else
|
||||
{
|
||||
dumpLog.WriteLine("Getting filesystem for whole device.");
|
||||
|
||||
xmlFileSysInfo = new PartitionType[1];
|
||||
xmlFileSysInfo[0] = new PartitionType
|
||||
{
|
||||
@@ -523,6 +554,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_plugin.GetInformation(_imageFormat, wholePart, out string foo);
|
||||
lstFs.Add(_plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
}
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal static class XGD
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, ref Metadata.Resume resume)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
MHDDLog mhddLog;
|
||||
IBGLog ibgLog;
|
||||
@@ -77,16 +77,20 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
|
||||
dumpLog.WriteLine("Reading Xbox Security Sector.");
|
||||
sense = dev.KreonExtractSS(out byte[] ssBuf, out byte[] senseBuf, dev.Timeout, out double duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get Xbox Security Sector, not continuing.");
|
||||
DicConsole.ErrorWriteLine("Cannot get Xbox Security Sector, not continuing.");
|
||||
return;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Decoding Xbox Security Sector.");
|
||||
Decoders.Xbox.SS.SecuritySector? xboxSS = Decoders.Xbox.SS.Decode(ssBuf);
|
||||
if(!xboxSS.HasValue)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot decode Xbox Security Sector, not continuing.");
|
||||
DicConsole.ErrorWriteLine("Cannot decode Xbox Security Sector, not continuing.");
|
||||
return;
|
||||
}
|
||||
@@ -116,22 +120,28 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
// Get video partition size
|
||||
DicConsole.DebugWriteLine("Dump-media command", "Getting video partition size");
|
||||
dumpLog.WriteLine("Locking drive.");
|
||||
sense = dev.KreonLock(out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot lock drive, not continuing.");
|
||||
DicConsole.ErrorWriteLine("Cannot lock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
dumpLog.WriteLine("Getting video partition size.");
|
||||
sense = dev.ReadCapacity(out byte[] readBuffer, out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get disc capacity.");
|
||||
DicConsole.ErrorWriteLine("Cannot get disc capacity.");
|
||||
return;
|
||||
}
|
||||
totalSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3]));
|
||||
dumpLog.WriteLine("Reading Physical Format Information.");
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get PFI.");
|
||||
DicConsole.ErrorWriteLine("Cannot get PFI.");
|
||||
return;
|
||||
}
|
||||
@@ -147,9 +157,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors", totalSize);
|
||||
l0Video = Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN - Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1;
|
||||
l1Video = totalSize - l0Video + 1;
|
||||
dumpLog.WriteLine("Reading Disc Manufacturing Information.");
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get DMI.");
|
||||
DicConsole.ErrorWriteLine("Cannot get DMI.");
|
||||
return;
|
||||
}
|
||||
@@ -165,15 +177,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
// Get game partition size
|
||||
DicConsole.DebugWriteLine("Dump-media command", "Getting game partition size");
|
||||
dumpLog.WriteLine("Unlocking drive (Xtreme).");
|
||||
sense = dev.KreonUnlockXtreme(out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot unlock drive, not continuing.");
|
||||
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
dumpLog.WriteLine("Getting game partition size.");
|
||||
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get disc capacity.");
|
||||
DicConsole.ErrorWriteLine("Cannot get disc capacity.");
|
||||
return;
|
||||
}
|
||||
@@ -182,22 +198,28 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
// Get middle zone size
|
||||
DicConsole.DebugWriteLine("Dump-media command", "Getting middle zone size");
|
||||
dumpLog.WriteLine("Unlocking drive (Wxripper).");
|
||||
sense = dev.KreonUnlockWxripper(out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot unlock drive, not continuing.");
|
||||
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
dumpLog.WriteLine("Getting disc size.");
|
||||
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get disc capacity.");
|
||||
DicConsole.ErrorWriteLine("Cannot get disc capacity.");
|
||||
return;
|
||||
}
|
||||
totalSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3]));
|
||||
dumpLog.WriteLine("Reading Physical Format Information.");
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get PFI.");
|
||||
DicConsole.ErrorWriteLine("Cannot get PFI.");
|
||||
return;
|
||||
}
|
||||
@@ -215,9 +237,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].Xbox.PFI.Image, tmpBuf, "Unlocked PFI", true);
|
||||
|
||||
dumpLog.WriteLine("Reading Disc Manufacturing Information.");
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get DMI.");
|
||||
DicConsole.ErrorWriteLine("Cannot get DMI.");
|
||||
return;
|
||||
}
|
||||
@@ -243,13 +267,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine("Real layer break: {0}", layerBreak);
|
||||
DicConsole.WriteLine();
|
||||
|
||||
dumpLog.WriteLine("Video layer 0 size: {0} sectors", l0Video);
|
||||
dumpLog.WriteLine("Video layer 1 size: {0} sectors", l1Video);
|
||||
dumpLog.WriteLine("Middle zone 0 size: {0} sectors", middleZone);
|
||||
dumpLog.WriteLine("Game data 0 size: {0} sectors", gameSize);
|
||||
dumpLog.WriteLine("Total 0 size: {0} sectors", totalSize);
|
||||
dumpLog.WriteLine("Real layer break: {0}", layerBreak);
|
||||
|
||||
bool read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, false, dev.Timeout, out duration);
|
||||
if(!read12)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot read medium, aborting scan...");
|
||||
DicConsole.ErrorWriteLine("Cannot read medium, aborting scan...");
|
||||
return;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Using SCSI READ (12) command.");
|
||||
DicConsole.WriteLine("Using SCSI READ (12) command.");
|
||||
|
||||
while(true)
|
||||
@@ -267,11 +300,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(dev.Error)
|
||||
{
|
||||
dumpLog.WriteLine("Device error {0} trying to guess ideal transfer length.", dev.LastError);
|
||||
DicConsole.ErrorWriteLine("Device error {0} trying to guess ideal transfer length.", dev.LastError);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dumpLog.WriteLine("Reading {0} sectors at a time.", blocksToRead);
|
||||
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
|
||||
|
||||
mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
@@ -291,13 +325,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
throw new Exception("Could not process resume file, not continuing...");
|
||||
ulong currentSector = resume.NextBlock;
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
dumpLog.WriteLine("Reading game partition.");
|
||||
for(int e = 0; e <= 16; e++)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
resume.NextBlock = currentSector;
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -334,6 +372,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -378,6 +417,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
|
||||
string[] senseLines = Decoders.SCSI.Sense.PrettifySense(senseBuf).Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach(string senseLine in senseLines)
|
||||
dumpLog.WriteLine(senseLine);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
@@ -394,6 +438,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -414,11 +459,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
// Middle Zone D
|
||||
dumpLog.WriteLine("Writing Middle Zone D (empty).");
|
||||
for(ulong middle = currentSector - blocks - 1; middle < (middleZone - 1); middle += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -438,9 +485,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
blocksToRead = saveBlocksToRead;
|
||||
|
||||
dumpLog.WriteLine("Locking drive.");
|
||||
sense = dev.KreonLock(out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot lock drive, not continuing.");
|
||||
DicConsole.ErrorWriteLine("Cannot lock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
@@ -452,11 +501,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
// Video Layer 1
|
||||
dumpLog.WriteLine("Reading Video Layer 1.");
|
||||
for(ulong l1 = currentSector - blocks - middleZone + l0Video; l1 < (l0Video + l1Video); l1 += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -501,6 +552,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
mhddLog.Write(l1, cmdDuration);
|
||||
|
||||
ibgLog.Write(l1, 0);
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, l1);
|
||||
string[] senseLines = Decoders.SCSI.Sense.PrettifySense(senseBuf).Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach(string senseLine in senseLines)
|
||||
dumpLog.WriteLine(senseLine);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
@@ -510,9 +565,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
resume.NextBlock = currentSector;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Unlocking drive (Wxripper).");
|
||||
sense = dev.KreonUnlockWxripper(out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot unlock drive, not continuing.");
|
||||
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
@@ -529,6 +586,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
|
||||
#region Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||
@@ -556,6 +615,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -571,6 +631,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
@@ -661,6 +722,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
@@ -687,6 +749,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
@@ -706,10 +769,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
blocks = totalSize;
|
||||
|
||||
dumpLog.WriteLine("Checksum starts.");
|
||||
for(ulong i = 0; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (uint)(blocks - i);
|
||||
@@ -732,6 +799,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
dumpFile.Close();
|
||||
end = DateTime.UtcNow;
|
||||
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins();
|
||||
@@ -760,8 +829,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(_imageFormat != null)
|
||||
{
|
||||
dumpLog.WriteLine("Getting partitions.");
|
||||
List<Partition> partitions = Partitions.GetAll(_imageFormat);
|
||||
Partitions.AddSchemesToStats(partitions);
|
||||
dumpLog.WriteLine("Found {0} partitions.", partitions.Count);
|
||||
|
||||
if(partitions.Count > 0)
|
||||
{
|
||||
@@ -778,6 +849,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Type = partitions[i].Type
|
||||
};
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme);
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -788,6 +861,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_plugin.GetInformation(_imageFormat, partitions[i], out string foo);
|
||||
lstFs.Add(_plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
|
||||
if(_plugin.XmlFSType.Type == "Opera")
|
||||
dskType = MediaType.ThreeDO;
|
||||
@@ -813,6 +887,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
else
|
||||
{
|
||||
dumpLog.WriteLine("Getting filesystem for whole device.");
|
||||
xmlFileSysInfo = new PartitionType[1];
|
||||
xmlFileSysInfo[0] = new PartitionType
|
||||
{
|
||||
@@ -837,6 +912,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_plugin.GetInformation(_imageFormat, wholePart, out string foo);
|
||||
lstFs.Add(_plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
|
||||
if(_plugin.XmlFSType.Type == "Opera")
|
||||
dskType = MediaType.ThreeDO;
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<Compile Include="Sidecar\LinearMedia.cs" />
|
||||
<Compile Include="Sidecar\AudioMedia.cs" />
|
||||
<Compile Include="Sidecar\BlockTape.cs" />
|
||||
<Compile Include="Logging\DumpLog.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DiscImageChef.Console\DiscImageChef.Console.csproj">
|
||||
@@ -161,7 +162,7 @@
|
||||
<Properties>
|
||||
<Policies>
|
||||
<TextStylePolicy FileWidth="120" TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" TabsToSpaces="True" scope="text/x-csharp" />
|
||||
<CSharpFormattingPolicy IndentBlock="True" IndentBraces="False" IndentSwitchSection="True" IndentSwitchCaseSection="True" LabelPositioning="OneLess" NewLinesForBracesInTypes="True" NewLinesForBracesInMethods="True" NewLinesForBracesInProperties="True" NewLinesForBracesInAccessors="True" NewLinesForBracesInAnonymousMethods="True" NewLinesForBracesInControlBlocks="True" NewLinesForBracesInAnonymousTypes="True" NewLinesForBracesInObjectCollectionArrayInitializers="True" NewLinesForBracesInLambdaExpressionBody="True" NewLineForElse="True" NewLineForCatch="True" NewLineForFinally="True" SpacingAfterMethodDeclarationName="False" SpaceWithinMethodDeclarationParenthesis="False" SpaceBetweenEmptyMethodDeclarationParentheses="False" SpaceAfterMethodCallName="False" SpaceWithinMethodCallParentheses="False" SpaceBetweenEmptyMethodCallParentheses="False" SpaceAfterControlFlowStatementKeyword="False" SpaceWithinExpressionParentheses="False" SpaceWithinCastParentheses="False" SpaceWithinOtherParentheses="False" SpaceAfterCast="False" SpacesIgnoreAroundVariableDeclaration="False" SpaceBeforeOpenSquareBracket="False" SpaceBetweenEmptySquareBrackets="False" SpaceWithinSquareBrackets="False" SpaceAfterColonInBaseTypeDeclaration="True" SpaceAfterComma="True" SpaceAfterDot="False" SpaceAfterSemicolonsInForStatement="True" SpaceBeforeColonInBaseTypeDeclaration="True" SpaceBeforeComma="False" SpaceBeforeDot="False" SpaceBeforeSemicolonsInForStatement="False" SpacingAroundBinaryOperator="Single" WrappingPreserveSingleLine="True" WrappingKeepStatementsOnSingleLine="True" PlaceSystemDirectiveFirst="True" NewLineForMembersInObjectInit="False" NewLineForMembersInAnonymousTypes="False" NewLineForClausesInQuery="False" scope="text/x-csharp" />
|
||||
<CSharpFormattingPolicy IndentBlock="True" IndentBraces="False" IndentSwitchSection="True" IndentSwitchCaseSection="True" LabelPositioning="OneLess" NewLinesForBracesInTypes="True" NewLinesForBracesInMethods="True" NewLinesForBracesInProperties="True" NewLinesForBracesInAccessors="True" NewLinesForBracesInAnonymousMethods="True" NewLinesForBracesInControlBlocks="True" NewLinesForBracesInAnonymousTypes="True" NewLinesForBracesInObjectCollectionArrayInitializers="True" NewLinesForBracesInLambdaExpressionBody="True" NewLineForElse="True" NewLineForCatch="True" NewLineForFinally="True" SpacingAfterMethodDeclarationName="False" SpaceWithinMethodDeclarationParenthesis="False" SpaceBetweenEmptyMethodDeclarationParentheses="False" SpaceAfterMethodCallName="False" SpaceWithinMethodCallParentheses="False" SpaceBetweenEmptyMethodCallParentheses="False" SpaceWithinExpressionParentheses="False" SpaceWithinCastParentheses="False" SpaceWithinOtherParentheses="False" SpaceAfterCast="False" SpacesIgnoreAroundVariableDeclaration="False" SpaceBeforeOpenSquareBracket="False" SpaceBetweenEmptySquareBrackets="False" SpaceWithinSquareBrackets="False" SpaceAfterColonInBaseTypeDeclaration="True" SpaceAfterComma="True" SpaceAfterDot="False" SpaceAfterSemicolonsInForStatement="True" SpaceBeforeColonInBaseTypeDeclaration="True" SpaceBeforeComma="False" SpaceBeforeDot="False" SpaceBeforeSemicolonsInForStatement="False" SpacingAroundBinaryOperator="Single" WrappingPreserveSingleLine="True" WrappingKeepStatementsOnSingleLine="True" PlaceSystemDirectiveFirst="True" NewLineForMembersInObjectInit="False" NewLineForMembersInAnonymousTypes="False" NewLineForClausesInQuery="False" SpaceAfterControlFlowStatementKeyword="False" scope="text/x-csharp" />
|
||||
<DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
|
||||
</Policies>
|
||||
</Properties>
|
||||
|
||||
138
DiscImageChef.Core/Logging/DumpLog.cs
Normal file
138
DiscImageChef.Core/Logging/DumpLog.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
// /***************************************************************************
|
||||
// The Disc Image Chef
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : DumpLog.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;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using DiscImageChef.Devices;
|
||||
namespace DiscImageChef.Core.Logging
|
||||
{
|
||||
public class DumpLog
|
||||
{
|
||||
readonly StreamWriter logSw;
|
||||
|
||||
public DumpLog(string outputFile, Device dev)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(outputFile))
|
||||
{
|
||||
logSw = new StreamWriter(outputFile, true);
|
||||
|
||||
logSw.WriteLine("Start logging at {0}", DateTime.Now);
|
||||
|
||||
Interop.PlatformID platId = Interop.DetectOS.GetRealPlatformID();
|
||||
string platVer = Interop.DetectOS.GetVersion();
|
||||
Type monoRunType = Type.GetType("Mono.Runtime");
|
||||
|
||||
logSw.WriteLine("################# System information #################");
|
||||
logSw.WriteLine("{0} {1} ({2}-bit)", Interop.DetectOS.GetPlatformName(platId, platVer), platVer, Environment.Is64BitOperatingSystem ? 64 : 32);
|
||||
if(monoRunType != null)
|
||||
{
|
||||
string monoVer = "unknown version";
|
||||
MethodInfo monoDisplayName = monoRunType.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
if(monoDisplayName != null)
|
||||
monoVer = (string)monoDisplayName.Invoke(null, null);
|
||||
logSw.WriteLine("Mono {0}", monoVer);
|
||||
}
|
||||
else
|
||||
logSw.WriteLine(".NET Framework {0}", Environment.Version);
|
||||
logSw.WriteLine();
|
||||
|
||||
logSw.WriteLine("################# Program information ################");
|
||||
logSw.WriteLine("DiscImageChef {0} running in {1}-bit", Version.GetVersion(), Environment.Is64BitProcess ? 64 : 32);
|
||||
#if DEBUG
|
||||
logSw.WriteLine("DEBUG version");
|
||||
#endif
|
||||
logSw.WriteLine("Command line: {0}", Environment.CommandLine);
|
||||
logSw.WriteLine();
|
||||
|
||||
logSw.WriteLine("################# Device information #################");
|
||||
logSw.WriteLine("Manufacturer: {0}", dev.Manufacturer);
|
||||
logSw.WriteLine("Model: {0}", dev.Model);
|
||||
logSw.WriteLine("Firmware revision: {0}", dev.Revision);
|
||||
logSw.WriteLine("Serial number: {0}", dev.Serial);
|
||||
logSw.WriteLine("Removable device: {0}", dev.IsRemovable);
|
||||
logSw.WriteLine("Device type: {0}", dev.Type);
|
||||
logSw.WriteLine("CompactFlash device: {0}", dev.IsCompactFlash);
|
||||
logSw.WriteLine("PCMCIA device: {0}", dev.IsPCMCIA);
|
||||
logSw.WriteLine("USB device: {0}", dev.IsUSB);
|
||||
if(dev.IsUSB)
|
||||
{
|
||||
logSw.WriteLine("USB manufacturer: {0}", dev.USBManufacturerString);
|
||||
logSw.WriteLine("USB product: {0}", dev.USBProductString);
|
||||
logSw.WriteLine("USB serial: {0}", dev.USBSerialString);
|
||||
logSw.WriteLine("USB vendor ID: {0:X4}h", dev.USBVendorID);
|
||||
logSw.WriteLine("USB product ID: {0:X4}h", dev.USBProductID);
|
||||
}
|
||||
logSw.WriteLine("FireWire device: {0}", dev.IsFireWire);
|
||||
if(dev.IsFireWire)
|
||||
{
|
||||
logSw.WriteLine("FireWire vendor: {0}", dev.FireWireVendorName);
|
||||
logSw.WriteLine("FireWire model: {0}", dev.FireWireModelName);
|
||||
logSw.WriteLine("FireWire GUID: 0x{0:X16}", dev.FireWireGUID);
|
||||
logSw.WriteLine("FireWire vendor ID: 0x{0:X8}", dev.FireWireVendor);
|
||||
logSw.WriteLine("FireWire product ID: 0x{0:X8}", dev.FireWireModel);
|
||||
}
|
||||
logSw.WriteLine();
|
||||
logSw.WriteLine("######################################################");
|
||||
|
||||
logSw.WriteLine();
|
||||
logSw.WriteLine("################ Dumping progress log ################");
|
||||
logSw.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteLine(string format, params object[] args)
|
||||
{
|
||||
if(logSw != null)
|
||||
{
|
||||
string text = string.Format(format, args);
|
||||
logSw.WriteLine("{0:s} {1}", DateTime.Now, text);
|
||||
logSw.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if(logSw != null)
|
||||
{
|
||||
logSw.WriteLine("######################################################");
|
||||
logSw.WriteLine("End logging at {0}", DateTime.Now);
|
||||
logSw.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,23 +105,27 @@ namespace DiscImageChef.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
DumpLog dumpLog = new DumpLog(options.OutputPrefix + ".log", dev);
|
||||
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
ATA.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume);
|
||||
ATA.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog);
|
||||
break;
|
||||
case DeviceType.MMC:
|
||||
case DeviceType.SecureDigital:
|
||||
SecureDigital.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume);
|
||||
SecureDigital.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog);
|
||||
break;
|
||||
case DeviceType.NVMe:
|
||||
NVMe.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume);
|
||||
NVMe.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog);
|
||||
break;
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
SCSI.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, options.SeparateSubchannel, ref resume);
|
||||
SCSI.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, options.SeparateSubchannel, ref resume, ref dumpLog);
|
||||
break;
|
||||
default:
|
||||
dumpLog.WriteLine("Unknown device type.");
|
||||
dumpLog.Close();
|
||||
throw new NotSupportedException("Unknown device type.");
|
||||
}
|
||||
|
||||
@@ -139,6 +143,8 @@ namespace DiscImageChef.Commands
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
dumpLog.Close();
|
||||
|
||||
Core.Statistics.AddCommand("dump-media");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user