Added dump log creation.

This commit is contained in:
2017-11-20 05:07:16 +00:00
parent 94fa71e217
commit 5fbf06c360
12 changed files with 581 additions and 120 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
}
}
}

View File

@@ -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.");
}

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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>

View 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();
}
}
}
}

View File

@@ -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");
}
}