using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml.Serialization; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Metadata; using DiscImageChef.Core.Logging; using DiscImageChef.Devices; using Schemas; namespace DiscImageChef.Core.Devices.Dumping { public partial class Dump { readonly Device dev; readonly string devicePath; readonly bool doResume; readonly DumpLog dumpLog; readonly bool dumpRaw; readonly Encoding encoding; readonly bool force; readonly Dictionary formatOptions; readonly bool nometadata; readonly bool notrim; readonly string outputPath; readonly IWritableImage outputPlugin; readonly string outputPrefix; readonly bool persistent; readonly CICMMetadataType preSidecar; readonly ushort retryPasses; readonly bool stopOnError; bool aborted; bool dumpFirstTrackPregap; Resume resume; Sidecar sidecarClass; uint skip; /// /// Initializes dumpers /// /// Should resume? /// Device /// Path to the device /// Prefix for output log files /// Plugin for output file /// How many times to retry /// Force to continue dump whenever possible /// Dump long sectors /// Store whatever data the drive returned on error /// Stop dump on first error /// Information for dump resuming /// Dump logger /// Encoding to use when analyzing dump /// Path to output file /// Formats to pass to output file plugin /// Do not trim errors from skipped sectors /// Try to read and dump as much first track pregap as possible /// Sidecar to store in dumped image /// How many sectors to skip reading on error /// Create metadata sidecar after dump? public Dump(bool doResume, Device dev, string devicePath, IWritableImage outputPlugin, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, Resume resume, DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, Dictionary formatOptions, CICMMetadataType preSidecar, uint skip, bool nometadata, bool notrim, bool dumpFirstTrackPregap) { this.doResume = doResume; this.dev = dev; this.devicePath = devicePath; this.outputPlugin = outputPlugin; this.retryPasses = retryPasses; this.force = force; this.dumpRaw = dumpRaw; this.persistent = persistent; this.stopOnError = stopOnError; this.resume = resume; this.dumpLog = dumpLog; this.encoding = encoding; this.outputPrefix = outputPrefix; this.outputPath = outputPath; this.formatOptions = formatOptions; this.preSidecar = preSidecar; this.skip = skip; this.nometadata = nometadata; this.notrim = notrim; this.dumpFirstTrackPregap = dumpFirstTrackPregap; aborted = false; } /// /// Starts dumping with the stablished fields and autodetecting the device type /// public void Start() { if(dev.IsUsb && dev.UsbVendorId == 0x054C && (dev.UsbProductId == 0x01C8 || dev.UsbProductId == 0x01C9 || dev.UsbProductId == 0x02D2)) PlayStationPortable(); else switch(dev.Type) { case DeviceType.ATA: Ata(); break; case DeviceType.MMC: case DeviceType.SecureDigital: SecureDigital(); break; case DeviceType.NVMe: NVMe(); break; case DeviceType.ATAPI: case DeviceType.SCSI: Scsi(); break; default: dumpLog.WriteLine("Unknown device type."); dumpLog.Close(); StoppingErrorMessage?.Invoke("Unknown device type."); return; } dumpLog.Close(); if(resume == null || !doResume) return; resume.LastWriteDate = DateTime.UtcNow; resume.BadBlocks.Sort(); if(File.Exists(outputPrefix + ".resume.xml")) File.Delete(outputPrefix + ".resume.xml"); FileStream fs = new FileStream(outputPrefix + ".resume.xml", FileMode.Create, FileAccess.ReadWrite); XmlSerializer xs = new XmlSerializer(resume.GetType()); xs.Serialize(fs, resume); fs.Close(); } public void Abort() { aborted = true; sidecarClass?.Abort(); } /// /// Event raised when the progress bar is not longer needed /// public event EndProgressHandler EndProgress; /// /// Event raised when a progress bar is needed /// public event InitProgressHandler InitProgress; /// /// Event raised to report status updates /// public event UpdateStatusHandler UpdateStatus; /// /// Event raised to report a non-fatal error /// public event ErrorMessageHandler ErrorMessage; /// /// Event raised to report a fatal error that stops the dumping operation and should call user's attention /// public event ErrorMessageHandler StoppingErrorMessage; /// /// Event raised to update the values of a determinate progress bar /// public event UpdateProgressHandler UpdateProgress; /// /// Event raised to update the status of an undeterminate progress bar /// public event PulseProgressHandler PulseProgress; /// /// Event raised when the progress bar is not longer needed /// public event EndProgressHandler2 EndProgress2; /// /// Event raised when a progress bar is needed /// public event InitProgressHandler2 InitProgress2; /// /// Event raised to update the values of a determinate progress bar /// public event UpdateProgressHandler2 UpdateProgress2; } }