diff --git a/DiscImageChef.Core/Devices/Dumping/ATA.cs b/DiscImageChef.Core/Devices/Dumping/ATA.cs index 84a56a81..cb3f8eee 100644 --- a/DiscImageChef.Core/Devices/Dumping/ATA.cs +++ b/DiscImageChef.Core/Devices/Dumping/ATA.cs @@ -78,9 +78,10 @@ namespace DiscImageChef.Core.Devices.Dumping bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Resume resume, ref - DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, + DumpLog dumpLog, Encoding encoding, string outputPrefix, + string outputPath, Dictionary - formatOptions) + formatOptions, CICMMetadataType preSidecar) { bool aborted; @@ -418,6 +419,7 @@ namespace DiscImageChef.Core.Devices.Dumping } outputPlugin.SetDumpHardware(resume.Tries); + if(preSidecar != null) outputPlugin.SetCicmMetadata(preSidecar); dumpLog.WriteLine("Closing output file."); DicConsole.WriteLine("Closing output file."); outputPlugin.Close(); @@ -436,6 +438,11 @@ namespace DiscImageChef.Core.Devices.Dumping DateTime chkStart = DateTime.UtcNow; CICMMetadataType sidecar = Sidecar.Create(inputPlugin, outputPath, filter.Id, encoding); + if(preSidecar != null) + { + preSidecar.BlockMedia = sidecar.BlockMedia; + sidecar = preSidecar; + } if(dev.IsUsb) { diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs index 1df76464..741cb2d3 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs @@ -89,7 +89,9 @@ namespace DiscImageChef.Core.Devices.Dumping Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding, string - outputPrefix, string outputPath, Dictionary formatOptions) + outputPrefix, string outputPath, Dictionary formatOptions, + CICMMetadataType + preSidecar) { uint subSize; DateTime start; @@ -887,6 +889,7 @@ namespace DiscImageChef.Core.Devices.Dumping } outputPlugin.SetDumpHardware(resume.Tries); + if(preSidecar != null) outputPlugin.SetCicmMetadata(preSidecar); dumpLog.WriteLine("Closing output file."); DicConsole.WriteLine("Closing output file."); outputPlugin.Close(); @@ -915,6 +918,12 @@ namespace DiscImageChef.Core.Devices.Dumping dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000)); + if(preSidecar == null) + { + preSidecar.OpticalDisc = sidecar.OpticalDisc; + sidecar = preSidecar; + } + sidecar.OpticalDisc[0].Dimensions = Dimensions.DimensionsFromMediaType(dskType); Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp); sidecar.OpticalDisc[0].DiscType = xmlDskTyp; diff --git a/DiscImageChef.Core/Devices/Dumping/MMC.cs b/DiscImageChef.Core/Devices/Dumping/MMC.cs index e12a5143..b07bbaeb 100644 --- a/DiscImageChef.Core/Devices/Dumping/MMC.cs +++ b/DiscImageChef.Core/Devices/Dumping/MMC.cs @@ -82,7 +82,9 @@ namespace DiscImageChef.Core.Devices.Dumping Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding, string - outputPrefix, string outputPath, Dictionary formatOptions) + outputPrefix, string outputPath, Dictionary formatOptions, + CICMMetadataType + preSidecar) { bool sense; ulong blocks; @@ -198,7 +200,7 @@ namespace DiscImageChef.Core.Devices.Dumping { CompactDisc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath, - formatOptions); + formatOptions, preSidecar); return; } @@ -599,12 +601,14 @@ namespace DiscImageChef.Core.Devices.Dumping if(isXbox) { Xgd.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags, - ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions); + ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions, + preSidecar); return; } Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags, - ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions); + ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions, + preSidecar); } internal static void AddMediaTagToSidecar(string outputPath, diff --git a/DiscImageChef.Core/Devices/Dumping/NVMe.cs b/DiscImageChef.Core/Devices/Dumping/NVMe.cs index 6e4169c9..3033124c 100644 --- a/DiscImageChef.Core/Devices/Dumping/NVMe.cs +++ b/DiscImageChef.Core/Devices/Dumping/NVMe.cs @@ -37,6 +37,7 @@ using DiscImageChef.Core.Logging; using DiscImageChef.Devices; using DiscImageChef.DiscImages; using DiscImageChef.Metadata; +using Schemas; namespace DiscImageChef.Core.Devices.Dumping { @@ -46,9 +47,10 @@ namespace DiscImageChef.Core.Devices.Dumping bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Resume resume, ref - DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, + DumpLog dumpLog, Encoding encoding, string outputPrefix, + string outputPath, Dictionary - formatOptions) + formatOptions, CICMMetadataType preSidecar) { throw new NotImplementedException("NVMe devices not yet supported."); } diff --git a/DiscImageChef.Core/Devices/Dumping/SBC.cs b/DiscImageChef.Core/Devices/Dumping/SBC.cs index b5393648..905e5b76 100644 --- a/DiscImageChef.Core/Devices/Dumping/SBC.cs +++ b/DiscImageChef.Core/Devices/Dumping/SBC.cs @@ -85,7 +85,8 @@ namespace DiscImageChef.Core.Devices.Dumping ref Resume resume, ref DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, - Dictionary formatOptions) + Dictionary formatOptions, + CICMMetadataType preSidecar) { bool sense; ulong blocks; @@ -646,6 +647,7 @@ namespace DiscImageChef.Core.Devices.Dumping } outputPlugin.SetDumpHardware(resume.Tries); + if(preSidecar != null) outputPlugin.SetCicmMetadata(preSidecar); dumpLog.WriteLine("Closing output file."); DicConsole.WriteLine("Closing output file."); outputPlugin.Close(); @@ -676,6 +678,12 @@ namespace DiscImageChef.Core.Devices.Dumping if(opticalDisc) { + if(preSidecar != null) + { + preSidecar.OpticalDisc = sidecar.OpticalDisc; + sidecar = preSidecar; + } + // TODO: Implement layers sidecar.OpticalDisc[0].Dimensions = Dimensions.DimensionsFromMediaType(dskType); Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp); @@ -689,6 +697,12 @@ namespace DiscImageChef.Core.Devices.Dumping } else { + if(preSidecar != null) + { + preSidecar.BlockMedia = sidecar.BlockMedia; + sidecar = preSidecar; + } + // All USB flash drives report as removable, even if the media is not removable if(!dev.IsRemovable || dev.IsUsb) { diff --git a/DiscImageChef.Core/Devices/Dumping/SCSI.cs b/DiscImageChef.Core/Devices/Dumping/SCSI.cs index b2b5ebe4..a69ee41c 100644 --- a/DiscImageChef.Core/Devices/Dumping/SCSI.cs +++ b/DiscImageChef.Core/Devices/Dumping/SCSI.cs @@ -40,6 +40,7 @@ using DiscImageChef.Decoders.SCSI; using DiscImageChef.Devices; using DiscImageChef.DiscImages; using DiscImageChef.Metadata; +using Schemas; using MediaType = DiscImageChef.CommonTypes.MediaType; namespace DiscImageChef.Core.Devices.Dumping @@ -76,7 +77,9 @@ namespace DiscImageChef.Core.Devices.Dumping DumpLog dumpLog, bool dumpLeadIn, Encoding encoding, string outputPrefix, string - outputPath, Dictionary formatOptions) + outputPath, Dictionary formatOptions, + CICMMetadataType + preSidecar) { MediaType dskType = MediaType.Unknown; int resets = 0; @@ -204,17 +207,17 @@ namespace DiscImageChef.Core.Devices.Dumping case PeripheralDeviceTypes.SequentialAccess: if(dumpRaw) throw new ArgumentException("Tapes cannot be dumped raw."); - Ssc.Dump(dev, outputPrefix, devicePath, ref resume, ref dumpLog); + Ssc.Dump(dev, outputPrefix, devicePath, ref resume, ref dumpLog, preSidecar); return; case PeripheralDeviceTypes.MultiMediaDevice: Mmc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath, - formatOptions); + formatOptions, preSidecar); return; default: Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, null, ref dskType, false, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, - formatOptions); + formatOptions, preSidecar); break; } } diff --git a/DiscImageChef.Core/Devices/Dumping/SSC.cs b/DiscImageChef.Core/Devices/Dumping/SSC.cs index 1dbcabfe..a237a76c 100644 --- a/DiscImageChef.Core/Devices/Dumping/SSC.cs +++ b/DiscImageChef.Core/Devices/Dumping/SSC.cs @@ -59,7 +59,8 @@ namespace DiscImageChef.Core.Devices.Dumping /// Information for dump resuming /// Dump logger internal static void Dump(Device dev, string outputPrefix, string devicePath, ref Resume resume, - ref DumpLog dumpLog) + ref DumpLog dumpLog, + CICMMetadataType preSidecar) { FixedSense? fxSense; bool aborted; @@ -74,7 +75,7 @@ namespace DiscImageChef.Core.Devices.Dumping double currentSpeed = 0; double maxSpeed = double.MinValue; double minSpeed = double.MaxValue; - CICMMetadataType sidecar = new CICMMetadataType(); + CICMMetadataType sidecar = preSidecar ?? new CICMMetadataType(); dev.RequestSense(out byte[] senseBuf, dev.Timeout, out double duration); fxSense = Sense.DecodeFixed(senseBuf, out string strSense); diff --git a/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs b/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs index 5b0dd9ec..1941d839 100644 --- a/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs +++ b/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs @@ -76,9 +76,10 @@ namespace DiscImageChef.Core.Devices.Dumping bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Resume resume, ref - DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, + DumpLog dumpLog, Encoding encoding, string outputPrefix, + string outputPath, Dictionary - formatOptions) + formatOptions, CICMMetadataType preSidecar) { bool aborted; @@ -391,6 +392,7 @@ namespace DiscImageChef.Core.Devices.Dumping currentTry.Extents = ExtentsConverter.ToMetadata(extents); outputPlugin.SetDumpHardware(resume.Tries); + if(preSidecar != null) outputPlugin.SetCicmMetadata(preSidecar); dumpLog.WriteLine("Closing output file."); DicConsole.WriteLine("Closing output file."); outputPlugin.Close(); @@ -410,6 +412,12 @@ namespace DiscImageChef.Core.Devices.Dumping DateTime chkStart = DateTime.UtcNow; CICMMetadataType sidecar = Sidecar.Create(inputPlugin, outputPath, filter.Id, encoding); + if(preSidecar != null) + { + preSidecar.BlockMedia = sidecar.BlockMedia; + sidecar = preSidecar; + } + switch(dev.Type) { case DeviceType.MMC: diff --git a/DiscImageChef.Core/Devices/Dumping/XGD.cs b/DiscImageChef.Core/Devices/Dumping/XGD.cs index 1a65890e..8c2131d5 100644 --- a/DiscImageChef.Core/Devices/Dumping/XGD.cs +++ b/DiscImageChef.Core/Devices/Dumping/XGD.cs @@ -87,7 +87,8 @@ namespace DiscImageChef.Core.Devices.Dumping ref Resume resume, ref DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, - Dictionary formatOptions) + Dictionary formatOptions, + CICMMetadataType preSidecar) { bool sense; ulong blocks; @@ -771,6 +772,7 @@ namespace DiscImageChef.Core.Devices.Dumping } outputPlugin.SetDumpHardware(resume.Tries); + if(preSidecar != null) outputPlugin.SetCicmMetadata(preSidecar); dumpLog.WriteLine("Closing output file."); DicConsole.WriteLine("Closing output file."); outputPlugin.Close(); @@ -794,6 +796,12 @@ namespace DiscImageChef.Core.Devices.Dumping CICMMetadataType sidecar = Sidecar.Create(inputPlugin, outputPath, filter.Id, encoding); end = DateTime.UtcNow; + if(preSidecar != null) + { + preSidecar.OpticalDisc = sidecar.OpticalDisc; + sidecar = preSidecar; + } + totalChkDuration = (end - chkStart).TotalMilliseconds; dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds); dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", diff --git a/DiscImageChef/Commands/DumpMedia.cs b/DiscImageChef/Commands/DumpMedia.cs index 82d330aa..2c60ccf1 100644 --- a/DiscImageChef/Commands/DumpMedia.cs +++ b/DiscImageChef/Commands/DumpMedia.cs @@ -43,6 +43,7 @@ using DiscImageChef.Core.Logging; using DiscImageChef.Devices; using DiscImageChef.DiscImages; using DiscImageChef.Metadata; +using Schemas; namespace DiscImageChef.Commands { @@ -59,21 +60,22 @@ namespace DiscImageChef.Commands Sidecar.EndProgressEvent2 += Progress.EndProgress2; Sidecar.UpdateStatusEvent += Progress.UpdateStatus; - DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", options.Debug); - DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", options.Verbose); - DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", options.DevicePath); - DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", options.Raw); - DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", options.StopOnError); - DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force); - DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", options.RetryPasses); - DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", options.Persistent); - DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", options.Resume); - DicConsole.DebugWriteLine("Dump-Media command", "--lead-in={0}", options.LeadIn); - DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", options.EncodingName); - DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", options.OutputFile); - DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", options.OutputFormat); - DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force); - DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", options.Options); + DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", options.Debug); + DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", options.Verbose); + DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", options.DevicePath); + DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", options.Raw); + DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", options.StopOnError); + DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force); + DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", options.RetryPasses); + DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", options.Persistent); + DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", options.Resume); + DicConsole.DebugWriteLine("Dump-Media command", "--lead-in={0}", options.LeadIn); + DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", options.EncodingName); + DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", options.OutputFile); + DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", options.OutputFormat); + DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force); + DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", options.Options); + DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", options.CicmXml); Dictionary parsedOptions = Options.Parse(options.Options); DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:"); @@ -132,6 +134,27 @@ namespace DiscImageChef.Commands return; } + CICMMetadataType sidecar = null; + XmlSerializer sidecarXs = new XmlSerializer(typeof(CICMMetadataType)); + if(options.CicmXml != null) + if(File.Exists(options.CicmXml)) + try + { + StreamReader sr = new StreamReader(options.CicmXml); + sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr); + sr.Close(); + } + catch + { + DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing..."); + return; + } + else + { + DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing..."); + return; + } + PluginBase plugins = new PluginBase(); List candidates = new List(); @@ -182,24 +205,24 @@ namespace DiscImageChef.Commands case DeviceType.ATA: Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix, - options.OutputFile, parsedOptions); + options.OutputFile, parsedOptions, sidecar); break; case DeviceType.MMC: case DeviceType.SecureDigital: SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, - encoding, outputPrefix, options.OutputFile, parsedOptions); + encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar); break; case DeviceType.NVMe: NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix, - options.OutputFile, parsedOptions); + options.OutputFile, parsedOptions, sidecar); break; case DeviceType.ATAPI: case DeviceType.SCSI: Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog, options.LeadIn, - encoding, outputPrefix, options.OutputFile, parsedOptions); + encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar); break; default: dumpLog.WriteLine("Unknown device type."); diff --git a/DiscImageChef/Options.cs b/DiscImageChef/Options.cs index 400cd59a..6d63f49f 100644 --- a/DiscImageChef/Options.cs +++ b/DiscImageChef/Options.cs @@ -305,6 +305,9 @@ namespace DiscImageChef [Option('O', "options", Default = null, HelpText = "Comma separated name=value pairs of options to pass to output image plugin")] public string Options { get; set; } + + [Option('x', "cicm-xml", Default = null, HelpText = "Take metadata from existing CICM XML sidecar.")] + public string CicmXml { get; set; } } [Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")]