From 758d4dd3643c5368b6e349aaacd4956cebf1989c Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 2 Jan 2020 04:09:39 +0000 Subject: [PATCH] Replace Mono.Options with System.CommandLine --- DiscImageChef.sln.DotSettings | 38 ++ DiscImageChef/Commands/Analyze.cs | 225 +++++----- DiscImageChef/Commands/Benchmark.cs | 75 ++-- DiscImageChef/Commands/Checksum.cs | 333 +++++++++----- DiscImageChef/Commands/Compare.cs | 194 ++++---- DiscImageChef/Commands/Configure.cs | 127 +++--- DiscImageChef/Commands/ConvertImage.cs | 534 ++++++++++++++--------- DiscImageChef/Commands/CreateSidecar.cs | 181 ++++---- DiscImageChef/Commands/Decode.cs | 265 ++++++----- DiscImageChef/Commands/DeviceInfo.cs | 74 ++-- DiscImageChef/Commands/DeviceReport.cs | 72 +-- DiscImageChef/Commands/DumpMedia.cs | 319 +++++++------- DiscImageChef/Commands/Entropy.cs | 125 +++--- DiscImageChef/Commands/ExtractFiles.cs | 335 ++++++++------ DiscImageChef/Commands/Formats.cs | 124 +++--- DiscImageChef/Commands/ImageInfo.cs | 84 ++-- DiscImageChef/Commands/ListDevices.cs | 55 +-- DiscImageChef/Commands/ListEncodings.cs | 72 +-- DiscImageChef/Commands/ListNamespaces.cs | 59 +-- DiscImageChef/Commands/ListOptions.cs | 94 ++-- DiscImageChef/Commands/Ls.cs | 272 +++++++----- DiscImageChef/Commands/MediaInfo.cs | 66 +-- DiscImageChef/Commands/MediaScan.cs | 89 ++-- DiscImageChef/Commands/PrintHex.cs | 142 +++--- DiscImageChef/Commands/Remote.cs | 59 +-- DiscImageChef/Commands/Statistics.cs | 127 +++--- DiscImageChef/Commands/Update.cs | 54 +-- DiscImageChef/Commands/Verify.cs | 176 ++++---- DiscImageChef/DiscImageChef.csproj | 2 +- DiscImageChef/Main.cs | 164 ++++--- 30 files changed, 2389 insertions(+), 2147 deletions(-) diff --git a/DiscImageChef.sln.DotSettings b/DiscImageChef.sln.DotSettings index bb467e150..804f6acf2 100644 --- a/DiscImageChef.sln.DotSettings +++ b/DiscImageChef.sln.DotSettings @@ -186,8 +186,11 @@ True True True + True True + True True + True True True True @@ -196,20 +199,39 @@ True True True + True True + True + True + True + True True + True + True + True + True True True True True + True + True + True + True True + True + True + True + True True True True True + True True True True + True True True True @@ -219,18 +241,34 @@ True True True + True True True + True True + True + True + True True + True + True True True + True + True True + True + True True True True True True + True + True + True True + True + True True True \ No newline at end of file diff --git a/DiscImageChef/Commands/Analyze.cs b/DiscImageChef/Commands/Analyze.cs index 64657e81d..50494d1c8 100644 --- a/DiscImageChef/Commands/Analyze.cs +++ b/DiscImageChef/Commands/Analyze.cs @@ -32,104 +32,103 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.Text; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class AnalyzeCommand : Command + internal class AnalyzeCommand : Command { - string encodingName; - string inputFile; - bool searchForFilesystems = true; - bool searchForPartitions = true; - bool showHelp; - public AnalyzeCommand() : base("analyze", "Analyzes a disc image and searches for partitions and/or filesystems.") { - Options = new OptionSet + Add(new Option(new[] + { + "--encoding", "-e" + }, "Name of character encoding to use.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] + { + "--filesystems", "-f" + }, "Searches and analyzes filesystems.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--partitions", "-p" + }, "Searches and interprets partitions.") + { + Argument = new Argument(() => true), Required = false + }); + + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] imagefile", - "", - Help, - {"encoding|e=", "Name of character encoding to use.", s => encodingName = s}, - {"filesystems|f", "Searches and analyzes filesystems.", b => searchForFilesystems = b != null}, - {"partitions|p", "Searches and interprets partitions.", b => searchForPartitions = b != null}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "Disc image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + int Invoke(bool verbose, bool debug, string encoding, bool filesystems, bool partitions, string imagePath) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("analyze"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + DicConsole.DebugWriteLine("Analyze command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Analyze command", "--encoding={0}", encoding); + DicConsole.DebugWriteLine("Analyze command", "--filesystems={0}", filesystems); + DicConsole.DebugWriteLine("Analyze command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Analyze command", "--partitions={0}", partitions); + DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose); - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - - DicConsole.DebugWriteLine("Analyze command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Analyze command", "--encoding={0}", encodingName); - DicConsole.DebugWriteLine("Analyze command", "--filesystems={0}", searchForFilesystems); - DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Analyze command", "--partitions={0}", searchForPartitions); - DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose); - - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } - Encoding encoding = null; + Encoding encodingClass = null; - if(encodingName != null) + if(encoding != null) try { - encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); + encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding); + + if(verbose) + DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName); } catch(ArgumentException) { DicConsole.ErrorWriteLine("Specified encoding is not supported."); - return (int)ErrorNumber.EncodingUnknown; + + return(int)ErrorNumber.EncodingUnknown; } PluginBase plugins = GetPluginBase.Instance; - bool checkraw = false; + bool checkRaw = false; try { @@ -138,13 +137,16 @@ namespace DiscImageChef.Commands if(imageFormat == null) { DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); - else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); + else + DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); + DicConsole.WriteLine(); try @@ -153,10 +155,11 @@ namespace DiscImageChef.Commands { DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("No error given"); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } - if(MainClass.Verbose) + if(verbose) { ImageInfo.PrintImageInfo(imageFormat); DicConsole.WriteLine(); @@ -171,52 +174,62 @@ namespace DiscImageChef.Commands DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Error: {0}", ex.Message); DicConsole.DebugWriteLine("Analyze command", "Stack trace: {0}", ex.StackTrace); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } List idPlugins; IFilesystem plugin; string information; - if(searchForPartitions) - { - List partitions = Core.Partitions.GetAll(imageFormat); - Core.Partitions.AddSchemesToStats(partitions); - if(partitions.Count == 0) + if(partitions) + { + List partitionsList = Core.Partitions.GetAll(imageFormat); + Core.Partitions.AddSchemesToStats(partitionsList); + + if(partitionsList.Count == 0) { DicConsole.DebugWriteLine("Analyze command", "No partitions found"); - if(!searchForFilesystems) + + if(!filesystems) { DicConsole.WriteLine("No partitions founds, not searching for filesystems"); - return (int)ErrorNumber.NothingFound; + + return(int)ErrorNumber.NothingFound; } - checkraw = true; + checkRaw = true; } else { - DicConsole.WriteLine("{0} partitions found.", partitions.Count); + DicConsole.WriteLine("{0} partitions found.", partitionsList.Count); - for(int i = 0; i < partitions.Count; i++) + for(int i = 0; i < partitionsList.Count; i++) { DicConsole.WriteLine(); - DicConsole.WriteLine("Partition {0}:", partitions[i].Sequence); - DicConsole.WriteLine("Partition name: {0}", partitions[i].Name); - DicConsole.WriteLine("Partition type: {0}", partitions[i].Type); - DicConsole.WriteLine("Partition start: sector {0}, byte {1}", partitions[i].Start, - partitions[i].Offset); - DicConsole.WriteLine("Partition length: {0} sectors, {1} bytes", partitions[i].Length, - partitions[i].Size); - DicConsole.WriteLine("Partition scheme: {0}", partitions[i].Scheme); - DicConsole.WriteLine("Partition description:"); - DicConsole.WriteLine(partitions[i].Description); + DicConsole.WriteLine("Partition {0}:", partitionsList[i].Sequence); + DicConsole.WriteLine("Partition name: {0}", partitionsList[i].Name); + DicConsole.WriteLine("Partition type: {0}", partitionsList[i].Type); - if(!searchForFilesystems) continue; + DicConsole.WriteLine("Partition start: sector {0}, byte {1}", partitionsList[i].Start, + partitionsList[i].Offset); + + DicConsole.WriteLine("Partition length: {0} sectors, {1} bytes", partitionsList[i].Length, + partitionsList[i].Size); + + DicConsole.WriteLine("Partition scheme: {0}", partitionsList[i].Scheme); + DicConsole.WriteLine("Partition description:"); + DicConsole.WriteLine(partitionsList[i].Description); + + if(!filesystems) + continue; DicConsole.WriteLine("Identifying filesystem on partition"); - Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]); - if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified"); + Core.Filesystems.Identify(imageFormat, out idPlugins, partitionsList[i]); + + if(idPlugins.Count == 0) + DicConsole.WriteLine("Filesystem not identified"); else if(idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); @@ -225,7 +238,10 @@ namespace DiscImageChef.Commands if(plugins.PluginsList.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - plugin.GetInformation(imageFormat, partitions[i], out information, encoding); + + plugin.GetInformation(imageFormat, partitionsList[i], out information, + encodingClass); + DicConsole.Write(information); Statistics.AddFilesystem(plugin.XmlFsType.Type); } @@ -233,10 +249,12 @@ namespace DiscImageChef.Commands else { plugins.PluginsList.TryGetValue(idPlugins[0], out plugin); - if(plugin == null) continue; + + if(plugin == null) + continue; DicConsole.WriteLine($"Identified by {plugin.Name}."); - plugin.GetInformation(imageFormat, partitions[i], out information, encoding); + plugin.GetInformation(imageFormat, partitionsList[i], out information, encodingClass); DicConsole.Write("{0}", information); Statistics.AddFilesystem(plugin.XmlFsType.Type); } @@ -244,17 +262,18 @@ namespace DiscImageChef.Commands } } - if(checkraw) + if(checkRaw) { - Partition wholePart = new Partition + var wholePart = new Partition { - Name = "Whole device", - Length = imageFormat.Info.Sectors, - Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize + Name = "Whole device", Length = imageFormat.Info.Sectors, + Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); - if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified"); + + if(idPlugins.Count == 0) + DicConsole.WriteLine("Filesystem not identified"); else if(idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); @@ -263,7 +282,7 @@ namespace DiscImageChef.Commands if(plugins.PluginsList.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - plugin.GetInformation(imageFormat, wholePart, out information, encoding); + plugin.GetInformation(imageFormat, wholePart, out information, encodingClass); DicConsole.Write(information); Statistics.AddFilesystem(plugin.XmlFsType.Type); } @@ -271,10 +290,11 @@ namespace DiscImageChef.Commands else { plugins.PluginsList.TryGetValue(idPlugins[0], out plugin); + if(plugin != null) { DicConsole.WriteLine($"Identified by {plugin.Name}."); - plugin.GetInformation(imageFormat, wholePart, out information, encoding); + plugin.GetInformation(imageFormat, wholePart, out information, encodingClass); DicConsole.Write(information); Statistics.AddFilesystem(plugin.XmlFsType.Type); } @@ -285,10 +305,11 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}"); DicConsole.DebugWriteLine("Analyze command", ex.StackTrace); - return (int)ErrorNumber.UnexpectedException; + + return(int)ErrorNumber.UnexpectedException; } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/Benchmark.cs b/DiscImageChef/Commands/Benchmark.cs index 5555ec69e..15a6c661c 100644 --- a/DiscImageChef/Commands/Benchmark.cs +++ b/DiscImageChef/Commands/Benchmark.cs @@ -31,58 +31,56 @@ // ****************************************************************************/ using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class BenchmarkCommand : Command + internal class BenchmarkCommand : Command { - int blockSize = 512; - int bufferSize = 128; - bool showHelp; - public BenchmarkCommand() : base("benchmark", "Benchmarks hashing and entropy calculation.") { - Options = new OptionSet + Add(new Option(new[] + { + "--block-size", "-b" + }, "Block size.") + { + Argument = new Argument(() => 512), Required = false + }); + + Add(new Option(new[] + { + "--buffer-size", "-s" + }, "Buffer size in mebibytes.") + { + Argument = new Argument(() => 128), Required = false + }); + + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS]", - "", - Help, - {"block-size|b=", "Block size.", (int i) => blockSize = i}, - {"buffer-size|s=", "Buffer size in mebibytes.", (int i) => bufferSize = i}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "Disc image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, int blockSize, int bufferSize) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("benchmark"); - if(extra.Count != 0) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } - - DicConsole.DebugWriteLine("Benchmark command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Benchmark command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Benchmark command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Benchmark command", "--verbose={0}", verbose); Benchmark.InitProgressEvent += Progress.InitProgress; Benchmark.UpdateProgressEvent += Progress.UpdateProgress; @@ -92,8 +90,10 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Took {0} seconds to fill buffer, {1:F3} MiB/sec.", results.FillTime, results.FillSpeed); + DicConsole.WriteLine("Took {0} seconds to read buffer, {1:F3} MiB/sec.", results.ReadTime, results.ReadSpeed); + DicConsole.WriteLine("Took {0} seconds to entropy buffer, {1:F3} MiB/sec.", results.EntropyTime, results.EntropySpeed); @@ -103,6 +103,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Took {0} seconds to do all algorithms at the same time, {1:F3} MiB/sec.", results.TotalTime, results.TotalSpeed); + DicConsole.WriteLine("Took {0} seconds to do all algorithms sequentially, {1:F3} MiB/sec.", results.SeparateTime, results.SeparateSpeed); @@ -110,7 +111,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Max memory used is {0} bytes", results.MaxMemory); DicConsole.WriteLine("Min memory used is {0} bytes", results.MinMemory); - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/Checksum.cs b/DiscImageChef/Commands/Checksum.cs index 9563e3c93..6724195ad 100644 --- a/DiscImageChef/Commands/Checksum.cs +++ b/DiscImageChef/Commands/Checksum.cs @@ -32,121 +32,167 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; using Schemas; namespace DiscImageChef.Commands { - class ChecksumCommand : Command + internal class ChecksumCommand : Command { // How many sectors to read at once const uint SECTORS_TO_READ = 256; - bool doAdler32 = true; - bool doCrc16 = true; - bool doCrc32 = true; - bool doCrc64; - bool doFletcher16; - bool doFletcher32; - bool doMd5 = true; - bool doSha1 = true; - bool doSha256; - bool doSha384; - bool doSha512; - bool doSpamSum = true; - string inputFile; - bool separatedTracks = true; - bool showHelp; - bool wholeDisc = true; - public ChecksumCommand() : base("checksum", "Checksums an image.") { - Options = new OptionSet + Add(new Option(new[] + { + "--adler32", "-a" + }, "Calculates Adler32.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option("--crc16", "Calculates CRC16.") { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] imagefile", - "", - Help, - {"adler32|a", "Calculates Adler-32.", b => doAdler32 = b != null}, - {"crc16", "Calculates CRC16.", b => doCrc16 = b != null}, - {"crc32|c", "Calculates CRC32.", b => doCrc32 = b != null}, - {"crc64", "Calculates CRC64 (ECMA).", b => doCrc64 = b != null}, - {"fletcher16", "Calculates Fletcher-16.", b => doFletcher16 = b != null}, - {"fletcher32", "Calculates Fletcher-32.", b => doFletcher32 = b != null}, - {"md5|m", "Calculates MD5.", b => doMd5 = b != null}, - {"separated-tracks|t", "Checksums each track separately.", b => separatedTracks = b != null}, - {"sha1|s", "Calculates SHA1.", b => doSha1 = b != null}, - {"sha256", "Calculates SHA256.", b => doSha256 = b != null}, - {"sha384", "Calculates SHA384.", b => doSha384 = b != null}, - {"sha512", "Calculates SHA512.", b => doSha512 = b != null}, - {"spamsum|f", "Calculates SpamSum fuzzy hash.", b => doSpamSum = b != null}, - {"whole-disc|w", "Checksums the whole disc.", b => wholeDisc = b != null}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--crc32", "-c" + }, "Calculates CRC32.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option("--crc64", "Calculates CRC64.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option("--fletcher16", "Calculates Fletcher-16.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option("--fletcher32", "Calculates Fletcher-32.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--md5", "-m" + }, "Calculates MD5.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--separated-tracks", "-t" + }, "Checksums each track separately.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--sha1", "-s" + }, "Calculates SHA1.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--sha256", "-a" + }, "Calculates SHA256.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option("--sha384", "Calculates SHA384.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option("--sha512", "Calculates SHA512.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--spamsum", "-f" + }, "Calculates SpamSum fuzzy hash.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--whole-disc", "-w" + }, "Checksums the whole disc.") + { + Argument = new Argument(() => true), Required = false + }); + + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, bool adler32, bool crc16, bool crc32, bool crc64, bool fletcher16, + bool fletcher32, bool md5, bool sha1, bool sha256, bool sha384, bool sha512, bool spamSum, + string imagePath, bool separatedTracks, bool wholeDisc) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("checksum"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - - DicConsole.DebugWriteLine("Checksum command", "--adler32={0}", doAdler32); - DicConsole.DebugWriteLine("Checksum command", "--crc16={0}", doCrc16); - DicConsole.DebugWriteLine("Checksum command", "--crc32={0}", doCrc32); - DicConsole.DebugWriteLine("Checksum command", "--crc64={0}", doCrc64); - DicConsole.DebugWriteLine("Checksum command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Checksum command", "--fletcher16={0}", doFletcher16); - DicConsole.DebugWriteLine("Checksum command", "--fletcher32={0}", doFletcher32); - DicConsole.DebugWriteLine("Checksum command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Checksum command", "--md5={0}", doMd5); + DicConsole.DebugWriteLine("Checksum command", "--adler32={0}", adler32); + DicConsole.DebugWriteLine("Checksum command", "--crc16={0}", crc16); + DicConsole.DebugWriteLine("Checksum command", "--crc32={0}", crc32); + DicConsole.DebugWriteLine("Checksum command", "--crc64={0}", crc64); + DicConsole.DebugWriteLine("Checksum command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Checksum command", "--fletcher16={0}", fletcher16); + DicConsole.DebugWriteLine("Checksum command", "--fletcher32={0}", fletcher32); + DicConsole.DebugWriteLine("Checksum command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Checksum command", "--md5={0}", md5); DicConsole.DebugWriteLine("Checksum command", "--separated-tracks={0}", separatedTracks); - DicConsole.DebugWriteLine("Checksum command", "--sha1={0}", doSha1); - DicConsole.DebugWriteLine("Checksum command", "--sha256={0}", doSha256); - DicConsole.DebugWriteLine("Checksum command", "--sha384={0}", doSha384); - DicConsole.DebugWriteLine("Checksum command", "--sha512={0}", doSha512); - DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", doSpamSum); - DicConsole.DebugWriteLine("Checksum command", "--verbose={0}", MainClass.Verbose); - DicConsole.DebugWriteLine("Checksum command", "--whole-disc={0}", wholeDisc); + DicConsole.DebugWriteLine("Checksum command", "--sha1={0}", sha1); + DicConsole.DebugWriteLine("Checksum command", "--sha256={0}", sha256); + DicConsole.DebugWriteLine("Checksum command", "--sha384={0}", sha384); + DicConsole.DebugWriteLine("Checksum command", "--sha512={0}", sha512); + DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", spamSum); + DicConsole.DebugWriteLine("Checksum command", "--verbose={0}", verbose); + DicConsole.DebugWriteLine("Checksum command", "--whole-disc={0}", wholeDisc); - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } IMediaImage inputFormat = ImageFormat.Detect(inputFilter); @@ -154,27 +200,51 @@ namespace DiscImageChef.Commands if(inputFormat == null) { DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming"); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } inputFormat.Open(inputFilter); Statistics.AddMediaFormat(inputFormat.Format); Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddFilter(inputFilter.Name); - EnableChecksum enabledChecksums = new EnableChecksum(); + var enabledChecksums = new EnableChecksum(); - if(doAdler32) enabledChecksums |= EnableChecksum.Adler32; - if(doCrc16) enabledChecksums |= EnableChecksum.Crc16; - if(doCrc32) enabledChecksums |= EnableChecksum.Crc32; - if(doCrc64) enabledChecksums |= EnableChecksum.Crc64; - if(doMd5) enabledChecksums |= EnableChecksum.Md5; - if(doSha1) enabledChecksums |= EnableChecksum.Sha1; - if(doSha256) enabledChecksums |= EnableChecksum.Sha256; - if(doSha384) enabledChecksums |= EnableChecksum.Sha384; - if(doSha512) enabledChecksums |= EnableChecksum.Sha512; - if(doSpamSum) enabledChecksums |= EnableChecksum.SpamSum; - if(doFletcher16) enabledChecksums |= EnableChecksum.Fletcher16; - if(doFletcher32) enabledChecksums |= EnableChecksum.Fletcher32; + if(adler32) + enabledChecksums |= EnableChecksum.Adler32; + + if(crc16) + enabledChecksums |= EnableChecksum.Crc16; + + if(crc32) + enabledChecksums |= EnableChecksum.Crc32; + + if(crc64) + enabledChecksums |= EnableChecksum.Crc64; + + if(md5) + enabledChecksums |= EnableChecksum.Md5; + + if(sha1) + enabledChecksums |= EnableChecksum.Sha1; + + if(sha256) + enabledChecksums |= EnableChecksum.Sha256; + + if(sha384) + enabledChecksums |= EnableChecksum.Sha384; + + if(sha512) + enabledChecksums |= EnableChecksum.Sha512; + + if(spamSum) + enabledChecksums |= EnableChecksum.SpamSum; + + if(fletcher16) + enabledChecksums |= EnableChecksum.Fletcher16; + + if(fletcher32) + enabledChecksums |= EnableChecksum.Fletcher32; Checksum mediaChecksum = null; @@ -185,11 +255,13 @@ namespace DiscImageChef.Commands { Checksum trackChecksum = null; - if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums); + if(wholeDisc) + mediaChecksum = new Checksum(enabledChecksums); ulong previousTrackEnd = 0; List inputTracks = opticalInput.Tracks; + foreach(Track currentTrack in inputTracks) { if(currentTrack.TrackStartSector - previousTrackEnd != 0 && wholeDisc) @@ -207,9 +279,10 @@ namespace DiscImageChef.Commands currentTrack.TrackSequence, currentTrack.TrackStartSector, currentTrack.TrackEndSector); - if(separatedTracks) trackChecksum = new Checksum(enabledChecksums); + if(separatedTracks) + trackChecksum = new Checksum(enabledChecksums); - ulong sectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector + 1; + ulong sectors = (currentTrack.TrackEndSector - currentTrack.TrackStartSector) + 1; ulong doneSectors = 0; DicConsole.WriteLine("Track {0} has {1} sectors", currentTrack.TrackSequence, sectors); @@ -221,22 +294,28 @@ namespace DiscImageChef.Commands { sector = opticalInput.ReadSectors(doneSectors, SECTORS_TO_READ, currentTrack.TrackSequence); - DicConsole.Write("\rHashings sectors {0} to {2} of track {1}", doneSectors, + + DicConsole.Write("\rHashing sectors {0} to {2} of track {1}", doneSectors, currentTrack.TrackSequence, doneSectors + SECTORS_TO_READ); + doneSectors += SECTORS_TO_READ; } else { sector = opticalInput.ReadSectors(doneSectors, (uint)(sectors - doneSectors), currentTrack.TrackSequence); - DicConsole.Write("\rHashings sectors {0} to {2} of track {1}", doneSectors, + + DicConsole.Write("\rHashing sectors {0} to {2} of track {1}", doneSectors, currentTrack.TrackSequence, doneSectors + (sectors - doneSectors)); + doneSectors += sectors - doneSectors; } - if(wholeDisc) mediaChecksum?.Update(sector); + if(wholeDisc) + mediaChecksum?.Update(sector); - if(separatedTracks) trackChecksum?.Update(sector); + if(separatedTracks) + trackChecksum?.Update(sector); } DicConsole.WriteLine(); @@ -266,8 +345,10 @@ namespace DiscImageChef.Commands } catch(Exception ex) { - if(MainClass.Debug) DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message); - else DicConsole.WriteLine("Unable to get separate tracks, not checksumming them"); + if(debug) + DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message); + else + DicConsole.WriteLine("Unable to get separate tracks, not checksumming them"); } break; @@ -276,7 +357,8 @@ namespace DiscImageChef.Commands { Checksum trackChecksum = null; - if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums); + if(wholeDisc) + mediaChecksum = new Checksum(enabledChecksums); ulong previousTrackEnd = 0; @@ -296,9 +378,10 @@ namespace DiscImageChef.Commands "Track {0} starts at sector {1} and ends at block {2}", currentFile.File, currentFile.FirstBlock, currentFile.LastBlock); - if(separatedTracks) trackChecksum = new Checksum(enabledChecksums); + if(separatedTracks) + trackChecksum = new Checksum(enabledChecksums); - ulong sectors = currentFile.LastBlock - currentFile.FirstBlock + 1; + ulong sectors = (currentFile.LastBlock - currentFile.FirstBlock) + 1; ulong doneSectors = 0; DicConsole.WriteLine("File {0} has {1} sectors", currentFile.File, sectors); @@ -309,22 +392,28 @@ namespace DiscImageChef.Commands if(sectors - doneSectors >= SECTORS_TO_READ) { sector = tapeImage.ReadSectors(doneSectors + currentFile.FirstBlock, SECTORS_TO_READ); - DicConsole.Write("\rHashings blocks {0} to {2} of file {1}", doneSectors, + + DicConsole.Write("\rHashing blocks {0} to {2} of file {1}", doneSectors, currentFile.File, doneSectors + SECTORS_TO_READ); + doneSectors += SECTORS_TO_READ; } else { sector = tapeImage.ReadSectors(doneSectors + currentFile.FirstBlock, (uint)(sectors - doneSectors)); - DicConsole.Write("\rHashings blocks {0} to {2} of file {1}", doneSectors, + + DicConsole.Write("\rHashing blocks {0} to {2} of file {1}", doneSectors, currentFile.File, doneSectors + (sectors - doneSectors)); + doneSectors += sectors - doneSectors; } - if(wholeDisc) mediaChecksum?.Update(sector); + if(wholeDisc) + mediaChecksum?.Update(sector); - if(separatedTracks) trackChecksum?.Update(sector); + if(separatedTracks) + trackChecksum?.Update(sector); } DicConsole.WriteLine(); @@ -350,6 +439,7 @@ namespace DiscImageChef.Commands if(mediaChecksum != null) foreach(ChecksumType chk in mediaChecksum.End()) DicConsole.WriteLine("Tape's {0}: {1}", chk.type, chk.Value); + break; } @@ -368,15 +458,19 @@ namespace DiscImageChef.Commands if(sectors - doneSectors >= SECTORS_TO_READ) { sector = inputFormat.ReadSectors(doneSectors, SECTORS_TO_READ); - DicConsole.Write("\rHashings sectors {0} to {1}", doneSectors, + + DicConsole.Write("\rHashing sectors {0} to {1}", doneSectors, doneSectors + SECTORS_TO_READ); + doneSectors += SECTORS_TO_READ; } else { sector = inputFormat.ReadSectors(doneSectors, (uint)(sectors - doneSectors)); - DicConsole.Write("\rHashings sectors {0} to {1}", doneSectors, + + DicConsole.Write("\rHashing sectors {0} to {1}", doneSectors, doneSectors + (sectors - doneSectors)); + doneSectors += sectors - doneSectors; } @@ -387,11 +481,12 @@ namespace DiscImageChef.Commands foreach(ChecksumType chk in mediaChecksum.End()) DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value); + break; } } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/Compare.cs b/DiscImageChef/Commands/Compare.cs index 6754ea98d..16a76b93c 100644 --- a/DiscImageChef/Commands/Compare.cs +++ b/DiscImageChef/Commands/Compare.cs @@ -32,6 +32,8 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.Text; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; @@ -39,81 +41,61 @@ using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; using ImageInfo = DiscImageChef.CommonTypes.Structs.ImageInfo; namespace DiscImageChef.Commands { - class CompareCommand : Command + internal class CompareCommand : Command { - string inputFile1; - string inputFile2; - bool showHelp; - public CompareCommand() : base("compare", "Compares two disc images.") { - Options = new OptionSet + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} imagefile1 imagefile2", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "First media image path", Name = "image-path1" + }); + + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Second media image path", Name = "image-path2" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, string imagePath1, string imagePath2) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("compare"); - if(extra.Count > 2) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + DicConsole.DebugWriteLine("Compare command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Compare command", "--input1={0}", imagePath1); + DicConsole.DebugWriteLine("Compare command", "--input2={0}", imagePath2); + DicConsole.DebugWriteLine("Compare command", "--verbose={0}", verbose); - if(extra.Count <= 1) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile1 = extra[0]; - inputFile2 = extra[1]; - - DicConsole.DebugWriteLine("Compare command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Compare command", "--input1={0}", inputFile1); - DicConsole.DebugWriteLine("Compare command", "--input2={0}", inputFile2); - DicConsole.DebugWriteLine("Compare command", "--verbose={0}", MainClass.Verbose); - - FiltersList filtersList = new FiltersList(); - IFilter inputFilter1 = filtersList.GetFilter(inputFile1); + var filtersList = new FiltersList(); + IFilter inputFilter1 = filtersList.GetFilter(imagePath1); filtersList = new FiltersList(); - IFilter inputFilter2 = filtersList.GetFilter(inputFile2); + IFilter inputFilter2 = filtersList.GetFilter(imagePath2); if(inputFilter1 == null) { DicConsole.ErrorWriteLine("Cannot open input file 1"); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } if(inputFilter2 == null) { DicConsole.ErrorWriteLine("Cannot open input file 2"); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } IMediaImage input1Format = ImageFormat.Detect(inputFilter1); @@ -122,24 +104,28 @@ namespace DiscImageChef.Commands if(input1Format == null) { DicConsole.ErrorWriteLine("Input file 1 format not identified, not proceeding with comparison."); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("Input file 1 format identified by {0} ({1}).", input1Format.Name, input1Format.Id); - else DicConsole.WriteLine("Input file 1 format identified by {0}.", input1Format.Name); + else + DicConsole.WriteLine("Input file 1 format identified by {0}.", input1Format.Name); if(input2Format == null) { DicConsole.ErrorWriteLine("Input file 2 format not identified, not proceeding with comparison."); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("Input file 2 format identified by {0} ({1}).", input2Format.Name, input2Format.Id); - else DicConsole.WriteLine("Input file 2 format identified by {0}.", input2Format.Name); + else + DicConsole.WriteLine("Input file 2 format identified by {0}.", input2Format.Name); input1Format.Open(inputFilter1); input2Format.Open(inputFilter2); @@ -151,19 +137,19 @@ namespace DiscImageChef.Commands Statistics.AddFilter(inputFilter1.Name); Statistics.AddFilter(inputFilter2.Name); - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - if(MainClass.Verbose) + if(verbose) { sb.AppendLine("\tDisc image 1\tDisc image 2"); sb.AppendLine("================================"); - sb.AppendFormat("File\t{0}\t{1}", inputFile1, inputFile2).AppendLine(); + sb.AppendFormat("File\t{0}\t{1}", imagePath1, imagePath2).AppendLine(); sb.AppendFormat("Disc image format\t{0}\t{1}", input1Format.Name, input2Format.Name).AppendLine(); } else { - sb.AppendFormat("Disc image 1: {0}", inputFile1).AppendLine(); - sb.AppendFormat("Disc image 2: {0}", inputFile2).AppendLine(); + sb.AppendFormat("Disc image 1: {0}", imagePath1).AppendLine(); + sb.AppendFormat("Disc image 2: {0}", imagePath2).AppendLine(); } bool imagesDiffer = false; @@ -205,47 +191,66 @@ namespace DiscImageChef.Commands #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body } - if(MainClass.Verbose) + if(verbose) { - sb.AppendFormat("Has partitions?\t{0}\t{1}", image1Info.HasPartitions, image2Info.HasPartitions) - .AppendLine(); + sb.AppendFormat("Has partitions?\t{0}\t{1}", image1Info.HasPartitions, image2Info.HasPartitions). + AppendLine(); + sb.AppendFormat("Has sessions?\t{0}\t{1}", image1Info.HasSessions, image2Info.HasSessions).AppendLine(); sb.AppendFormat("Image size\t{0}\t{1}", image1Info.ImageSize, image2Info.ImageSize).AppendLine(); sb.AppendFormat("Sectors\t{0}\t{1}", image1Info.Sectors, image2Info.Sectors).AppendLine(); sb.AppendFormat("Sector size\t{0}\t{1}", image1Info.SectorSize, image2Info.SectorSize).AppendLine(); - sb.AppendFormat("Creation time\t{0}\t{1}", image1Info.CreationTime, image2Info.CreationTime) - .AppendLine(); + + sb.AppendFormat("Creation time\t{0}\t{1}", image1Info.CreationTime, image2Info.CreationTime). + AppendLine(); + sb.AppendFormat("Last modification time\t{0}\t{1}", image1Info.LastModificationTime, image2Info.LastModificationTime).AppendLine(); + sb.AppendFormat("Disk type\t{0}\t{1}", image1Info.MediaType, image2Info.MediaType).AppendLine(); sb.AppendFormat("Image version\t{0}\t{1}", image1Info.Version, image2Info.Version).AppendLine(); - sb.AppendFormat("Image application\t{0}\t{1}", image1Info.Application, image2Info.Application) - .AppendLine(); + + sb.AppendFormat("Image application\t{0}\t{1}", image1Info.Application, image2Info.Application). + AppendLine(); + sb.AppendFormat("Image application version\t{0}\t{1}", image1Info.ApplicationVersion, image2Info.ApplicationVersion).AppendLine(); + sb.AppendFormat("Image creator\t{0}\t{1}", image1Info.Creator, image2Info.Creator).AppendLine(); sb.AppendFormat("Image name\t{0}\t{1}", image1Info.MediaTitle, image2Info.MediaTitle).AppendLine(); sb.AppendFormat("Image comments\t{0}\t{1}", image1Info.Comments, image2Info.Comments).AppendLine(); + sb.AppendFormat("Disk manufacturer\t{0}\t{1}", image1Info.MediaManufacturer, image2Info.MediaManufacturer).AppendLine(); + sb.AppendFormat("Disk model\t{0}\t{1}", image1Info.MediaModel, image2Info.MediaModel).AppendLine(); + sb.AppendFormat("Disk serial number\t{0}\t{1}", image1Info.MediaSerialNumber, image2Info.MediaSerialNumber).AppendLine(); - sb.AppendFormat("Disk barcode\t{0}\t{1}", image1Info.MediaBarcode, image2Info.MediaBarcode) - .AppendLine(); - sb.AppendFormat("Disk part no.\t{0}\t{1}", image1Info.MediaPartNumber, image2Info.MediaPartNumber) - .AppendLine(); - sb.AppendFormat("Disk sequence\t{0}\t{1}", image1Info.MediaSequence, image2Info.MediaSequence) - .AppendLine(); + + sb.AppendFormat("Disk barcode\t{0}\t{1}", image1Info.MediaBarcode, image2Info.MediaBarcode). + AppendLine(); + + sb.AppendFormat("Disk part no.\t{0}\t{1}", image1Info.MediaPartNumber, image2Info.MediaPartNumber). + AppendLine(); + + sb.AppendFormat("Disk sequence\t{0}\t{1}", image1Info.MediaSequence, image2Info.MediaSequence). + AppendLine(); + sb.AppendFormat("Last disk on sequence\t{0}\t{1}", image1Info.LastMediaSequence, image2Info.LastMediaSequence).AppendLine(); + sb.AppendFormat("Drive manufacturer\t{0}\t{1}", image1Info.DriveManufacturer, image2Info.DriveManufacturer).AppendLine(); + sb.AppendFormat("Drive firmware revision\t{0}\t{1}", image1Info.DriveFirmwareRevision, image2Info.DriveFirmwareRevision).AppendLine(); + sb.AppendFormat("Drive model\t{0}\t{1}", image1Info.DriveModel, image2Info.DriveModel).AppendLine(); + sb.AppendFormat("Drive serial number\t{0}\t{1}", image1Info.DriveSerialNumber, image2Info.DriveSerialNumber).AppendLine(); + foreach(MediaTagType disktag in Enum.GetValues(typeof(MediaTagType))) sb.AppendFormat("Has {0}?\t{1}\t{2}", disktag, image1DiskTags.ContainsKey(disktag), image2DiskTags.ContainsKey(disktag)).AppendLine(); @@ -256,58 +261,76 @@ namespace DiscImageChef.Commands if(image1Info.HasPartitions != image2Info.HasPartitions) { imagesDiffer = true; - if(!MainClass.Verbose) sb.AppendLine("Image partitioned status differ"); + + if(!verbose) + sb.AppendLine("Image partitioned status differ"); } if(image1Info.HasSessions != image2Info.HasSessions) { imagesDiffer = true; - if(!MainClass.Verbose) sb.AppendLine("Image session status differ"); + + if(!verbose) + sb.AppendLine("Image session status differ"); } if(image1Info.Sectors != image2Info.Sectors) { imagesDiffer = true; - if(!MainClass.Verbose) sb.AppendLine("Image sectors differ"); + + if(!verbose) + sb.AppendLine("Image sectors differ"); } if(image1Info.SectorSize != image2Info.SectorSize) { imagesDiffer = true; - if(!MainClass.Verbose) sb.AppendLine("Image sector size differ"); + + if(!verbose) + sb.AppendLine("Image sector size differ"); } if(image1Info.MediaType != image2Info.MediaType) { imagesDiffer = true; - if(!MainClass.Verbose) sb.AppendLine("Disk type differ"); + + if(!verbose) + sb.AppendLine("Disk type differ"); } ulong leastSectors; + if(image1Info.Sectors < image2Info.Sectors) { imagesDiffer = true; leastSectors = image1Info.Sectors; - if(!MainClass.Verbose) sb.AppendLine("Image 2 has more sectors"); + + if(!verbose) + sb.AppendLine("Image 2 has more sectors"); } else if(image1Info.Sectors > image2Info.Sectors) { imagesDiffer = true; leastSectors = image2Info.Sectors; - if(!MainClass.Verbose) sb.AppendLine("Image 1 has more sectors"); + + if(!verbose) + sb.AppendLine("Image 1 has more sectors"); } - else leastSectors = image1Info.Sectors; + else + leastSectors = image1Info.Sectors; DicConsole.WriteLine("Comparing sectors..."); for(ulong sector = 0; sector < leastSectors; sector++) { DicConsole.Write("\rComparing sector {0} of {1}...", sector + 1, leastSectors); + try { byte[] image1Sector = input1Format.ReadSector(sector); byte[] image2Sector = input2Format.ReadSector(sector); ArrayHelpers.CompareBytes(out bool different, out bool sameSize, image1Sector, image2Sector); + if(different) { imagesDiffer = true; @@ -316,8 +339,9 @@ namespace DiscImageChef.Commands else if(!sameSize) { imagesDiffer = true; - sb - .AppendFormat("Sector {0} has different sizes ({1} bytes in image 1, {2} in image 2) but are otherwise identical", + + sb. + AppendFormat("Sector {0} has different sizes ({1} bytes in image 1, {2} in image 2) but are otherwise identical", sector, image1Sector.LongLength, image2Sector.LongLength).AppendLine(); } } @@ -335,7 +359,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine(sb.ToString()); - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/Configure.cs b/DiscImageChef/Commands/Configure.cs index 5a943e915..b882e67e4 100644 --- a/DiscImageChef/Commands/Configure.cs +++ b/DiscImageChef/Commands/Configure.cs @@ -31,79 +31,65 @@ // ****************************************************************************/ using System; -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Settings; -using Mono.Options; namespace DiscImageChef.Commands { - class ConfigureCommand : Command + internal class ConfigureCommand : Command { - readonly bool gdprChange; - bool autoCall; - bool showHelp; + readonly bool _autoCall; + readonly bool _gdprChange; public ConfigureCommand(bool gdprChange, bool autoCall) : base("configure", "Configures user settings and statistics.") { - this.gdprChange = gdprChange; - this.autoCall = autoCall; - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name}", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + _gdprChange = gdprChange; + _autoCall = autoCall; + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + int Invoke(bool debug, bool verbose) { - if(!autoCall) + if(!_autoCall) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - if(extra.Count != 0) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; } - if(gdprChange) + if(_gdprChange) { DicConsole.WriteLine("In compliance with the European Union General Data Protection Regulation 2016/679 (GDPR),\n" + "we must give you the following information about DiscImageChef and ask if you want to opt-in\n" + "in some information sharing."); + DicConsole.WriteLine(); + DicConsole.WriteLine("Disclaimer: Because DiscImageChef is an open source software this information, and therefore,\n" + "compliance with GDPR only holds true if you obtained a certificated copy from its original\n" + "authors. In case of doubt, close DiscImageChef now and ask in our IRC support channel."); + DicConsole.WriteLine(); + DicConsole.WriteLine("For any information sharing your IP address may be stored in our server, in a way that is not\n" + "possible for any person, manual, or automated process, to link with your identity, unless\n" + "specified otherwise."); } - ConsoleKeyInfo pressedKey = new ConsoleKeyInfo(); + var pressedKey = new ConsoleKeyInfo(); #region Device reports DicConsole.WriteLine(); + DicConsole.WriteLine( "With the 'device-report' command, DiscImageChef creates a report of a device, that includes its\n" + "manufacturer, model, firmware revision and/or version, attached bus, size, and supported commands.\n" + @@ -113,7 +99,8 @@ namespace DiscImageChef.Commands "of devices. A human-readable copy of the report in XML format is always created in the same directory\n" + "where DiscImageChef is being run from."); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to save device reports in shared folder of your computer? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -124,12 +111,15 @@ namespace DiscImageChef.Commands pressedKey = new ConsoleKeyInfo(); DicConsole.WriteLine(); + DicConsole.WriteLine("Sharing a report with us will send it to our server, that's in the european union territory, where it\n" + - "will be manually analized by an european union citizen to remove any trace of personal identification\n" + - "from it. Once that is done, it will be shared in our stats website, https://www.discimagechef.app\n" + + "will be manually analyzed by an european union citizen to remove any trace of personal identification\n" + + "from it. Once that is done, it will be shared in our stats website, https://www.discimagechef.app\n" + "These report will be used to improve DiscImageChef support, and in some cases, to provide emulation of the\n" + "devices to other open-source projects. In any case, no information linking the report to you will be stored."); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to share your device reports with us? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -141,13 +131,16 @@ namespace DiscImageChef.Commands #region Statistics DicConsole.WriteLine(); + DicConsole.WriteLine("DiscImageChef can store some usage statistics. These statistics are limited to the number of times a\n" + "command is executed, a filesystem, partition, or device is used, the operating system version, and other.\n" + "In no case, any information besides pure statistical usage numbers is stored, and they're just joint to the\n" + "pool with no way of using them to identify you."); pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to save stats about your DiscImageChef usage? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -159,7 +152,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats = new StatsSettings(); pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to share your stats anonymously? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -169,7 +164,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.ShareStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about benchmarks? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -179,7 +176,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.BenchmarkStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about command usage? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -189,7 +188,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.CommandStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about found devices? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -199,7 +200,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.DeviceStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about found filesystems? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -209,7 +212,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.FilesystemStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about found file filters? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -219,7 +224,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.FilterStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about found media image formats? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -229,7 +236,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.MediaImageStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about scanned media? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -239,7 +248,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.MediaScanStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about found partitioning schemes? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -249,7 +260,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.PartitionStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about media types? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -259,7 +272,9 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.MediaStats = pressedKey.Key == ConsoleKey.Y; pressedKey = new ConsoleKeyInfo(); - while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) + + while(pressedKey.Key != ConsoleKey.Y && + pressedKey.Key != ConsoleKey.N) { DicConsole.Write("Do you want to gather statistics about media image verifications? (Y/N): "); pressedKey = System.Console.ReadKey(); @@ -268,12 +283,14 @@ namespace DiscImageChef.Commands Settings.Settings.Current.Stats.VerifyStats = pressedKey.Key == ConsoleKey.Y; } - else Settings.Settings.Current.Stats = null; + else + Settings.Settings.Current.Stats = null; #endregion Statistics Settings.Settings.Current.GdprCompliance = DicSettings.GdprLevel; Settings.Settings.SaveSettings(); - return (int)ErrorNumber.NoError; + + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/ConvertImage.cs b/DiscImageChef/Commands/ConvertImage.cs index 892f0f7dc..eac43fb9a 100644 --- a/DiscImageChef/Commands/ConvertImage.cs +++ b/DiscImageChef/Commands/ConvertImage.cs @@ -32,6 +32,8 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.IO; using System.Linq; using System.Xml.Serialization; @@ -42,235 +44,271 @@ using DiscImageChef.CommonTypes.Metadata; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; using Schemas; using ImageInfo = DiscImageChef.CommonTypes.Structs.ImageInfo; using Version = DiscImageChef.CommonTypes.Interop.Version; namespace DiscImageChef.Commands { - class ConvertImageCommand : Command + internal class ConvertImageCommand : Command { - string cicmXml; - string comments; - int count = 64; - string creator; - string driveFirmwareRevision; - string driveManufacturer; - string driveModel; - string driveSerialNumber; - bool force; - string inputFile; - int lastMediaSequence; - string mediaBarcode; - string mediaManufacturer; - string mediaModel; - string mediaPartNumber; - int mediaSequence; - string mediaSerialNumber; - string mediaTitle; - string outputFile; - string outputOptions; - string resumeFile; - bool showHelp; - string wantedOutputFormat; - public ConvertImageCommand() : base("convert-image", "Converts one image to another format.") { - Options = new OptionSet + Add(new Option(new[] + { + "--cicm-xml", "-x" + }, "Take metadata from existing CICM XML sidecar.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--comments", "Image comments.") { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] inputimage outputimage", - "", - Help, - {"cicm-xml|x=", "Take metadata from existing CICM XML sidecar.", s => cicmXml = s}, - {"comments=", "Image comments.", s => comments = s}, - {"count|c=", "How many sectors to convert at once.", (int i) => count = i}, - {"creator=", "Who (person) created the image?.", s => creator = s}, + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] { - "drive-manufacturer=", - "Manufacturer of the drive used to read the media represented by the image.", - s => driveManufacturer = s - }, + "--count", "-c" + }, "How many sectors to convert at once.") { - "drive-model=", "Model of the drive used to read the media represented by the image.", - s => driveModel = s - }, + Argument = new Argument(() => 64), Required = false + }); + + Add(new Option("--creator", "Who (person) created the image?.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--drive-manufacturer", + "Manufacturer of the drive used to read the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--drive-model", "Model of the drive used to read the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--drive-revision", + "Firmware revision of the drive used to read the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--drive-serial", + "Serial number of the drive used to read the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] { - "drive-revision=", - "Firmware revision of the drive used to read the media represented by the image.", - s => driveFirmwareRevision = s - }, + "--force", "-f" + }, "Continue conversion even if sector or media tags will be lost in the process.") { - "drive-serial=", "Serial number of the drive used to read the media represented by the image.", - s => driveSerialNumber = s - }, + Argument = new Argument(() => false), Required = false + }); + + Add(new Option(new[] + { + "--format", "-p" + }, + "Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--media-barcode", "Barcode of the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--media-lastsequence", + "Last media of the sequence the media represented by the image corresponds to.") + { + Argument = new Argument(() => 0), Required = false + }); + + Add(new Option("--media-manufacturer", "Manufacturer of the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--media-model", "Model of the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--media-partnumber", "Part number of the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--media-sequence", "Number in sequence for the media represented by the image.") + { + Argument = new Argument(() => 0), Required = false + }); + + Add(new Option("--media-serial", "Serial number of the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--media-title", "Title of the media represented by the image.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] { - "force|f", "Continue conversion even if sector or media tags will be lost in the process.", - b => force = b != null - }, + "--options", "-O" + }, "Comma separated name=value pairs of options to pass to output image plugin.") { - "format|p=", - "Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.", - s => wantedOutputFormat = s - }, - {"media-barcode=", "Barcode of the media represented by the image.", s => mediaBarcode = s}, + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] { - "media-lastsequence=", - "Last media of the sequence the media represented by the image corresponds to.", - (int i) => lastMediaSequence = i - }, + "--resume-file", "-r" + }, "Take list of dump hardware from existing resume file.") { - "media-manufacturer=", "Manufacturer of the media represented by the image.", - s => mediaManufacturer = s - }, - {"media-model=", "Model of the media represented by the image.", s => mediaModel = s}, - { - "media-partnumber=", "Part number of the media represented by the image.", - s => mediaPartNumber = s - }, - { - "media-sequence=", "Number in sequence for the media represented by the image.", - (int i) => mediaSequence = i - }, - { - "media-serial=", "Serial number of the media represented by the image.", - s => mediaSerialNumber = s - }, - {"media-title=", "Title of the media represented by the image.", s => mediaTitle = s}, - { - "options|O=", "Comma separated name=value pairs of options to pass to output image plugin.", - s => outputOptions = s - }, - {"resume-file|r=", "Take list of dump hardware from existing resume file.", s => resumeFile = s}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Argument = new Argument(() => null), Required = false + }); + + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Input image path", Name = "input-path" + }); + + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Output image path", Name = "output-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool verbose, bool debug, string cicmXml, string comments, int count, string creator, + string driveFirmwareRevision, string driveManufacturer, string driveModel, + string driveSerialNumber, bool force, string inputPath, int lastMediaSequence, + string mediaBarcode, string mediaManufacturer, string mediaModel, string mediaPartNumber, + int mediaSequence, string mediaSerialNumber, string mediaTitle, string outputPath, + string outputOptions, string resumeFile, string format) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("convert-image"); - if(extra.Count > 2) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count <= 1) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - outputFile = extra[1]; - - DicConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml); - DicConsole.DebugWriteLine("Analyze command", "--comments={0}", comments); - DicConsole.DebugWriteLine("Analyze command", "--count={0}", count); - DicConsole.DebugWriteLine("Analyze command", "--creator={0}", creator); - DicConsole.DebugWriteLine("Analyze command", "--debug={0}", MainClass.Debug); + DicConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml); + DicConsole.DebugWriteLine("Analyze command", "--comments={0}", comments); + DicConsole.DebugWriteLine("Analyze command", "--count={0}", count); + DicConsole.DebugWriteLine("Analyze command", "--creator={0}", creator); + DicConsole.DebugWriteLine("Analyze command", "--debug={0}", debug); DicConsole.DebugWriteLine("Analyze command", "--drive-manufacturer={0}", driveManufacturer); - DicConsole.DebugWriteLine("Analyze command", "--drive-model={0}", driveModel); - DicConsole.DebugWriteLine("Analyze command", "--drive-revision={0}", driveFirmwareRevision); - DicConsole.DebugWriteLine("Analyze command", "--drive-serial={0}", driveSerialNumber); - DicConsole.DebugWriteLine("Analyze command", "--force={0}", force); - DicConsole.DebugWriteLine("Analyze command", "--format={0}", wantedOutputFormat); - DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Analyze command", "--media-barcode={0}", mediaBarcode); + DicConsole.DebugWriteLine("Analyze command", "--drive-model={0}", driveModel); + DicConsole.DebugWriteLine("Analyze command", "--drive-revision={0}", driveFirmwareRevision); + DicConsole.DebugWriteLine("Analyze command", "--drive-serial={0}", driveSerialNumber); + DicConsole.DebugWriteLine("Analyze command", "--force={0}", force); + DicConsole.DebugWriteLine("Analyze command", "--format={0}", format); + DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputPath); + DicConsole.DebugWriteLine("Analyze command", "--media-barcode={0}", mediaBarcode); DicConsole.DebugWriteLine("Analyze command", "--media-lastsequence={0}", lastMediaSequence); DicConsole.DebugWriteLine("Analyze command", "--media-manufacturer={0}", mediaManufacturer); - DicConsole.DebugWriteLine("Analyze command", "--media-model={0}", mediaModel); - DicConsole.DebugWriteLine("Analyze command", "--media-partnumber={0}", mediaPartNumber); - DicConsole.DebugWriteLine("Analyze command", "--media-sequence={0}", mediaSequence); - DicConsole.DebugWriteLine("Analyze command", "--media-serial={0}", mediaSerialNumber); - DicConsole.DebugWriteLine("Analyze command", "--media-title={0}", mediaTitle); - DicConsole.DebugWriteLine("Analyze command", "--options={0}", outputOptions); - DicConsole.DebugWriteLine("Analyze command", "--output={0}", outputFile); - DicConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile); - DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Analyze command", "--media-model={0}", mediaModel); + DicConsole.DebugWriteLine("Analyze command", "--media-partnumber={0}", mediaPartNumber); + DicConsole.DebugWriteLine("Analyze command", "--media-sequence={0}", mediaSequence); + DicConsole.DebugWriteLine("Analyze command", "--media-serial={0}", mediaSerialNumber); + DicConsole.DebugWriteLine("Analyze command", "--media-title={0}", mediaTitle); + DicConsole.DebugWriteLine("Analyze command", "--options={0}", outputOptions); + DicConsole.DebugWriteLine("Analyze command", "--output={0}", outputPath); + DicConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile); + DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose); Dictionary parsedOptions = Core.Options.Parse(outputOptions); DicConsole.DebugWriteLine("Analyze command", "Parsed options:"); + foreach(KeyValuePair parsedOption in parsedOptions) DicConsole.DebugWriteLine("Analyze command", "{0} = {1}", parsedOption.Key, parsedOption.Value); if(count == 0) { DicConsole.ErrorWriteLine("Need to specify more than 0 sectors to copy at once"); - return (int)ErrorNumber.InvalidArgument; + + return(int)ErrorNumber.InvalidArgument; } Resume resume = null; CICMMetadataType sidecar = null; - XmlSerializer xs = new XmlSerializer(typeof(CICMMetadataType)); + var xs = new XmlSerializer(typeof(CICMMetadataType)); + if(cicmXml != null) if(File.Exists(cicmXml)) try { - StreamReader sr = new StreamReader(cicmXml); + var sr = new StreamReader(cicmXml); sidecar = (CICMMetadataType)xs.Deserialize(sr); sr.Close(); } catch { DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing..."); - return (int)ErrorNumber.InvalidSidecar; + + return(int)ErrorNumber.InvalidSidecar; } else { DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing..."); - return (int)ErrorNumber.FileNotFound; + + return(int)ErrorNumber.FileNotFound; } xs = new XmlSerializer(typeof(Resume)); + if(resumeFile != null) if(File.Exists(resumeFile)) try { - StreamReader sr = new StreamReader(resumeFile); + var sr = new StreamReader(resumeFile); resume = (Resume)xs.Deserialize(sr); sr.Close(); } catch { DicConsole.ErrorWriteLine("Incorrect resume file, not continuing..."); - return (int)ErrorNumber.InvalidResume; + + return(int)ErrorNumber.InvalidResume; } else { DicConsole.ErrorWriteLine("Could not find resume file, not continuing..."); - return (int)ErrorNumber.FileNotFound; + + return(int)ErrorNumber.FileNotFound; } - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(inputPath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } - if(File.Exists(outputFile)) + if(File.Exists(outputPath)) { DicConsole.ErrorWriteLine("Output file already exists, not continuing."); - return (int)ErrorNumber.DestinationExists; + + return(int)ErrorNumber.DestinationExists; } PluginBase plugins = GetPluginBase.Instance; @@ -279,13 +317,15 @@ namespace DiscImageChef.Commands if(inputFormat == null) { DicConsole.WriteLine("Input image format not identified, not proceeding with conversion."); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("Input image format identified by {0} ({1}).", inputFormat.Name, inputFormat.Id); - else DicConsole.WriteLine("Input image format identified by {0}.", inputFormat.Name); + else + DicConsole.WriteLine("Input image format identified by {0}.", inputFormat.Name); try { @@ -293,13 +333,17 @@ namespace DiscImageChef.Commands { DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("No error given"); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } DicConsole.DebugWriteLine("Convert-image command", "Correctly opened image file."); + DicConsole.DebugWriteLine("Convert-image command", "Image without headers is {0} bytes.", inputFormat.Info.ImageSize); + DicConsole.DebugWriteLine("Convert-image command", "Image has {0} sectors.", inputFormat.Info.Sectors); + DicConsole.DebugWriteLine("Convert-image command", "Image identifies media type as {0}.", inputFormat.Info.MediaType); @@ -312,85 +356,101 @@ namespace DiscImageChef.Commands DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Error: {0}", ex.Message); DicConsole.DebugWriteLine("Convert-image command", "Stack trace: {0}", ex.StackTrace); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } List candidates = new List(); // Try extension - if(string.IsNullOrEmpty(wantedOutputFormat)) + if(string.IsNullOrEmpty(format)) candidates.AddRange(plugins.WritableImages.Values.Where(t => - t.KnownExtensions - .Contains(Path.GetExtension(outputFile)))); + t.KnownExtensions. + Contains(Path.GetExtension(outputPath)))); + // Try Id - else if(Guid.TryParse(wantedOutputFormat, out Guid outId)) + else if(Guid.TryParse(format, out Guid outId)) candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId))); + // Try name else - candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, wantedOutputFormat, - StringComparison - .InvariantCultureIgnoreCase))); + candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, format, + StringComparison. + InvariantCultureIgnoreCase))); if(candidates.Count == 0) { DicConsole.WriteLine("No plugin supports requested extension."); - return (int)ErrorNumber.FormatNotFound; + + return(int)ErrorNumber.FormatNotFound; } if(candidates.Count > 1) { DicConsole.WriteLine("More than one plugin supports requested extension."); - return (int)ErrorNumber.TooManyFormats; + + return(int)ErrorNumber.TooManyFormats; } IWritableImage outputFormat = candidates[0]; - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id); - else DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name); + else + DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name); if(!outputFormat.SupportedMediaTypes.Contains(inputFormat.Info.MediaType)) { DicConsole.ErrorWriteLine("Output format does not support media type, cannot continue..."); - return (int)ErrorNumber.UnsupportedMedia; + + return(int)ErrorNumber.UnsupportedMedia; } foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags) { - if(outputFormat.SupportedMediaTags.Contains(mediaTag) || force) continue; + if(outputFormat.SupportedMediaTags.Contains(mediaTag) || force) + continue; DicConsole.ErrorWriteLine("Converting image will lose media tag {0}, not continuing...", mediaTag); DicConsole.ErrorWriteLine("If you don't care, use force option."); - return (int)ErrorNumber.DataWillBeLost; + + return(int)ErrorNumber.DataWillBeLost; } bool useLong = inputFormat.Info.ReadableSectorTags.Count != 0; foreach(SectorTagType sectorTag in inputFormat.Info.ReadableSectorTags) { - if(outputFormat.SupportedSectorTags.Contains(sectorTag)) continue; + if(outputFormat.SupportedSectorTags.Contains(sectorTag)) + continue; if(force) { - if(sectorTag != SectorTagType.CdTrackFlags && sectorTag != SectorTagType.CdTrackIsrc && - sectorTag != SectorTagType.CdSectorSubchannel) useLong = false; + if(sectorTag != SectorTagType.CdTrackFlags && + sectorTag != SectorTagType.CdTrackIsrc && + sectorTag != SectorTagType.CdSectorSubchannel) + useLong = false; + continue; } DicConsole.ErrorWriteLine("Converting image will lose sector tag {0}, not continuing...", sectorTag); - DicConsole - .ErrorWriteLine("If you don't care, use force option. This will skip all sector tags converting only user data."); - return (int)ErrorNumber.DataWillBeLost; + + DicConsole. + ErrorWriteLine("If you don't care, use force option. This will skip all sector tags converting only user data."); + + return(int)ErrorNumber.DataWillBeLost; } - if(!outputFormat.Create(outputFile, inputFormat.Info.MediaType, parsedOptions, inputFormat.Info.Sectors, + if(!outputFormat.Create(outputPath, inputFormat.Info.MediaType, parsedOptions, inputFormat.Info.Sectors, inputFormat.Info.SectorSize)) { DicConsole.ErrorWriteLine("Error {0} creating output image.", outputFormat.ErrorMessage); - return (int)ErrorNumber.CannotCreateFormat; + + return(int)ErrorNumber.CannotCreateFormat; } - ImageInfo metadata = new ImageInfo + var metadata = new ImageInfo { Application = "DiscImageChef", ApplicationVersion = Version.GetVersion(), @@ -413,10 +473,12 @@ namespace DiscImageChef.Commands if(!outputFormat.SetMetadata(metadata)) { DicConsole.ErrorWrite("Error {0} setting metadata, ", outputFormat.ErrorMessage); + if(!force) { DicConsole.ErrorWriteLine("not continuing..."); - return (int)ErrorNumber.WriteError; + + return(int)ErrorNumber.WriteError; } DicConsole.ErrorWriteLine("continuing..."); @@ -427,11 +489,14 @@ namespace DiscImageChef.Commands foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags) { - if(force && !outputFormat.SupportedMediaTags.Contains(mediaTag)) continue; + if(force && !outputFormat.SupportedMediaTags.Contains(mediaTag)) + continue; DicConsole.WriteLine("Converting media tag {0}", mediaTag); byte[] tag = inputFormat.ReadDiskTag(mediaTag); - if(outputFormat.WriteMediaTag(tag, mediaTag)) continue; + + if(outputFormat.WriteMediaTag(tag, mediaTag)) + continue; if(force) DicConsole.ErrorWriteLine("Error {0} writing media tag, continuing...", outputFormat.ErrorMessage); @@ -439,35 +504,41 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Error {0} writing media tag, not continuing...", outputFormat.ErrorMessage); - return (int)ErrorNumber.WriteError; + + return(int)ErrorNumber.WriteError; } } DicConsole.WriteLine("{0} sectors to convert", inputFormat.Info.Sectors); ulong doneSectors = 0; - if(inputFormat is IOpticalMediaImage inputOptical && outputFormat is IWritableOpticalImage outputOptical && + if(inputFormat is IOpticalMediaImage inputOptical && + outputFormat is IWritableOpticalImage outputOptical && inputOptical.Tracks != null) { if(!outputOptical.SetTracks(inputOptical.Tracks)) { DicConsole.ErrorWriteLine("Error {0} sending tracks list to output image.", outputFormat.ErrorMessage); - return (int)ErrorNumber.WriteError; + + return(int)ErrorNumber.WriteError; } foreach(Track track in inputOptical.Tracks) { doneSectors = 0; - ulong trackSectors = track.TrackEndSector - track.TrackStartSector + 1; + ulong trackSectors = (track.TrackEndSector - track.TrackStartSector) + 1; while(doneSectors < trackSectors) { byte[] sector; uint sectorsToDo; - if(trackSectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count; - else sectorsToDo = (uint)(trackSectors - doneSectors); + + if(trackSectors - doneSectors >= (ulong)count) + sectorsToDo = (uint)count; + else + sectorsToDo = (uint)(trackSectors - doneSectors); DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)", doneSectors + track.TrackStartSector, @@ -476,6 +547,7 @@ namespace DiscImageChef.Commands track.TrackSequence); bool result; + if(useLong) if(sectorsToDo == 1) { @@ -485,6 +557,7 @@ namespace DiscImageChef.Commands else { sector = inputFormat.ReadSectorsLong(doneSectors + track.TrackStartSector, sectorsToDo); + result = outputFormat.WriteSectorsLong(sector, doneSectors + track.TrackStartSector, sectorsToDo); } @@ -498,6 +571,7 @@ namespace DiscImageChef.Commands else { sector = inputFormat.ReadSectors(doneSectors + track.TrackStartSector, sectorsToDo); + result = outputFormat.WriteSectors(sector, doneSectors + track.TrackStartSector, sectorsToDo); } @@ -511,7 +585,8 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...", outputFormat.ErrorMessage, doneSectors); - return (int)ErrorNumber.WriteError; + + return(int)ErrorNumber.WriteError; } doneSectors += sectorsToDo; @@ -520,11 +595,13 @@ namespace DiscImageChef.Commands DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)", inputFormat.Info.Sectors, inputFormat.Info.Sectors, 1.0, inputOptical.Tracks.Count); + DicConsole.WriteLine(); foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.OrderBy(t => t)) { - if(!useLong) break; + if(!useLong) + break; switch(tag) { @@ -540,12 +617,13 @@ namespace DiscImageChef.Commands continue; } - if(force && !outputFormat.SupportedSectorTags.Contains(tag)) continue; + if(force && !outputFormat.SupportedSectorTags.Contains(tag)) + continue; foreach(Track track in inputOptical.Tracks) { doneSectors = 0; - ulong trackSectors = track.TrackEndSector - track.TrackStartSector + 1; + ulong trackSectors = (track.TrackEndSector - track.TrackStartSector) + 1; byte[] sector; bool result; @@ -556,8 +634,10 @@ namespace DiscImageChef.Commands DicConsole.Write("\rConverting tag {0} in track {1} ({2:P2} done).", tag, track.TrackSequence, track.TrackSequence / (double)inputOptical.Tracks.Count); + sector = inputFormat.ReadSectorTag(track.TrackStartSector, tag); result = outputFormat.WriteSectorTag(sector, track.TrackStartSector, tag); + if(!result) if(force) DicConsole.ErrorWriteLine("Error {0} writing tag, continuing...", @@ -566,7 +646,8 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Error {0} writing tag, not continuing...", outputFormat.ErrorMessage); - return (int)ErrorNumber.WriteError; + + return(int)ErrorNumber.WriteError; } continue; @@ -575,10 +656,11 @@ namespace DiscImageChef.Commands while(doneSectors < trackSectors) { uint sectorsToDo; - if(trackSectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count; + + if(trackSectors - doneSectors >= (ulong)count) + sectorsToDo = (uint)count; else - sectorsToDo = - (uint)(trackSectors - doneSectors); + sectorsToDo = (uint)(trackSectors - doneSectors); DicConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)", doneSectors + track.TrackStartSector, @@ -595,6 +677,7 @@ namespace DiscImageChef.Commands { sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo, tag); + result = outputFormat.WriteSectorsTag(sector, doneSectors + track.TrackStartSector, sectorsToDo, tag); } @@ -607,7 +690,8 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, not continuing...", outputFormat.ErrorMessage, doneSectors); - return (int)ErrorNumber.WriteError; + + return(int)ErrorNumber.WriteError; } doneSectors += sectorsToDo; @@ -620,11 +704,13 @@ namespace DiscImageChef.Commands case SectorTagType.CdTrackIsrc: DicConsole.Write("\rConverting tag {0} in track {1} ({2:P2} done).", tag, inputOptical.Tracks.Count, 1.0); + break; default: DicConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)", inputFormat.Info.Sectors, inputFormat.Info.Sectors, 1.0, inputOptical.Tracks.Count, tag); + break; } @@ -636,6 +722,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Setting geometry to {0} cylinders, {1} heads and {2} sectors per track", inputFormat.Info.Cylinders, inputFormat.Info.Heads, inputFormat.Info.SectorsPerTrack); + if(!outputFormat.SetGeometry(inputFormat.Info.Cylinders, inputFormat.Info.Heads, inputFormat.Info.SectorsPerTrack)) DicConsole.ErrorWriteLine("Error {0} setting geometry, image may be incorrect, continuing...", @@ -646,15 +733,17 @@ namespace DiscImageChef.Commands byte[] sector; uint sectorsToDo; - if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count; + + if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) + sectorsToDo = (uint)count; else - sectorsToDo = - (uint)(inputFormat.Info.Sectors - doneSectors); + sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors); DicConsole.Write("\rConverting sectors {0} to {1} ({2:P2} done)", doneSectors, doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors); bool result; + if(useLong) if(sectorsToDo == 1) { @@ -688,7 +777,8 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...", outputFormat.ErrorMessage, doneSectors); - return (int)ErrorNumber.WriteError; + + return(int)ErrorNumber.WriteError; } doneSectors += sectorsToDo; @@ -696,11 +786,13 @@ namespace DiscImageChef.Commands DicConsole.Write("\rConverting sectors {0} to {1} ({2:P2} done)", inputFormat.Info.Sectors, inputFormat.Info.Sectors, 1.0); + DicConsole.WriteLine(); foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags) { - if(!useLong) break; + if(!useLong) + break; switch(tag) { @@ -716,24 +808,28 @@ namespace DiscImageChef.Commands continue; } - if(force && !outputFormat.SupportedSectorTags.Contains(tag)) continue; + if(force && !outputFormat.SupportedSectorTags.Contains(tag)) + continue; doneSectors = 0; + while(doneSectors < inputFormat.Info.Sectors) { byte[] sector; uint sectorsToDo; - if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count; + + if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) + sectorsToDo = (uint)count; else - sectorsToDo = - (uint)(inputFormat.Info.Sectors - doneSectors); + sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors); DicConsole.Write("\rConverting tag {2} for sectors {0} to {1} ({2:P2} done)", doneSectors, doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors, tag); bool result; + if(sectorsToDo == 1) { sector = inputFormat.ReadSectorTag(doneSectors, tag); @@ -753,7 +849,8 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...", outputFormat.ErrorMessage, doneSectors); - return (int)ErrorNumber.WriteError; + + return(int)ErrorNumber.WriteError; } doneSectors += sectorsToDo; @@ -761,24 +858,37 @@ namespace DiscImageChef.Commands DicConsole.Write("\rConverting tag {2} for sectors {0} to {1} ({2:P2} done)", inputFormat.Info.Sectors, inputFormat.Info.Sectors, 1.0, tag); + DicConsole.WriteLine(); } } bool ret = false; - if(resume != null || dumpHardware != null) + + if(resume != null || + dumpHardware != null) { - if(resume != null) ret = outputFormat.SetDumpHardware(resume.Tries); - else if(dumpHardware != null) ret = outputFormat.SetDumpHardware(dumpHardware); - if(ret) DicConsole.WriteLine("Written dump hardware list to output image."); + if(resume != null) + ret = outputFormat.SetDumpHardware(resume.Tries); + else if(dumpHardware != null) + ret = outputFormat.SetDumpHardware(dumpHardware); + + if(ret) + DicConsole.WriteLine("Written dump hardware list to output image."); } ret = false; - if(sidecar != null || cicmMetadata != null) + + if(sidecar != null || + cicmMetadata != null) { - if(sidecar != null) ret = outputFormat.SetCicmMetadata(sidecar); - else if(cicmMetadata != null) ret = outputFormat.SetCicmMetadata(cicmMetadata); - if(ret) DicConsole.WriteLine("Written CICM XML metadata to output image."); + if(sidecar != null) + ret = outputFormat.SetCicmMetadata(sidecar); + else if(cicmMetadata != null) + ret = outputFormat.SetCicmMetadata(cicmMetadata); + + if(ret) + DicConsole.WriteLine("Written CICM XML metadata to output image."); } DicConsole.WriteLine("Closing output image."); @@ -790,7 +900,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine(); DicConsole.WriteLine("Conversion done."); - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/CreateSidecar.cs b/DiscImageChef/Commands/CreateSidecar.cs index a3b5936aa..73fd52866 100644 --- a/DiscImageChef/Commands/CreateSidecar.cs +++ b/DiscImageChef/Commands/CreateSidecar.cs @@ -32,6 +32,8 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.IO; using System.Linq; using System.Text; @@ -41,109 +43,109 @@ using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; using Schemas; namespace DiscImageChef.Commands { - class CreateSidecarCommand : Command + internal class CreateSidecarCommand : Command { - uint blockSize; - string encodingName; - string inputFile; - bool showHelp; - bool tape; - public CreateSidecarCommand() : base("create-sidecar", "Creates CICM Metadata XML sidecar.") { - Options = new OptionSet + Add(new Option(new[] + { + "--block-size", "-b" + }, + "Only used for tapes, indicates block size. Files in the folder whose size is not a multiple of this value will simply be ignored.") { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] input", - "", - Help, + Argument = new Argument(() => 512), Required = false + }); + + Add(new Option(new[] { - "block-size|b=", - "Only used for tapes, indicates block size. Files in the folder whose size is not a multiple of this value will simply be ignored.", - (uint i) => blockSize = i - }, - {"encoding|e=", "Name of character encoding to use.", s => encodingName = s}, + "--encoding", "-e" + }, "Name of character encoding to use.") { - "tape|t", - "When used indicates that input is a folder containing alphabetically sorted files extracted from a linear block-based tape with fixed block size (e.g. a SCSI tape device).", - b => tape = b != null - }, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] + { + "--encoding", "-e" + }, "Name of character encoding to use.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] + { + "--tape", "-t" + }, + "When used indicates that input is a folder containing alphabetically sorted files extracted from a linear block-based tape with fixed block size (e.g. a SCSI tape device).") + { + Argument = new Argument(() => false), Required = false + }); + + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, uint blockSize, string encodingName, string imagePath, bool tape) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("create-sidecar"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - DicConsole.DebugWriteLine("Create sidecar command", "--block-size={0}", blockSize); - DicConsole.DebugWriteLine("Create sidecar command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Create sidecar command", "--encoding={0}", encodingName); - DicConsole.DebugWriteLine("Create sidecar command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Create sidecar command", "--tape={0}", tape); - DicConsole.DebugWriteLine("Create sidecar command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Create sidecar command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Create sidecar command", "--encoding={0}", encodingName); + DicConsole.DebugWriteLine("Create sidecar command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Create sidecar command", "--tape={0}", tape); + DicConsole.DebugWriteLine("Create sidecar command", "--verbose={0}", verbose); - Encoding encoding = null; + Encoding encodingClass = null; if(encodingName != null) try { - encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); + encodingClass = Claunia.Encoding.Encoding.GetEncoding(encodingName); + + if(verbose) + DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName); } catch(ArgumentException) { DicConsole.ErrorWriteLine("Specified encoding is not supported."); - return (int)ErrorNumber.EncodingUnknown; + + return(int)ErrorNumber.EncodingUnknown; } - if(File.Exists(inputFile)) + if(File.Exists(imagePath)) { if(tape) { DicConsole.ErrorWriteLine("You cannot use --tape option when input is a file."); - return (int)ErrorNumber.ExpectedDirectory; + + return(int)ErrorNumber.ExpectedDirectory; } - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } try @@ -153,13 +155,15 @@ namespace DiscImageChef.Commands if(imageFormat == null) { DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); - else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); + else + DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); try { @@ -167,7 +171,8 @@ namespace DiscImageChef.Commands { DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("No error given"); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } DicConsole.DebugWriteLine("Analyze command", "Correctly opened image file."); @@ -176,13 +181,14 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Error: {0}", ex.Message); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } Statistics.AddMediaFormat(imageFormat.Format); Statistics.AddFilter(inputFilter.Name); - Sidecar sidecarClass = new Sidecar(imageFormat, inputFile, inputFilter.Id, encoding); + var sidecarClass = new Sidecar(imageFormat, imagePath, inputFilter.Id, encodingClass); sidecarClass.InitProgressEvent += Progress.InitProgress; sidecarClass.UpdateProgressEvent += Progress.UpdateProgress; sidecarClass.EndProgressEvent += Progress.EndProgress; @@ -190,21 +196,23 @@ namespace DiscImageChef.Commands sidecarClass.UpdateProgressEvent2 += Progress.UpdateProgress2; sidecarClass.EndProgressEvent2 += Progress.EndProgress2; sidecarClass.UpdateStatusEvent += Progress.UpdateStatus; + System.Console.CancelKeyPress += (sender, e) => { e.Cancel = true; sidecarClass.Abort(); }; + CICMMetadataType sidecar = sidecarClass.Create(); DicConsole.WriteLine("Writing metadata sidecar"); - FileStream xmlFs = + var xmlFs = new - FileStream(Path.Combine(Path.GetDirectoryName(inputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(inputFile) + ".cicm.xml"), + FileStream(Path.Combine(Path.GetDirectoryName(imagePath) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(imagePath) + ".cicm.xml"), FileMode.CreateNew); - XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType)); + var xmlSer = new XmlSerializer(typeof(CICMMetadataType)); xmlSer.Serialize(xmlFs, sidecar); xmlFs.Close(); } @@ -212,23 +220,25 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}"); DicConsole.DebugWriteLine("Analyze command", ex.StackTrace); - return (int)ErrorNumber.UnexpectedException; + + return(int)ErrorNumber.UnexpectedException; } } - else if(Directory.Exists(inputFile)) + else if(Directory.Exists(imagePath)) { if(!tape) { DicConsole.ErrorWriteLine("Cannot create a sidecar from a directory."); - return (int)ErrorNumber.ExpectedFile; + + return(int)ErrorNumber.ExpectedFile; } - string[] contents = Directory.GetFiles(inputFile, "*", SearchOption.TopDirectoryOnly); + string[] contents = Directory.GetFiles(imagePath, "*", SearchOption.TopDirectoryOnly); List files = contents.Where(file => new FileInfo(file).Length % blockSize == 0).ToList(); files.Sort(StringComparer.CurrentCultureIgnoreCase); - Sidecar sidecarClass = new Sidecar(); + var sidecarClass = new Sidecar(); sidecarClass.InitProgressEvent += Progress.InitProgress; sidecarClass.UpdateProgressEvent += Progress.UpdateProgress; sidecarClass.EndProgressEvent += Progress.EndProgress; @@ -236,22 +246,23 @@ namespace DiscImageChef.Commands sidecarClass.UpdateProgressEvent2 += Progress.UpdateProgress2; sidecarClass.EndProgressEvent2 += Progress.EndProgress2; sidecarClass.UpdateStatusEvent += Progress.UpdateStatus; - CICMMetadataType sidecar = sidecarClass.BlockTape(Path.GetFileName(inputFile), files, blockSize); + CICMMetadataType sidecar = sidecarClass.BlockTape(Path.GetFileName(imagePath), files, blockSize); DicConsole.WriteLine("Writing metadata sidecar"); - FileStream xmlFs = + var xmlFs = new - FileStream(Path.Combine(Path.GetDirectoryName(inputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(inputFile) + ".cicm.xml"), + FileStream(Path.Combine(Path.GetDirectoryName(imagePath) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(imagePath) + ".cicm.xml"), FileMode.CreateNew); - XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType)); + var xmlSer = new XmlSerializer(typeof(CICMMetadataType)); xmlSer.Serialize(xmlFs, sidecar); xmlFs.Close(); } - else DicConsole.ErrorWriteLine("The specified input file cannot be found."); + else + DicConsole.ErrorWriteLine("The specified input file cannot be found."); - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/Decode.cs b/DiscImageChef/Commands/Decode.cs index 33bda02ce..4c02cb3b5 100644 --- a/DiscImageChef/Commands/Decode.cs +++ b/DiscImageChef/Commands/Decode.cs @@ -30,7 +30,8 @@ // Copyright © 2011-2019 Natalia Portillo // ****************************************************************************/ -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; @@ -39,81 +40,82 @@ using DiscImageChef.Core; using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.CD; using DiscImageChef.Decoders.SCSI; -using Mono.Options; namespace DiscImageChef.Commands { - class DecodeCommand : Command + internal class DecodeCommand : Command { - bool diskTags = true; - string inputFile; - string length = "all"; - bool sectorTags = true; - bool showHelp; - ulong startSector; - public DecodeCommand() : base("decode", "Decodes and pretty prints disk and/or sector tags.") { - Options = new OptionSet + Add(new Option(new[] + { + "--disk-tags", "-f" + }, "Decode disk tags.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--length", "-l" + }, "How many sectors to decode, or \"all\".") + { + Argument = new Argument(() => "all"), Required = false + }); + + Add(new Option(new[] + { + "--sector-tags", "-p" + }, "Decode sector tags.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--start", "-s" + }, "Sector to start decoding from.") + { + Argument = new Argument(() => 0), Required = false + }); + + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] imagefile", - "", - Help, - {"disk-tags|f", "Decode disk tags.", b => diskTags = b != null}, - {"length|l=", "How many sectors to decode, or \"all\".", s => length = s}, - {"sector-tags|p", "Decode sector tags.", b => sectorTags = b != null}, - {"start|s=", "Name of character encoding to use.", (ulong ul) => startSector = ul}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool verbose, bool debug, bool diskTags, string imagePath, string length, bool sectorTags, + ulong startSector) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("decode"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - - DicConsole.DebugWriteLine("Decode command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", diskTags); - DicConsole.DebugWriteLine("Decode command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Decode command", "--length={0}", length); + DicConsole.DebugWriteLine("Decode command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", diskTags); + DicConsole.DebugWriteLine("Decode command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Decode command", "--length={0}", length); DicConsole.DebugWriteLine("Decode command", "--sector-tags={0}", sectorTags); - DicConsole.DebugWriteLine("Decode command", "--start={0}", startSector); - DicConsole.DebugWriteLine("Decode command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Decode command", "--start={0}", startSector); + DicConsole.DebugWriteLine("Decode command", "--verbose={0}", verbose); - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } IMediaImage inputFormat = ImageFormat.Detect(inputFilter); @@ -121,7 +123,8 @@ namespace DiscImageChef.Commands if(inputFormat == null) { DicConsole.ErrorWriteLine("Unable to recognize image format, not decoding"); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } inputFormat.Open(inputFilter); @@ -139,16 +142,20 @@ namespace DiscImageChef.Commands case MediaTagType.SCSI_INQUIRY: { byte[] inquiry = inputFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY); + if(inquiry == null) DicConsole.WriteLine("Error reading SCSI INQUIRY response from disc image"); else { DicConsole.WriteLine("SCSI INQUIRY command response:"); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + DicConsole.WriteLine(Inquiry.Prettify(inquiry)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); } break; @@ -156,16 +163,20 @@ namespace DiscImageChef.Commands case MediaTagType.ATA_IDENTIFY: { byte[] identify = inputFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY); + if(identify == null) DicConsole.WriteLine("Error reading ATA IDENTIFY DEVICE response from disc image"); else { DicConsole.WriteLine("ATA IDENTIFY DEVICE command response:"); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + DicConsole.WriteLine(Identify.Prettify(identify)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); } break; @@ -173,17 +184,21 @@ namespace DiscImageChef.Commands case MediaTagType.ATAPI_IDENTIFY: { byte[] identify = inputFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY); + if(identify == null) - DicConsole - .WriteLine("Error reading ATA IDENTIFY PACKET DEVICE response from disc image"); + DicConsole. + WriteLine("Error reading ATA IDENTIFY PACKET DEVICE response from disc image"); else { DicConsole.WriteLine("ATA IDENTIFY PACKET DEVICE command response:"); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + DicConsole.WriteLine(Identify.Prettify(identify)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); } break; @@ -191,31 +206,41 @@ namespace DiscImageChef.Commands case MediaTagType.CD_ATIP: { byte[] atip = inputFormat.ReadDiskTag(MediaTagType.CD_ATIP); - if(atip == null) DicConsole.WriteLine("Error reading CD ATIP from disc image"); + + if(atip == null) + DicConsole.WriteLine("Error reading CD ATIP from disc image"); else { DicConsole.WriteLine("CD ATIP:"); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + DicConsole.WriteLine(ATIP.Prettify(atip)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); } break; } case MediaTagType.CD_FullTOC: { - byte[] fulltoc = inputFormat.ReadDiskTag(MediaTagType.CD_FullTOC); - if(fulltoc == null) DicConsole.WriteLine("Error reading CD full TOC from disc image"); + byte[] fullToc = inputFormat.ReadDiskTag(MediaTagType.CD_FullTOC); + + if(fullToc == null) + DicConsole.WriteLine("Error reading CD full TOC from disc image"); else { DicConsole.WriteLine("CD full TOC:"); - DicConsole - .WriteLine("================================================================================"); - DicConsole.WriteLine(FullTOC.Prettify(fulltoc)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + + DicConsole.WriteLine(FullTOC.Prettify(fullToc)); + + DicConsole. + WriteLine("================================================================================"); } break; @@ -223,48 +248,62 @@ namespace DiscImageChef.Commands case MediaTagType.CD_PMA: { byte[] pma = inputFormat.ReadDiskTag(MediaTagType.CD_PMA); - if(pma == null) DicConsole.WriteLine("Error reading CD PMA from disc image"); + + if(pma == null) + DicConsole.WriteLine("Error reading CD PMA from disc image"); else { DicConsole.WriteLine("CD PMA:"); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + DicConsole.WriteLine(PMA.Prettify(pma)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); } break; } case MediaTagType.CD_SessionInfo: { - byte[] sessioninfo = inputFormat.ReadDiskTag(MediaTagType.CD_SessionInfo); - if(sessioninfo == null) + byte[] sessionInfo = inputFormat.ReadDiskTag(MediaTagType.CD_SessionInfo); + + if(sessionInfo == null) DicConsole.WriteLine("Error reading CD session information from disc image"); else { DicConsole.WriteLine("CD session information:"); - DicConsole - .WriteLine("================================================================================"); - DicConsole.WriteLine(Session.Prettify(sessioninfo)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + + DicConsole.WriteLine(Session.Prettify(sessionInfo)); + + DicConsole. + WriteLine("================================================================================"); } break; } case MediaTagType.CD_TEXT: { - byte[] cdtext = inputFormat.ReadDiskTag(MediaTagType.CD_TEXT); - if(cdtext == null) DicConsole.WriteLine("Error reading CD-TEXT from disc image"); + byte[] cdText = inputFormat.ReadDiskTag(MediaTagType.CD_TEXT); + + if(cdText == null) + DicConsole.WriteLine("Error reading CD-TEXT from disc image"); else { DicConsole.WriteLine("CD-TEXT:"); - DicConsole - .WriteLine("================================================================================"); - DicConsole.WriteLine(CDTextOnLeadIn.Prettify(cdtext)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + + DicConsole.WriteLine(CDTextOnLeadIn.Prettify(cdText)); + + DicConsole. + WriteLine("================================================================================"); } break; @@ -272,15 +311,20 @@ namespace DiscImageChef.Commands case MediaTagType.CD_TOC: { byte[] toc = inputFormat.ReadDiskTag(MediaTagType.CD_TOC); - if(toc == null) DicConsole.WriteLine("Error reading CD TOC from disc image"); + + if(toc == null) + DicConsole.WriteLine("Error reading CD TOC from disc image"); else { DicConsole.WriteLine("CD TOC:"); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); + DicConsole.WriteLine(TOC.Prettify(toc)); - DicConsole - .WriteLine("================================================================================"); + + DicConsole. + WriteLine("================================================================================"); } break; @@ -288,6 +332,7 @@ namespace DiscImageChef.Commands default: DicConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.", tag); + break; } @@ -300,6 +345,7 @@ namespace DiscImageChef.Commands { DicConsole.WriteLine("Value \"{0}\" is not a valid number for length.", length); DicConsole.WriteLine("Not decoding sectors tags"); + return 3; } } @@ -313,13 +359,14 @@ namespace DiscImageChef.Commands default: DicConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.", tag); + break; } // TODO: Not implemented } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/DeviceInfo.cs b/DiscImageChef/Commands/DeviceInfo.cs index 8234fe495..88c34b509 100644 --- a/DiscImageChef/Commands/DeviceInfo.cs +++ b/DiscImageChef/Commands/DeviceInfo.cs @@ -31,6 +31,8 @@ // ****************************************************************************/ using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Core; @@ -40,72 +42,46 @@ using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI.MMC; using DiscImageChef.Decoders.SCSI.SSC; using DiscImageChef.Devices; -using Mono.Options; using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo; namespace DiscImageChef.Commands { internal class DeviceInfoCommand : Command { - string devicePath; - string outputPrefix; - - bool showHelp; - - public DeviceInfoCommand() : base("device-info", "Gets information about a device.") => Options = new OptionSet + public DeviceInfoCommand() : base("device-info", "Gets information about a device.") { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] devicepath", "", - Help, - { - "output-prefix|w=", "Name of character encoding to use.", s => outputPrefix = s - }, - { - "help|h|?", "Show this message and exit.", v => showHelp = v != null - } - }; + Add(new Option(new[] + { + "--output-prefix", "-w" + }, "Prefix for saving binary information from device.") + { + Argument = new Argument(() => null), Required = false + }); - public override int Invoke(IEnumerable arguments) + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + } + + static int Invoke(bool debug, bool verbose, string devicePath, string outputPrefix) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - - return(int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) + if(debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; Statistics.AddCommand("device-info"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - - return(int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing device path."); - - return(int)ErrorNumber.MissingArgument; - } - - devicePath = extra[0]; - - DicConsole.DebugWriteLine("Device-Info command", "--debug={0}", MainClass.Debug); + DicConsole.DebugWriteLine("Device-Info command", "--debug={0}", debug); DicConsole.DebugWriteLine("Device-Info command", "--device={0}", devicePath); DicConsole.DebugWriteLine("Device-Info command", "--output-prefix={0}", outputPrefix); - DicConsole.DebugWriteLine("Device-Info command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Device-Info command", "--verbose={0}", verbose); if(devicePath.Length == 2 && devicePath[1] == ':' && @@ -932,7 +908,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("\tCan do challenge/response with Xbox discs"); if(devInfo.KreonFeatures.HasFlag(KreonFeatures.DecryptSs)) - DicConsole.WriteLine("\tCan read and descrypt SS from Xbox discs"); + DicConsole.WriteLine("\tCan read and decrypt SS from Xbox discs"); if(devInfo.KreonFeatures.HasFlag(KreonFeatures.XtremeUnlock)) DicConsole.WriteLine("\tCan set xtreme unlock state with Xbox discs"); @@ -944,7 +920,7 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("\tCan do challenge/response with Xbox 360 discs"); if(devInfo.KreonFeatures.HasFlag(KreonFeatures.DecryptSs360)) - DicConsole.WriteLine("\tCan read and descrypt SS from Xbox 360 discs"); + DicConsole.WriteLine("\tCan read and decrypt SS from Xbox 360 discs"); if(devInfo.KreonFeatures.HasFlag(KreonFeatures.XtremeUnlock360)) DicConsole.WriteLine("\tCan set xtreme unlock state with Xbox 360 discs"); diff --git a/DiscImageChef/Commands/DeviceReport.cs b/DiscImageChef/Commands/DeviceReport.cs index 6f435253f..854b07067 100644 --- a/DiscImageChef/Commands/DeviceReport.cs +++ b/DiscImageChef/Commands/DeviceReport.cs @@ -32,6 +32,8 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.IO; using System.Threading; using DiscImageChef.CommonTypes.Enums; @@ -44,9 +46,8 @@ using DiscImageChef.Database.Models; using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Devices; -using Mono.Options; using Newtonsoft.Json; -using Command = Mono.Options.Command; +using Command = System.CommandLine.Command; using Device = DiscImageChef.Devices.Device; using DeviceReport = DiscImageChef.Core.Devices.Report.DeviceReport; @@ -54,73 +55,44 @@ namespace DiscImageChef.Commands { internal class DeviceReportCommand : Command { - string _devicePath; - bool _showHelp; - public DeviceReportCommand() : base("device-report", - "Tests the device capabilities and creates an JSON report of them.") => - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} devicepath", "", - Help, - { - "help|h|?", "Show this message and exit.", v => _showHelp = v != null - } - }; - - public override int Invoke(IEnumerable arguments) + "Tests the device capabilities and creates an JSON report of them.") { - List extra = Options.Parse(arguments); - - if(_showHelp) + AddArgument(new Argument { - Options.WriteOptionDescriptions(CommandSet.Out); + Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path" + }); - return(int)ErrorNumber.HelpRequested; - } + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + } + static int Invoke(bool debug, bool verbose, string devicePath) + { MainClass.PrintCopyright(); - if(MainClass.Debug) + if(debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; Statistics.AddCommand("device-report"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); + DicConsole.DebugWriteLine("Device-Report command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Device-Report command", "--device={0}", devicePath); + DicConsole.DebugWriteLine("Device-Report command", "--verbose={0}", verbose); - return(int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing device path."); - - return(int)ErrorNumber.MissingArgument; - } - - _devicePath = extra[0]; - - DicConsole.DebugWriteLine("Device-Report command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Device-Report command", "--device={0}", _devicePath); - DicConsole.DebugWriteLine("Device-Report command", "--verbose={0}", MainClass.Verbose); - - if(_devicePath.Length == 2 && - _devicePath[1] == ':' && - _devicePath[0] != '/' && - char.IsLetter(_devicePath[0])) - _devicePath = "\\\\.\\" + char.ToUpper(_devicePath[0]) + ':'; + if(devicePath.Length == 2 && + devicePath[1] == ':' && + devicePath[0] != '/' && + char.IsLetter(devicePath[0])) + devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':'; Device dev; try { - dev = new Device(_devicePath); + dev = new Device(devicePath); if(dev.IsRemote) Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem, diff --git a/DiscImageChef/Commands/DumpMedia.cs b/DiscImageChef/Commands/DumpMedia.cs index be31248d5..ac7b9a8b1 100644 --- a/DiscImageChef/Commands/DumpMedia.cs +++ b/DiscImageChef/Commands/DumpMedia.cs @@ -32,6 +32,8 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.IO; using System.Linq; using System.Text; @@ -39,173 +41,195 @@ using System.Xml.Serialization; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; -using DiscImageChef.CommonTypes.Interop; using DiscImageChef.CommonTypes.Metadata; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Core.Devices.Dumping; using DiscImageChef.Core.Logging; using DiscImageChef.Devices; -using Mono.Options; using Schemas; -using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID; namespace DiscImageChef.Commands { // TODO: Add raw dumping internal class DumpMediaCommand : Command { - string _cicmXml; - string _devicePath; - bool _doResume = true; - string _encodingName; - bool _firstTrackPregap; - bool _fixOffset = true; - bool _force; - bool _noMetadata; - bool _noTrim; - string _outputFile; - string _outputOptions; - bool _persistent; - ushort _retryPasses = 5; - bool _showHelp; - int _skip = 512; - int _speed; - bool _stopOnError; - string _wantedOutputFormat; - string _wantedSubchannel; - public DumpMediaCommand() : base("dump-media", "Dumps the media inserted on a device to a media image.") { - Options = new OptionSet + Add(new Option(new[] + { + "--cicm-xml", "-x" + }, "Take metadata from existing CICM XML sidecar.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] + { + "--encoding", "-e" + }, "Name of character encoding to use.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option("--first-pregap", "Try to read first track pregap. Only applicable to CD/DDCD/GD.") { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] device_path output_image", - "", Help, + Argument = new Argument(() => false), Required = false + }); + + Add(new Option("--fix-offset", "Fix audio tracks offset. Only applicable to CD/GD.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] { - "cicm-xml|x=", "Take metadata from existing CICM XML sidecar.", s => _cicmXml = s - }, + "--force", "-f" + }, "Continue dump whatever happens.") { - "encoding|e=", "Name of character encoding to use.", s => _encodingName = s - } - }; + Argument = new Argument(() => false), Required = false + }); - if(DetectOS.GetRealPlatformID() != PlatformID.FreeBSD) - Options.Add("first-pregap", "Try to read first track pregap. Only applicable to CD/DDCD/GD.", - b => _firstTrackPregap = b != null); + Add(new Option(new[] + { + "--format", "-t" + }, + "Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.") + { + Argument = new Argument(() => null), Required = false + }); - Options.Add("fix-offset", "Fix audio tracks offset. Only applicable to CD/GD.", - b => _fixOffset = b != null); + Add(new Option("--no-metadata", "Disables creating CICM XML sidecar.") + { + Argument = new Argument(() => false), Required = false + }); - Options.Add("force|f", "Continue dump whatever happens.", b => _force = b != null); + Add(new Option("--no-trim", "Disables trimming errored from skipped sectors.") + { + Argument = new Argument(() => false), Required = false + }); - Options.Add("format|t=", - "Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.", - s => _wantedOutputFormat = s); + Add(new Option(new[] + { + "--options", "-O" + }, "Comma separated name=value pairs of options to pass to output image plugin.") + { + Argument = new Argument(() => null), Required = false + }); - Options.Add("no-metadata", "Disables creating CICM XML sidecar.", b => _noMetadata = b != null); - Options.Add("no-trim", "Disables trimming errored from skipped sectors.", b => _noTrim = b != null); + Add(new Option("--persistent", "Try to recover partial or incorrect data.") + { + Argument = new Argument(() => false), Required = false + }); - Options.Add("options|O=", "Comma separated name=value pairs of options to pass to output image plugin.", - s => _outputOptions = s); + Add(new Option(new[] + { + "--resume", "-r" + }, "Create/use resume mapfile.") + { + Argument = new Argument(() => true), Required = false + }); - Options.Add("persistent", "Try to recover partial or incorrect data.", b => _persistent = b != null); + Add(new Option(new[] + { + "--retry-passes", "-p" + }, "How many retry passes to do.") + { + Argument = new Argument(() => 5), Required = false + }); - Options.Add("resume|r", "Create/use resume mapfile.", b => _doResume = b != null); + Add(new Option(new[] + { + "--skip", "-k" + }, "When an unreadable sector is found skip this many sectors.") + { + Argument = new Argument(() => 512), Required = false + }); - Options.Add("retry-passes|p=", "How many retry passes to do.", (ushort us) => _retryPasses = us); - Options.Add("skip|k=", "When an unreadable sector is found skip this many sectors.", (int i) => _skip = i); + Add(new Option(new[] + { + "--stop-on-error", "-s" + }, "Stop media dump on first error.") + { + Argument = new Argument(() => false), Required = false + }); - Options.Add("stop-on-error|s", "Stop media dump on first error.", b => _stopOnError = b != null); + Add(new Option("--subchannel", + "Subchannel to dump. Only applicable to CD/GD. Values: any, rw, rw-or-pq, pq, none.") + { + Argument = new Argument(() => "any"), Required = false + }); - Options.Add("help|h|?", "Show this message and exit.", v => _showHelp = v != null); + Add(new Option("--speed", "Speed to dump. Only applicable to optical drives, 0 for maximum.") + { + Argument = new Argument(() => 0), Required = false + }); - Options.Add("subchannel", - "Subchannel to dump. Only applicable to CD/GD. Values: any, rw, rw-or-pq, pq, none", - s => _wantedSubchannel = s); + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path" + }); - Options.Add("speed", "Speed to dump. Only applicable to optical drives, 0 for maximum", - (int i) => _speed = i); + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Output image path", Name = "output-path" + }); - /* TODO: Disabled temporarily - Options.Add("raw|r", "Dump sectors with tags included. For optical media, dump scrambled sectors.", (b) => raw = b != null);*/ + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, string cicmXml, string devicePath, bool resume, string encoding, + bool firstTrackPregap, bool fixOffset, bool force, bool noMetadata, bool noTrim, + string outputPath, string options, bool persistent, ushort retryPasses, int skip, + int speed, bool stopOnError, string format, string subchannel) { - List extra = Options.Parse(arguments); - - if(_showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - - return(int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) + if(debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; Statistics.AddCommand("dump-media"); - if(extra.Count > 2) - { - DicConsole.ErrorWriteLine("Too many arguments."); - - return(int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count <= 1) - { - DicConsole.ErrorWriteLine("Missing paths."); - - return(int)ErrorNumber.MissingArgument; - } - - _devicePath = extra[0]; - _outputFile = extra[1]; - - DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", _cicmXml); - DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", _devicePath); - DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", _encodingName); - DicConsole.DebugWriteLine("Dump-Media command", "--first-pregap={0}", _firstTrackPregap); - DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", _force); - DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", _force); - DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", _wantedOutputFormat); - DicConsole.DebugWriteLine("Dump-Media command", "--no-metadata={0}", _noMetadata); - DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", Options); - DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", _outputFile); - DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", _persistent); - DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", _doResume); - DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", _retryPasses); - DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", _skip); - DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", _stopOnError); - DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose); - DicConsole.DebugWriteLine("Dump-Media command", "--subchannel={0}", _wantedSubchannel); + DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", cicmXml); + DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", devicePath); + DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", encoding); + DicConsole.DebugWriteLine("Dump-Media command", "--first-pregap={0}", firstTrackPregap); + DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", force); + DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", force); + DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", format); + DicConsole.DebugWriteLine("Dump-Media command", "--no-metadata={0}", noMetadata); + DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", options); + DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", outputPath); + DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", persistent); + DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", resume); + DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", retryPasses); + DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", skip); + DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", stopOnError); + DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", verbose); + DicConsole.DebugWriteLine("Dump-Media command", "--subchannel={0}", subchannel); // TODO: Disabled temporarily //DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw); - Dictionary parsedOptions = Core.Options.Parse(_outputOptions); + Dictionary parsedOptions = Core.Options.Parse(options); DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:"); foreach(KeyValuePair parsedOption in parsedOptions) DicConsole.DebugWriteLine("Dump-Media command", "{0} = {1}", parsedOption.Key, parsedOption.Value); - Encoding encoding = null; + Encoding encodingClass = null; - if(_encodingName != null) + if(encoding != null) try { - encoding = Claunia.Encoding.Encoding.GetEncoding(_encodingName); + encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding); - if(MainClass.Verbose) - DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); + if(verbose) + DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName); } catch(ArgumentException) { @@ -214,48 +238,48 @@ namespace DiscImageChef.Commands return(int)ErrorNumber.EncodingUnknown; } - DumpSubchannel subchannel = DumpSubchannel.Any; + DumpSubchannel wantedSubchannel = DumpSubchannel.Any; - switch(_wantedSubchannel?.ToLowerInvariant()) + switch(subchannel?.ToLowerInvariant()) { case"any": case null: - subchannel = DumpSubchannel.Any; + wantedSubchannel = DumpSubchannel.Any; break; case"rw": - subchannel = DumpSubchannel.Rw; + wantedSubchannel = DumpSubchannel.Rw; break; case"rw-or-pq": - subchannel = DumpSubchannel.RwOrPq; + wantedSubchannel = DumpSubchannel.RwOrPq; break; case"pq": - subchannel = DumpSubchannel.Pq; + wantedSubchannel = DumpSubchannel.Pq; break; case"none": - subchannel = DumpSubchannel.None; + wantedSubchannel = DumpSubchannel.None; break; default: - DicConsole.WriteLine("Incorrect subchannel type \"{0}\" requested.", _wantedSubchannel); + DicConsole.WriteLine("Incorrect subchannel type \"{0}\" requested.", subchannel); break; } - if(_devicePath.Length == 2 && - _devicePath[1] == ':' && - _devicePath[0] != '/' && - char.IsLetter(_devicePath[0])) - _devicePath = "\\\\.\\" + char.ToUpper(_devicePath[0]) + ':'; + if(devicePath.Length == 2 && + devicePath[1] == ':' && + devicePath[0] != '/' && + char.IsLetter(devicePath[0])) + devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':'; Device dev; try { - dev = new Device(_devicePath); + dev = new Device(devicePath); if(dev.IsRemote) Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem, @@ -277,17 +301,17 @@ namespace DiscImageChef.Commands Statistics.AddDevice(dev); - string outputPrefix = Path.Combine(Path.GetDirectoryName(_outputFile), - Path.GetFileNameWithoutExtension(_outputFile)); + string outputPrefix = Path.Combine(Path.GetDirectoryName(outputPath), + Path.GetFileNameWithoutExtension(outputPath)); - Resume resume = null; - var xs = new XmlSerializer(typeof(Resume)); + Resume resumeClass = null; + var xs = new XmlSerializer(typeof(Resume)); - if(File.Exists(outputPrefix + ".resume.xml") && _doResume) + if(File.Exists(outputPrefix + ".resume.xml") && resume) try { var sr = new StreamReader(outputPrefix + ".resume.xml"); - resume = (Resume)xs.Deserialize(sr); + resumeClass = (Resume)xs.Deserialize(sr); sr.Close(); } catch @@ -297,10 +321,10 @@ namespace DiscImageChef.Commands return(int)ErrorNumber.InvalidResume; } - if(resume != null && - resume.NextBlock > resume.LastBlock && - resume.BadBlocks.Count == 0 && - !resume.Tape) + if(resumeClass != null && + resumeClass.NextBlock > resumeClass.LastBlock && + resumeClass.BadBlocks.Count == 0 && + !resumeClass.Tape) { DicConsole.WriteLine("Media already dumped correctly, not continuing..."); @@ -310,12 +334,12 @@ namespace DiscImageChef.Commands CICMMetadataType sidecar = null; var sidecarXs = new XmlSerializer(typeof(CICMMetadataType)); - if(_cicmXml != null) - if(File.Exists(_cicmXml)) + if(cicmXml != null) + if(File.Exists(cicmXml)) { try { - var sr = new StreamReader(_cicmXml); + var sr = new StreamReader(cicmXml); sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr); sr.Close(); } @@ -337,19 +361,18 @@ namespace DiscImageChef.Commands List candidates = new List(); // Try extension - if(string.IsNullOrEmpty(_wantedOutputFormat)) + if(string.IsNullOrEmpty(format)) candidates.AddRange(plugins.WritableImages.Values.Where(t => t.KnownExtensions. - Contains(Path. - GetExtension(_outputFile)))); + Contains(Path.GetExtension(outputPath)))); // Try Id - else if(Guid.TryParse(_wantedOutputFormat, out Guid outId)) + else if(Guid.TryParse(format, out Guid outId)) candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId))); // Try name else - candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, _wantedOutputFormat, + candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, format, StringComparison. InvariantCultureIgnoreCase))); @@ -371,7 +394,7 @@ namespace DiscImageChef.Commands var dumpLog = new DumpLog(outputPrefix + ".log", dev); - if(MainClass.Verbose) + if(verbose) { dumpLog.WriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id); DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id); @@ -382,10 +405,10 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name); } - var dumper = new Dump(_doResume, dev, _devicePath, outputFormat, _retryPasses, _force, false, _persistent, - _stopOnError, resume, dumpLog, encoding, outputPrefix, _outputFile, parsedOptions, - sidecar, (uint)_skip, _noMetadata, _noTrim, _firstTrackPregap, _fixOffset, - MainClass.Debug, subchannel, _speed); + var dumper = new Dump(resume, dev, devicePath, outputFormat, retryPasses, force, false, persistent, + stopOnError, resumeClass, dumpLog, encodingClass, outputPrefix, outputPath, + parsedOptions, sidecar, (uint)skip, noMetadata, noTrim, firstTrackPregap, fixOffset, + debug, wantedSubchannel, speed); dumper.UpdateStatus += Progress.UpdateStatus; dumper.ErrorMessage += Progress.ErrorMessage; diff --git a/DiscImageChef/Commands/Entropy.cs b/DiscImageChef/Commands/Entropy.cs index 27c0b4666..7187e1ae7 100644 --- a/DiscImageChef/Commands/Entropy.cs +++ b/DiscImageChef/Commands/Entropy.cs @@ -30,92 +30,80 @@ // Copyright © 2011-2019 Natalia Portillo // ****************************************************************************/ -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class EntropyCommand : Command + internal class EntropyCommand : Command { - bool duplicatedSectors = true; - string inputFile; - bool separatedTracks = true; - - bool showHelp; - bool wholeDisc = true; - public EntropyCommand() : base("entropy", "Calculates entropy and/or duplicated sectors of an image.") { - Options = new OptionSet + Add(new Option(new[] + { + "--duplicated-sectors", "-p" + }, "Calculates how many sectors are duplicated (have same exact data in user area).") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--separated-tracks", "-t" + }, "Calculates entropy for each track separately.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--whole-disc", "-w" + }, "Calculates entropy for the whole disc.") + { + Argument = new Argument(() => true), Required = false + }); + + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] imagefile", - "", - Help, - { - "duplicated-sectors|p", - "Calculates how many sectors are duplicated (have same exact data in user area).", - b => duplicatedSectors = b != null - }, - { - "separated-tracks|t", "Calculates entropy for each track separately.", - b => separatedTracks = b != null - }, - {"whole-disc|w", "Calculates entropy for the whole disc.", b => wholeDisc = b != null}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, bool duplicatedSectors, string imagePath, bool separatedTracks, + bool wholeDisc) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("entropy"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - - DicConsole.DebugWriteLine("Entropy command", "--debug={0}", MainClass.Debug); + DicConsole.DebugWriteLine("Entropy command", "--debug={0}", debug); DicConsole.DebugWriteLine("Entropy command", "--duplicated-sectors={0}", duplicatedSectors); - DicConsole.DebugWriteLine("Entropy command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Entropy command", "--separated-tracks={0}", separatedTracks); - DicConsole.DebugWriteLine("Entropy command", "--verbose={0}", MainClass.Verbose); - DicConsole.DebugWriteLine("Entropy command", "--whole-disc={0}", wholeDisc); + DicConsole.DebugWriteLine("Entropy command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Entropy command", "--separated-tracks={0}", separatedTracks); + DicConsole.DebugWriteLine("Entropy command", "--verbose={0}", verbose); + DicConsole.DebugWriteLine("Entropy command", "--whole-disc={0}", wholeDisc); - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } IMediaImage inputFormat = ImageFormat.Detect(inputFilter); @@ -123,7 +111,8 @@ namespace DiscImageChef.Commands if(inputFormat == null) { DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming"); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } inputFormat.Open(inputFilter); @@ -131,7 +120,7 @@ namespace DiscImageChef.Commands Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddFilter(inputFilter.Name); - Entropy entropyCalculator = new Entropy(MainClass.Debug, MainClass.Verbose, inputFormat); + var entropyCalculator = new Entropy(debug, verbose, inputFormat); entropyCalculator.InitProgressEvent += Progress.InitProgress; entropyCalculator.InitProgress2Event += Progress.InitProgress2; entropyCalculator.UpdateProgressEvent += Progress.UpdateProgress; @@ -142,9 +131,11 @@ namespace DiscImageChef.Commands if(separatedTracks) { EntropyResults[] tracksEntropy = entropyCalculator.CalculateTracksEntropy(duplicatedSectors); + foreach(EntropyResults trackEntropy in tracksEntropy) { DicConsole.WriteLine("Entropy for track {0} is {1:F4}.", trackEntropy.Track, trackEntropy.Entropy); + if(trackEntropy.UniqueSectors != null) DicConsole.WriteLine("Track {0} has {1} unique sectors ({2:P3})", trackEntropy.Track, trackEntropy.UniqueSectors, @@ -152,16 +143,18 @@ namespace DiscImageChef.Commands } } - if(!wholeDisc) return (int)ErrorNumber.NoError; + if(!wholeDisc) + return(int)ErrorNumber.NoError; EntropyResults entropy = entropyCalculator.CalculateMediaEntropy(duplicatedSectors); DicConsole.WriteLine("Entropy for disk is {0:F4}.", entropy.Entropy); + if(entropy.UniqueSectors != null) DicConsole.WriteLine("Disk has {0} unique sectors ({1:P3})", entropy.UniqueSectors, (double)entropy.UniqueSectors / (double)entropy.Sectors); - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/ExtractFiles.cs b/DiscImageChef/Commands/ExtractFiles.cs index 2c4bd2155..272ae9a5c 100644 --- a/DiscImageChef/Commands/ExtractFiles.cs +++ b/DiscImageChef/Commands/ExtractFiles.cs @@ -32,6 +32,8 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.IO; using System.Text; using DiscImageChef.CommonTypes; @@ -40,110 +42,115 @@ using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; using FileAttributes = DiscImageChef.CommonTypes.Structs.FileAttributes; namespace DiscImageChef.Commands { - class ExtractFilesCommand : Command + internal class ExtractFilesCommand : Command { - string encodingName; - bool extractXattrs; - string inputFile; - string @namespace; - string outputDir; - string pluginOptions; - bool showHelp; - public ExtractFilesCommand() : base("extract-files", "Extracts all files in disc image.") { - Options = new OptionSet + Add(new Option(new[] + { + "--encoding", "-e" + }, "Name of character encoding to use.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] + { + "--options", "-O" + }, "Comma separated name=value pairs of options to pass to filesystem plugin.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] + { + "--xattrs", "-x" + }, "Extract extended attributes if present.") + { + Argument = new Argument(() => false), Required = false + }); + + Add(new Option(new[] + { + "--namespace", "-n" + }, "Namespace to use for filenames.") + { + Argument = new Argument(() => null), Required = false + }); + + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] imagefile", - "", - Help, - {"encoding|e=", "Name of character encoding to use.", s => encodingName = s}, - { - "options|O=", "Comma separated name=value pairs of options to pass to filesystem plugin.", - s => pluginOptions = s - }, - { - "output|o=", "Directory where extracted files will be created. Will abort if it exists.", - s => outputDir = s - }, - {"xattrs|x", "Extract extended attributes if present.", b => extractXattrs = b != null}, - {"namespace|n=", "Namespace to use for filenames.", s => @namespace = s}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "Disc image path", Name = "image-path" + }); + + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, + Description = "Directory where extracted files will be created. Will abort if it exists", + Name = "output-dir" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, string encoding, bool xattrs, string imagePath, string @namespace, + string outputDir, string options) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("extract-files"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + DicConsole.DebugWriteLine("Extract-Files command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Extract-Files command", "--encoding={0}", encoding); + DicConsole.DebugWriteLine("Extract-Files command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Extract-Files command", "--options={0}", options); + DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", outputDir); + DicConsole.DebugWriteLine("Extract-Files command", "--verbose={0}", verbose); + DicConsole.DebugWriteLine("Extract-Files command", "--xattrs={0}", xattrs); - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); - inputFile = extra[0]; - - DicConsole.DebugWriteLine("Extract-Files command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Extract-Files command", "--encoding={0}", encodingName); - DicConsole.DebugWriteLine("Extract-Files command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Extract-Files command", "--options={0}", pluginOptions); - DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", outputDir); - DicConsole.DebugWriteLine("Extract-Files command", "--verbose={0}", MainClass.Verbose); - DicConsole.DebugWriteLine("Extract-Files command", "--xattrs={0}", extractXattrs); - - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); - - Dictionary parsedOptions = Core.Options.Parse(pluginOptions); + Dictionary parsedOptions = Core.Options.Parse(options); DicConsole.DebugWriteLine("Extract-Files command", "Parsed options:"); + foreach(KeyValuePair parsedOption in parsedOptions) DicConsole.DebugWriteLine("Extract-Files command", "{0} = {1}", parsedOption.Key, parsedOption.Value); - parsedOptions.Add("debug", MainClass.Debug.ToString()); + + parsedOptions.Add("debug", debug.ToString()); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } - Encoding encoding = null; + Encoding encodingClass = null; - if(encodingName != null) + if(encoding != null) try { - encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); + encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding); + + if(verbose) + DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName); } catch(ArgumentException) { DicConsole.ErrorWriteLine("Specified encoding is not supported."); - return (int)ErrorNumber.EncodingUnknown; + + return(int)ErrorNumber.EncodingUnknown; } PluginBase plugins = GetPluginBase.Instance; @@ -155,24 +162,29 @@ namespace DiscImageChef.Commands if(imageFormat == null) { DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); - else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); + else + DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); - if (outputDir == null) + if(outputDir == null) { DicConsole.WriteLine("Output directory missing."); - return (int)ErrorNumber.MissingArgument; + + return(int)ErrorNumber.MissingArgument; } - if(Directory.Exists(outputDir) || File.Exists(outputDir)) + if(Directory.Exists(outputDir) || + File.Exists(outputDir)) { DicConsole.ErrorWriteLine("Destination exists, aborting."); - return (int)ErrorNumber.DestinationExists; + + return(int)ErrorNumber.DestinationExists; } Directory.CreateDirectory(outputDir); @@ -183,14 +195,18 @@ namespace DiscImageChef.Commands { DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("No error given"); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } DicConsole.DebugWriteLine("Extract-Files command", "Correctly opened image file."); + DicConsole.DebugWriteLine("Extract-Files command", "Image without headers is {0} bytes.", imageFormat.Info.ImageSize); + DicConsole.DebugWriteLine("Extract-Files command", "Image has {0} sectors.", imageFormat.Info.Sectors); + DicConsole.DebugWriteLine("Extract-Files command", "Image identifies disk type as {0}.", imageFormat.Info.MediaType); @@ -202,7 +218,8 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Error: {0}", ex.Message); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } List partitions = Core.Partitions.GetAll(imageFormat); @@ -211,7 +228,9 @@ namespace DiscImageChef.Commands List idPlugins; IReadOnlyFilesystem plugin; Errno error; - if(partitions.Count == 0) DicConsole.DebugWriteLine("Extract-Files command", "No partitions found"); + + if(partitions.Count == 0) + DicConsole.DebugWriteLine("Extract-Files command", "No partitions found"); else { DicConsole.WriteLine("{0} partitions found.", partitions.Count); @@ -224,7 +243,9 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Identifying filesystem on partition"); Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]); - if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified"); + + if(idPlugins.Count == 0) + DicConsole.WriteLine("Filesystem not identified"); else if(idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); @@ -233,20 +254,22 @@ namespace DiscImageChef.Commands if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin - .GetType() - .GetConstructor(Type.EmptyTypes) - ?.Invoke(new object[] { }); - error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace); + var fs = (IReadOnlyFilesystem)plugin. + GetType().GetConstructor(Type.EmptyTypes)?. + Invoke(new object[] + { }); + + error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, + @namespace); + if(error == Errno.NoError) { string volumeName = - string.IsNullOrEmpty(fs.XmlFsType.VolumeName) - ? "NO NAME" + string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" : fs.XmlFsType.VolumeName; - ExtractFilesInDir("/", fs, volumeName); + ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs); Statistics.AddFilesystem(fs.XmlFsType.Type); } @@ -259,34 +282,38 @@ namespace DiscImageChef.Commands { plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin); DicConsole.WriteLine($"Identified by {plugin.Name}."); - IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin - .GetType().GetConstructor(Type.EmptyTypes) - ?.Invoke(new object[] { }); - error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace); + + var fs = (IReadOnlyFilesystem)plugin. + GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + { }); + + error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace); + if(error == Errno.NoError) { - string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) - ? "NO NAME" + string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" : fs.XmlFsType.VolumeName; - ExtractFilesInDir("/", fs, volumeName); + ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs); Statistics.AddFilesystem(fs.XmlFsType.Type); } - else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); + else + DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } - Partition wholePart = new Partition + var wholePart = new Partition { - Name = "Whole device", - Length = imageFormat.Info.Sectors, - Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize + Name = "Whole device", Length = imageFormat.Info.Sectors, + Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); - if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified"); + + if(idPlugins.Count == 0) + DicConsole.WriteLine("Filesystem not identified"); else if(idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); @@ -295,67 +322,79 @@ namespace DiscImageChef.Commands if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin - .GetType().GetConstructor(Type.EmptyTypes) - ?.Invoke(new object[] { }); - error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace); + + var fs = (IReadOnlyFilesystem)plugin. + GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + { }); + + error = fs.Mount(imageFormat, wholePart, encodingClass, parsedOptions, @namespace); + if(error == Errno.NoError) { - string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) - ? "NO NAME" + string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" : fs.XmlFsType.VolumeName; - ExtractFilesInDir("/", fs, volumeName); + ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs); Statistics.AddFilesystem(fs.XmlFsType.Type); } - else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); + else + DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } else { plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin); DicConsole.WriteLine($"Identified by {plugin.Name}."); - IReadOnlyFilesystem fs = - (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); - error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace); + + var fs = (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + { }); + + error = fs.Mount(imageFormat, wholePart, encodingClass, parsedOptions, @namespace); + if(error == Errno.NoError) { - string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) - ? "NO NAME" + string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" : fs.XmlFsType.VolumeName; - ExtractFilesInDir("/", fs, volumeName); + ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs); Statistics.AddFilesystem(fs.XmlFsType.Type); } - else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); + else + DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } catch(Exception ex) { DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}"); DicConsole.DebugWriteLine("Extract-Files command", ex.StackTrace); - return (int)ErrorNumber.UnexpectedException; + + return(int)ErrorNumber.UnexpectedException; } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } - void ExtractFilesInDir(string path, IReadOnlyFilesystem fs, string volumeName) + static void ExtractFilesInDir(string path, IReadOnlyFilesystem fs, string volumeName, string outputDir, + bool doXattrs) { - if(path.StartsWith("/")) path = path.Substring(1); + if(path.StartsWith("/")) + path = path.Substring(1); Errno error = fs.ReadDir(path, out List directory); + if(error != Errno.NoError) { DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); + return; } foreach(string entry in directory) { error = fs.Stat(path + "/" + entry, out FileEntryInfo stat); + if(error == Errno.NoError) { string outputPath; @@ -370,14 +409,15 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Created subdirectory at {0}", outputPath); - ExtractFilesInDir(path + "/" + entry, fs, volumeName); + ExtractFilesInDir(path + "/" + entry, fs, volumeName, outputDir, doXattrs); - DirectoryInfo di = new DirectoryInfo(outputPath); + var di = new DirectoryInfo(outputPath); #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body try { - if(stat.CreationTimeUtc.HasValue) di.CreationTimeUtc = stat.CreationTimeUtc.Value; + if(stat.CreationTimeUtc.HasValue) + di.CreationTimeUtc = stat.CreationTimeUtc.Value; } catch { @@ -386,7 +426,8 @@ namespace DiscImageChef.Commands try { - if(stat.LastWriteTimeUtc.HasValue) di.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value; + if(stat.LastWriteTimeUtc.HasValue) + di.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value; } catch { @@ -395,7 +436,8 @@ namespace DiscImageChef.Commands try { - if(stat.AccessTimeUtc.HasValue) di.LastAccessTimeUtc = stat.AccessTimeUtc.Value; + if(stat.AccessTimeUtc.HasValue) + di.LastAccessTimeUtc = stat.AccessTimeUtc.Value; } catch { @@ -407,15 +449,19 @@ namespace DiscImageChef.Commands } FileStream outputFile; - if(extractXattrs) + + if(doXattrs) { error = fs.ListXAttr(path + "/" + entry, out List xattrs); + if(error == Errno.NoError) foreach(string xattr in xattrs) { byte[] xattrBuf = new byte[0]; error = fs.GetXattr(path + "/" + entry, xattr, ref xattrBuf); - if(error != Errno.NoError) continue; + + if(error != Errno.NoError) + continue; Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, ".xattrs", xattr)); @@ -427,9 +473,10 @@ namespace DiscImageChef.Commands { outputFile = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None); + outputFile.Write(xattrBuf, 0, xattrBuf.Length); outputFile.Close(); - FileInfo fi = new FileInfo(outputPath); + var fi = new FileInfo(outputPath); #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body try { @@ -453,7 +500,8 @@ namespace DiscImageChef.Commands try { - if(stat.AccessTimeUtc.HasValue) fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value; + if(stat.AccessTimeUtc.HasValue) + fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value; } catch { @@ -483,13 +531,15 @@ namespace DiscImageChef.Commands { outputFile = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None); + outputFile.Write(outBuf, 0, outBuf.Length); outputFile.Close(); - FileInfo fi = new FileInfo(outputPath); + var fi = new FileInfo(outputPath); #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body try { - if(stat.CreationTimeUtc.HasValue) fi.CreationTimeUtc = stat.CreationTimeUtc.Value; + if(stat.CreationTimeUtc.HasValue) + fi.CreationTimeUtc = stat.CreationTimeUtc.Value; } catch { @@ -498,7 +548,8 @@ namespace DiscImageChef.Commands try { - if(stat.LastWriteTimeUtc.HasValue) fi.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value; + if(stat.LastWriteTimeUtc.HasValue) + fi.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value; } catch { @@ -507,7 +558,8 @@ namespace DiscImageChef.Commands try { - if(stat.AccessTimeUtc.HasValue) fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value; + if(stat.AccessTimeUtc.HasValue) + fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value; } catch { @@ -517,12 +569,15 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Written {0} bytes of file {1} to {2}", outBuf.Length, entry, outputPath); } - else DicConsole.ErrorWriteLine("Error {0} reading file {1}", error, entry); + else + DicConsole.ErrorWriteLine("Error {0} reading file {1}", error, entry); } - else DicConsole.ErrorWriteLine("Cannot write file {0}, output exists", entry); + else + DicConsole.ErrorWriteLine("Cannot write file {0}, output exists", entry); } - else DicConsole.ErrorWriteLine("Error reading file {0}", entry); + else + DicConsole.ErrorWriteLine("Error reading file {0}", entry); } } } -} +} \ No newline at end of file diff --git a/DiscImageChef/Commands/Formats.cs b/DiscImageChef/Commands/Formats.cs index e2c834a22..a787d7e81 100644 --- a/DiscImageChef/Commands/Formats.cs +++ b/DiscImageChef/Commands/Formats.cs @@ -31,6 +31,8 @@ // ****************************************************************************/ using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.Linq; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; @@ -38,123 +40,121 @@ using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Partitions; -using Mono.Options; namespace DiscImageChef.Commands { - class FormatsCommand : Command + internal class FormatsCommand : Command { - bool showHelp; - public FormatsCommand() : base("formats", - "Lists all supported disc images, partition schemes and file systems.") + "Lists all supported disc images, partition schemes and file systems.") => + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + + static int Invoke(bool verbose, bool debug) { - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name}", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; - } - - public override int Invoke(IEnumerable arguments) - { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("formats"); - if(extra.Count > 0) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + DicConsole.DebugWriteLine("Formats command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Formats command", "--verbose={0}", verbose); - DicConsole.DebugWriteLine("Formats command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Formats command", "--verbose={0}", MainClass.Verbose); - - PluginBase plugins = GetPluginBase.Instance; - FiltersList filtersList = new FiltersList(); + PluginBase plugins = GetPluginBase.Instance; + var filtersList = new FiltersList(); DicConsole.WriteLine("Supported filters ({0}):", filtersList.Filters.Count); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tFilter"); + + if(verbose) + DicConsole.VerboseWriteLine("GUID\t\t\t\t\tFilter"); + foreach(KeyValuePair kvp in filtersList.Filters) - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(); + DicConsole.WriteLine("Read-only media image formats ({0}):", - plugins.ImagePluginsList.Count(t => !t.Value.GetType().GetInterfaces() - .Contains(typeof(IWritableImage)))); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); - foreach(KeyValuePair kvp in plugins.ImagePluginsList.Where(t => !t.Value.GetType() - .GetInterfaces() - .Contains(typeof( + plugins.ImagePluginsList.Count(t => !t.Value.GetType().GetInterfaces(). + Contains(typeof(IWritableImage)))); + + if(verbose) + DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); + + foreach(KeyValuePair kvp in plugins.ImagePluginsList.Where(t => !t.Value.GetType(). + GetInterfaces(). + Contains(typeof( IWritableImage )))) - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(); DicConsole.WriteLine("Read/write media image formats ({0}):", plugins.WritableImages.Count); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); + + if(verbose) + DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); + foreach(KeyValuePair kvp in plugins.WritableImages) - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(); + DicConsole.WriteLine("Supported filesystems for identification and information only ({0}):", - plugins.PluginsList.Count(t => !t.Value.GetType().GetInterfaces() - .Contains(typeof(IReadOnlyFilesystem)))); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); - foreach(KeyValuePair kvp in plugins.PluginsList.Where(t => !t.Value.GetType() - .GetInterfaces() - .Contains(typeof( + plugins.PluginsList.Count(t => !t.Value.GetType().GetInterfaces(). + Contains(typeof(IReadOnlyFilesystem)))); + + if(verbose) + DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); + + foreach(KeyValuePair kvp in plugins.PluginsList.Where(t => !t.Value.GetType(). + GetInterfaces(). + Contains(typeof( IReadOnlyFilesystem )))) - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(); + DicConsole.WriteLine("Supported filesystems that can read their contents ({0}):", plugins.ReadOnlyFilesystems.Count); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); + + if(verbose) + DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); + foreach(KeyValuePair kvp in plugins.ReadOnlyFilesystems) - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(); DicConsole.WriteLine("Supported partitioning schemes ({0}):", plugins.PartPluginsList.Count); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); + + if(verbose) + DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); + foreach(KeyValuePair kvp in plugins.PartPluginsList) - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); else DicConsole.WriteLine(kvp.Value.Name); - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/ImageInfo.cs b/DiscImageChef/Commands/ImageInfo.cs index 14640584b..0f2eabcfa 100644 --- a/DiscImageChef/Commands/ImageInfo.cs +++ b/DiscImageChef/Commands/ImageInfo.cs @@ -31,77 +31,53 @@ // ****************************************************************************/ using System; -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class ImageInfoCommand : Command + internal class ImageInfoCommand : Command { - string inputFile; - - bool showHelp; - public ImageInfoCommand() : base("image-info", "Opens a media image and shows information about the media it represents and metadata.") { - Options = new OptionSet + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} imagefile", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, string imagePath) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("image-info"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + DicConsole.DebugWriteLine("Analyze command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Analyze command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose); - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - - DicConsole.DebugWriteLine("Analyze command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose); - - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } try @@ -111,7 +87,8 @@ namespace DiscImageChef.Commands if(imageFormat == null) { DicConsole.WriteLine("Image format not identified."); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } DicConsole.WriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); @@ -123,7 +100,8 @@ namespace DiscImageChef.Commands { DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("No error given"); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } ImageInfo.PrintImageInfo(imageFormat); @@ -137,17 +115,19 @@ namespace DiscImageChef.Commands DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Error: {0}", ex.Message); DicConsole.DebugWriteLine("Image-info command", "Stack trace: {0}", ex.StackTrace); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } } catch(Exception ex) { DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}"); DicConsole.DebugWriteLine("Image-info command", ex.StackTrace); - return (int)ErrorNumber.UnexpectedException; + + return(int)ErrorNumber.UnexpectedException; } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/ListDevices.cs b/DiscImageChef/Commands/ListDevices.cs index f615029fe..3a979a467 100644 --- a/DiscImageChef/Commands/ListDevices.cs +++ b/DiscImageChef/Commands/ListDevices.cs @@ -30,70 +30,47 @@ // Copyright © 2011-2019 Natalia Portillo // ****************************************************************************/ -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.Linq; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Devices; -using Mono.Options; namespace DiscImageChef.Commands { internal class ListDevicesCommand : Command { - bool showHelp; - - public ListDevicesCommand() : base("list-devices", "Lists all connected devices.") => Options = new OptionSet + public ListDevicesCommand() : base("list-devices", "Lists all connected devices.") { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [dic-remote-host]", "", - Help, + AddArgument(new Argument { - "help|h|?", "Show this message and exit.", v => showHelp = v != null - } - }; + Arity = ArgumentArity.ZeroOrOne, Description = "dicremote host", Name = "dic-remote-host" + }); - public override int Invoke(IEnumerable arguments) + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + } + + static int Invoke(bool debug, bool verbose, string dicRemoteHost) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - - return(int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) + if(debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; Statistics.AddCommand("list-devices"); - string dicRemote = null; - - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - - return(int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 1) - dicRemote = extra[0]; - - DicConsole.DebugWriteLine("List-Devices command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("List-Devices command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("List-Devices command", "--debug={0}", debug); + DicConsole.DebugWriteLine("List-Devices command", "--verbose={0}", verbose); DeviceInfo[] devices = Device.ListDevices(out bool isRemote, out string serverApplication, out string serverVersion, out string serverOperatingSystem, out string serverOperatingSystemVersion, - out string serverArchitecture, dicRemote); + out string serverArchitecture, dicRemoteHost); if(isRemote) { @@ -110,7 +87,7 @@ namespace DiscImageChef.Commands { devices = devices.OrderBy(d => d.Path).ToArray(); - if(dicRemote is null) + if(dicRemoteHost is null) { DicConsole.WriteLine("{0,-22}|{1,-16}|{2,-24}|{3,-24}|{4,-10}|{5,-10}", "Path", "Vendor", "Model", "Serial", "Bus", "Supported?"); diff --git a/DiscImageChef/Commands/ListEncodings.cs b/DiscImageChef/Commands/ListEncodings.cs index 192ccff9b..9d9c6044b 100644 --- a/DiscImageChef/Commands/ListEncodings.cs +++ b/DiscImageChef/Commands/ListEncodings.cs @@ -31,76 +31,52 @@ // ****************************************************************************/ using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.Linq; using System.Text; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class ListEncodingsCommand : Command + internal class ListEncodingsCommand : Command { - bool showHelp; + public ListEncodingsCommand() : base("list-encodings", "Lists all supported text encodings and code pages.") => + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); - public ListEncodingsCommand() : base("list-encodings", "Lists all supported text encodings and code pages.") + static int Invoke(bool debug, bool verbose) { - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name}", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; - } - - public override int Invoke(IEnumerable arguments) - { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("list-encodings"); - if(extra.Count > 0) + DicConsole.DebugWriteLine("List-Encodings command", "--debug={0}", debug); + DicConsole.DebugWriteLine("List-Encodings command", "--verbose={0}", verbose); + + List encodings = Encoding.GetEncodings().Select(info => new CommonEncodingInfo { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + Name = info.Name, DisplayName = info.GetEncoding().EncodingName + }).ToList(); - DicConsole.DebugWriteLine("List-Encodings command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("List-Encodings command", "--verbose={0}", MainClass.Verbose); - - List encodings = Encoding - .GetEncodings().Select(info => new CommonEncodingInfo - { - Name = info.Name, - DisplayName = - info.GetEncoding().EncodingName - }).ToList(); - encodings.AddRange(Claunia.Encoding.Encoding.GetEncodings() - .Select(info => new CommonEncodingInfo - { - Name = info.Name, DisplayName = info.DisplayName - })); + encodings.AddRange(Claunia.Encoding.Encoding.GetEncodings().Select(info => new CommonEncodingInfo + { + Name = info.Name, DisplayName = info.DisplayName + })); DicConsole.WriteLine("{0,-16} {1,-8}", "Name", "Description"); foreach(CommonEncodingInfo info in encodings.OrderBy(t => t.DisplayName)) DicConsole.WriteLine("{0,-16} {1,-8}", info.Name, info.DisplayName); - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } struct CommonEncodingInfo diff --git a/DiscImageChef/Commands/ListNamespaces.cs b/DiscImageChef/Commands/ListNamespaces.cs index 1d09a5bcc..bc9438e40 100644 --- a/DiscImageChef/Commands/ListNamespaces.cs +++ b/DiscImageChef/Commands/ListNamespaces.cs @@ -31,73 +31,54 @@ // ****************************************************************************/ using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.Linq; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class ListNamespacesCommand : Command + internal class ListNamespacesCommand : Command { - bool showHelp; - public ListNamespacesCommand() : base("list-namespaces", - "Lists all namespaces supported by read-only filesystems.") + "Lists all namespaces supported by read-only filesystems.") => + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + + static int Invoke(bool debug, bool verbose) { - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name}", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; - } - - public override int Invoke(IEnumerable arguments) - { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - if(extra.Count > 0) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - DicConsole.DebugWriteLine("List-Namespaces command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("List-Namespaces command", "--verbose={0}", MainClass.Verbose); + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + DicConsole.DebugWriteLine("List-Namespaces command", "--debug={0}", debug); + DicConsole.DebugWriteLine("List-Namespaces command", "--verbose={0}", verbose); Statistics.AddCommand("list-namespaces"); PluginBase plugins = GetPluginBase.Instance; foreach(KeyValuePair kvp in plugins.ReadOnlyFilesystems) { - if(kvp.Value.Namespaces is null) continue; + if(kvp.Value.Namespaces is null) + continue; - DicConsole.WriteLine("\tNamespaces for {0}:", kvp.Value.Name); + DicConsole.WriteLine("\tNamespaces for {0}:", kvp.Value.Name); DicConsole.WriteLine("\t\t{0,-16} {1,-16}", "Namespace", "Description"); + foreach(KeyValuePair @namespace in kvp.Value.Namespaces.OrderBy(t => t.Key)) DicConsole.WriteLine("\t\t{0,-16} {1,-16}", @namespace.Key, @namespace.Value); + DicConsole.WriteLine(); } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/ListOptions.cs b/DiscImageChef/Commands/ListOptions.cs index dc9973a72..cf0fdf724 100644 --- a/DiscImageChef/Commands/ListOptions.cs +++ b/DiscImageChef/Commands/ListOptions.cs @@ -32,109 +32,107 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.Linq; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class ListOptionsCommand : Command + internal class ListOptionsCommand : Command { - bool showHelp; - public ListOptionsCommand() : base("list-options", - "Lists all options supported by read-only filesystems and writable media images.") + "Lists all options supported by read-only filesystems and writable media images.") => + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + + static int Invoke(bool debug, bool verbose) { - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name}", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; - } - - public override int Invoke(IEnumerable arguments) - { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - if(extra.Count > 0) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - DicConsole.DebugWriteLine("List-Options command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("List-Options command", "--verbose={0}", MainClass.Verbose); + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + DicConsole.DebugWriteLine("List-Options command", "--debug={0}", debug); + DicConsole.DebugWriteLine("List-Options command", "--verbose={0}", verbose); Statistics.AddCommand("list-options"); PluginBase plugins = GetPluginBase.Instance; DicConsole.WriteLine("Read-only filesystems options:"); + foreach(KeyValuePair kvp in plugins.ReadOnlyFilesystems) { List<(string name, Type type, string description)> options = kvp.Value.SupportedOptions.ToList(); - if(options.Count == 0) continue; - DicConsole.WriteLine("\tOptions for {0}:", kvp.Value.Name); + if(options.Count == 0) + continue; + + DicConsole.WriteLine("\tOptions for {0}:", kvp.Value.Name); DicConsole.WriteLine("\t\t{0,-16} {1,-16} {2,-8}", "Name", "Type", "Description"); + foreach((string name, Type type, string description) option in options.OrderBy(t => t.name)) DicConsole.WriteLine("\t\t{0,-16} {1,-16} {2,-8}", option.name, TypeToString(option.type), option.description); + DicConsole.WriteLine(); } DicConsole.WriteLine(); DicConsole.WriteLine("Read/Write media images options:"); + foreach(KeyValuePair kvp in plugins.WritableImages) { List<(string name, Type type, string description, object @default)> options = kvp.Value.SupportedOptions.ToList(); - if(options.Count == 0) continue; - DicConsole.WriteLine("\tOptions for {0}:", kvp.Value.Name); + if(options.Count == 0) + continue; + + DicConsole.WriteLine("\tOptions for {0}:", kvp.Value.Name); DicConsole.WriteLine("\t\t{0,-20} {1,-10} {2,-12} {3,-8}", "Name", "Type", "Default", "Description"); + foreach((string name, Type type, string description, object @default) option in options.OrderBy(t => t.name)) DicConsole.WriteLine("\t\t{0,-20} {1,-10} {2,-12} {3,-8}", option.name, TypeToString(option.type), option.@default, option.description); + DicConsole.WriteLine(); } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } static string TypeToString(Type type) { - if(type == typeof(bool)) return "boolean"; + if(type == typeof(bool)) + return"boolean"; - if(type == typeof(sbyte) || type == typeof(short) || type == typeof(int) || type == typeof(long)) - return "signed number"; + if(type == typeof(sbyte) || + type == typeof(short) || + type == typeof(int) || + type == typeof(long)) + return"signed number"; - if(type == typeof(byte) || type == typeof(ushort) || type == typeof(uint) || type == typeof(ulong)) - return "number"; + if(type == typeof(byte) || + type == typeof(ushort) || + type == typeof(uint) || + type == typeof(ulong)) + return"number"; - if(type == typeof(float) || type == typeof(double)) return "float number"; + if(type == typeof(float) || + type == typeof(double)) + return"float number"; - if(type == typeof(Guid)) return "uuid"; + if(type == typeof(Guid)) + return"uuid"; return type == typeof(string) ? "string" : type.ToString(); } diff --git a/DiscImageChef/Commands/Ls.cs b/DiscImageChef/Commands/Ls.cs index e20001b53..b094611d2 100644 --- a/DiscImageChef/Commands/Ls.cs +++ b/DiscImageChef/Commands/Ls.cs @@ -32,6 +32,8 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using System.Linq; using System.Text; using DiscImageChef.CommonTypes; @@ -40,102 +42,104 @@ using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class LsCommand : Command + internal class LsCommand : Command { - string encodingName; - string inputFile; - bool longFormat; - string @namespace; - string pluginOptions; - bool showHelp; - public LsCommand() : base("ls", "Lists files in disc image.") { - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] imagefile", - "", - Help, - {"encoding|e=", "Name of character encoding to use.", s => encodingName = s}, - {"long|l", "Uses long format.", b => longFormat = b != null}, + Add(new Option(new[] { - "options|O=", "Comma separated name=value pairs of options to pass to filesystem plugin.", - s => pluginOptions = s - }, - {"namespace|n=", "Namespace to use for filenames.", s => @namespace = s}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + "--encoding", "-e" + }, "Name of character encoding to use.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] + { + "--long-format", "-l" + }, "Uses long format.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--options", "-O" + }, "Comma separated name=value pairs of options to pass to filesystem plugin.") + { + Argument = new Argument(() => null), Required = false + }); + + Add(new Option(new[] + { + "--namespace", "-n" + }, "Namespace to use for filenames.") + { + Argument = new Argument(() => null), Required = false + }); + + AddArgument(new Argument + { + Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, string encoding, string imagePath, bool longFormat, + string @namespace, string options) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - inputFile = extra[0]; - - DicConsole.DebugWriteLine("Ls command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Ls command", "--encoding={0}", encodingName); - DicConsole.DebugWriteLine("Ls command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Ls command", "--options={0}", pluginOptions); - DicConsole.DebugWriteLine("Ls command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Ls command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Ls command", "--encoding={0}", encoding); + DicConsole.DebugWriteLine("Ls command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Ls command", "--options={0}", options); + DicConsole.DebugWriteLine("Ls command", "--verbose={0}", verbose); Statistics.AddCommand("ls"); - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); - Dictionary parsedOptions = Core.Options.Parse(pluginOptions); + Dictionary parsedOptions = Core.Options.Parse(options); DicConsole.DebugWriteLine("Ls command", "Parsed options:"); + foreach(KeyValuePair parsedOption in parsedOptions) DicConsole.DebugWriteLine("Ls command", "{0} = {1}", parsedOption.Key, parsedOption.Value); - parsedOptions.Add("debug", MainClass.Debug.ToString()); + + parsedOptions.Add("debug", debug.ToString()); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } - Encoding encoding = null; + Encoding encodingClass = null; - if(encodingName != null) + if(encoding != null) try { - encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName); - if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); + encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding); + + if(verbose) + DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName); } catch(ArgumentException) { DicConsole.ErrorWriteLine("Specified encoding is not supported."); - return (int)ErrorNumber.EncodingUnknown; + + return(int)ErrorNumber.EncodingUnknown; } PluginBase plugins = GetPluginBase.Instance; @@ -147,13 +151,15 @@ namespace DiscImageChef.Commands if(imageFormat == null) { DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); - else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); + else + DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); try { @@ -161,13 +167,17 @@ namespace DiscImageChef.Commands { DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("No error given"); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } DicConsole.DebugWriteLine("Ls command", "Correctly opened image file."); + DicConsole.DebugWriteLine("Ls command", "Image without headers is {0} bytes.", imageFormat.Info.ImageSize); + DicConsole.DebugWriteLine("Ls command", "Image has {0} sectors.", imageFormat.Info.Sectors); + DicConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.", imageFormat.Info.MediaType); @@ -179,7 +189,8 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Error: {0}", ex.Message); - return (int)ErrorNumber.CannotOpenFormat; + + return(int)ErrorNumber.CannotOpenFormat; } List partitions = Core.Partitions.GetAll(imageFormat); @@ -188,7 +199,9 @@ namespace DiscImageChef.Commands List idPlugins; IReadOnlyFilesystem plugin; Errno error; - if(partitions.Count == 0) DicConsole.DebugWriteLine("Ls command", "No partitions found"); + + if(partitions.Count == 0) + DicConsole.DebugWriteLine("Ls command", "No partitions found"); else { DicConsole.WriteLine("{0} partitions found.", partitions.Count); @@ -201,7 +214,9 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Identifying filesystem on partition"); Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]); - if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified"); + + if(idPlugins.Count == 0) + DicConsole.WriteLine("Filesystem not identified"); else if(idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); @@ -210,17 +225,21 @@ namespace DiscImageChef.Commands if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin - .GetType() - .GetConstructor(Type.EmptyTypes) - ?.Invoke(new object[] { }); - if(fs == null) continue; + var fs = (IReadOnlyFilesystem)plugin. + GetType().GetConstructor(Type.EmptyTypes)?. + Invoke(new object[] + { }); + + if(fs == null) + continue; + + error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, + @namespace); - error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace); if(error == Errno.NoError) { - ListFilesInDir("/", fs); + ListFilesInDir("/", fs, longFormat); Statistics.AddFilesystem(fs.XmlFsType.Type); } @@ -232,35 +251,43 @@ namespace DiscImageChef.Commands else { plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin); - if(plugin == null) continue; + + if(plugin == null) + continue; DicConsole.WriteLine($"Identified by {plugin.Name}."); - IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin - .GetType().GetConstructor(Type.EmptyTypes) - ?.Invoke(new object[] { }); - if(fs == null) continue; - error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace); + var fs = (IReadOnlyFilesystem)plugin. + GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + { }); + + if(fs == null) + continue; + + error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace); + if(error == Errno.NoError) { - ListFilesInDir("/", fs); + ListFilesInDir("/", fs, longFormat); Statistics.AddFilesystem(fs.XmlFsType.Type); } - else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); + else + DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } - Partition wholePart = new Partition + var wholePart = new Partition { - Name = "Whole device", - Length = imageFormat.Info.Sectors, - Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize + Name = "Whole device", Length = imageFormat.Info.Sectors, + Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); - if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified"); + + if(idPlugins.Count == 0) + DicConsole.WriteLine("Filesystem not identified"); else if(idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); @@ -269,40 +296,50 @@ namespace DiscImageChef.Commands if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); - IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin - .GetType().GetConstructor(Type.EmptyTypes) - ?.Invoke(new object[] { }); - if(fs == null) continue; - error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace); + var fs = (IReadOnlyFilesystem)plugin. + GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + { }); + + if(fs == null) + continue; + + error = fs.Mount(imageFormat, wholePart, encodingClass, parsedOptions, @namespace); + if(error == Errno.NoError) { - ListFilesInDir("/", fs); + ListFilesInDir("/", fs, longFormat); Statistics.AddFilesystem(fs.XmlFsType.Type); } - else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); + else + DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } else { plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin); + if(plugin != null) { DicConsole.WriteLine($"Identified by {plugin.Name}."); - IReadOnlyFilesystem fs = - (IReadOnlyFilesystem)plugin - .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); + + var fs = (IReadOnlyFilesystem)plugin. + GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + { }); + if(fs != null) { - error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace); + error = fs.Mount(imageFormat, wholePart, encodingClass, parsedOptions, @namespace); + if(error == Errno.NoError) { - ListFilesInDir("/", fs); + ListFilesInDir("/", fs, longFormat); Statistics.AddFilesystem(fs.XmlFsType.Type); } - else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); + else + DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } @@ -311,15 +348,17 @@ namespace DiscImageChef.Commands { DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}"); DicConsole.DebugWriteLine("Ls command", ex.StackTrace); - return (int)ErrorNumber.UnexpectedException; + + return(int)ErrorNumber.UnexpectedException; } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } - void ListFilesInDir(string path, IReadOnlyFilesystem fs) + static void ListFilesInDir(string path, IReadOnlyFilesystem fs, bool longFormat) { - if(path.StartsWith("/")) path = path.Substring(1); + if(path.StartsWith("/")) + path = path.Substring(1); DicConsole.WriteLine(string.IsNullOrEmpty(path) ? "Root directory" : $"Directory: {path}"); @@ -328,6 +367,7 @@ namespace DiscImageChef.Commands if(error != Errno.NoError) { DicConsole.ErrorWriteLine("Error {0} reading root directory {1}", error.ToString(), path); + return; } @@ -335,7 +375,7 @@ namespace DiscImageChef.Commands foreach(string entry in directory) { - error = fs.Stat(path + "/" + entry, out FileEntryInfo stat); + fs.Stat(path + "/" + entry, out FileEntryInfo stat); stats.Add(entry, stat); } @@ -355,30 +395,36 @@ namespace DiscImageChef.Commands entry.Key); error = fs.ListXAttr(path + "/" + entry.Key, out List xattrs); - if(error != Errno.NoError) continue; + + if(error != Errno.NoError) + continue; foreach(string xattr in xattrs) { byte[] xattrBuf = new byte[0]; error = fs.GetXattr(path + "/" + entry.Key, xattr, ref xattrBuf); + if(error == Errno.NoError) DicConsole.WriteLine("\t\t{0}\t{1:##,#}", xattr, xattrBuf.Length); } } - else DicConsole.WriteLine("{0, 47}{1}", string.Empty, entry.Key); + else + DicConsole.WriteLine("{0, 47}{1}", string.Empty, entry.Key); } else { - if(entry.Value != null && entry.Value.Attributes.HasFlag(FileAttributes.Directory)) + if(entry.Value != null && + entry.Value.Attributes.HasFlag(FileAttributes.Directory)) DicConsole.WriteLine("{0}/", entry.Key); - else DicConsole.WriteLine("{0}", entry.Key); + else + DicConsole.WriteLine("{0}", entry.Key); } DicConsole.WriteLine(); foreach(KeyValuePair subdirectory in stats.Where(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == true)) - ListFilesInDir(path + "/" + subdirectory.Key, fs); + ListFilesInDir(path + "/" + subdirectory.Key, fs, longFormat); } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/MediaInfo.cs b/DiscImageChef/Commands/MediaInfo.cs index 96314bd27..403ece911 100644 --- a/DiscImageChef/Commands/MediaInfo.cs +++ b/DiscImageChef/Commands/MediaInfo.cs @@ -32,6 +32,8 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Core; @@ -44,7 +46,6 @@ using DiscImageChef.Decoders.SCSI.MMC; using DiscImageChef.Decoders.SCSI.SSC; using DiscImageChef.Decoders.Xbox; using DiscImageChef.Devices; -using Mono.Options; using BCA = DiscImageChef.Decoders.Bluray.BCA; using Cartridge = DiscImageChef.Decoders.DVD.Cartridge; using DDS = DiscImageChef.Decoders.DVD.DDS; @@ -55,65 +56,40 @@ namespace DiscImageChef.Commands { internal class MediaInfoCommand : Command { - string devicePath; - string outputPrefix; - bool showHelp; - - public MediaInfoCommand() : base("media-info", "Gets information about the media inserted on a device.") => - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] devicepath", "", - Help, - { - "output-prefix|w=", "Write binary responses from device with that prefix.", s => outputPrefix = s - }, - { - "help|h|?", "Show this message and exit.", v => showHelp = v != null - } - }; - - public override int Invoke(IEnumerable arguments) + public MediaInfoCommand() : base("media-info", "Gets information about the media inserted on a device.") { - List extra = Options.Parse(arguments); + Add(new Option(new[] + { + "--output-prefix", "-w" + }, "Write binary responses from device with that prefix.") + { + Argument = new Argument(() => null), Required = false + }); - if(showHelp) + AddArgument(new Argument { - Options.WriteOptionDescriptions(CommandSet.Out); + Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path" + }); - return(int)ErrorNumber.HelpRequested; - } + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + } + static int Invoke(bool debug, bool verbose, string devicePath, string outputPrefix) + { MainClass.PrintCopyright(); - if(MainClass.Debug) + if(debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; Statistics.AddCommand("media-info"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - - return(int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing device path."); - - return(int)ErrorNumber.MissingArgument; - } - - devicePath = extra[0]; - - DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", MainClass.Debug); + DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", debug); DicConsole.DebugWriteLine("Media-Info command", "--device={0}", devicePath); DicConsole.DebugWriteLine("Media-Info command", "--output-prefix={0}", outputPrefix); - DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", verbose); if(devicePath.Length == 2 && devicePath[1] == ':' && diff --git a/DiscImageChef/Commands/MediaScan.cs b/DiscImageChef/Commands/MediaScan.cs index 3cf251f27..5c0db2541 100644 --- a/DiscImageChef/Commands/MediaScan.cs +++ b/DiscImageChef/Commands/MediaScan.cs @@ -30,82 +30,61 @@ // Copyright © 2011-2019 Natalia Portillo // ****************************************************************************/ -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Core.Devices.Scanning; using DiscImageChef.Devices; -using Mono.Options; namespace DiscImageChef.Commands { internal class MediaScanCommand : Command { - string devicePath; - string ibgLogPath; - string mhddLogPath; - bool showHelp; - - public MediaScanCommand() : base("media-scan", "Scans the media inserted on a device.") => - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] devicepath", "", - Help, - { - "mhdd-log|mw=", "Write a log of the scan in the format used by MHDD.", s => mhddLogPath = s - }, - { - "ibg-log|b=", "Write a log of the scan in the format used by ImgBurn.", s => ibgLogPath = s - }, - { - "help|h|?", "Show this message and exit.", v => showHelp = v != null - } - }; - - public override int Invoke(IEnumerable arguments) + public MediaScanCommand() : base("media-scan", "Scans the media inserted on a device.") { - List extra = Options.Parse(arguments); + Add(new Option(new[] + { + "--mhdd-log", "-m" + }, "Write a log of the scan in the format used by MHDD.") + { + Argument = new Argument(() => null), Required = false + }); - if(showHelp) + Add(new Option(new[] + { + "--ibg-log", "-b" + }, "Write a log of the scan in the format used by ImgBurn.") + { + Argument = new Argument(() => true), Required = false + }); + + AddArgument(new Argument { - Options.WriteOptionDescriptions(CommandSet.Out); + Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path" + }); - return(int)ErrorNumber.HelpRequested; - } + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + } + static int Invoke(bool debug, bool verbose, string devicePath, string ibgLog, string mhddLog) + { MainClass.PrintCopyright(); - if(MainClass.Debug) + if(debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; Statistics.AddCommand("media-scan"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - - return(int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing device path."); - - return(int)ErrorNumber.MissingArgument; - } - - devicePath = extra[0]; - - DicConsole.DebugWriteLine("Media-Scan command", "--debug={0}", MainClass.Debug); + DicConsole.DebugWriteLine("Media-Scan command", "--debug={0}", debug); DicConsole.DebugWriteLine("Media-Scan command", "--device={0}", devicePath); - DicConsole.DebugWriteLine("Media-Scan command", "--ibg-log={0}", ibgLogPath); - DicConsole.DebugWriteLine("Media-Scan command", "--mhdd-log={0}", mhddLogPath); - DicConsole.DebugWriteLine("Media-Scan command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Media-Scan command", "--ibg-log={0}", ibgLog); + DicConsole.DebugWriteLine("Media-Scan command", "--mhdd-log={0}", mhddLog); + DicConsole.DebugWriteLine("Media-Scan command", "--verbose={0}", verbose); if(devicePath.Length == 2 && devicePath[1] == ':' && @@ -139,7 +118,7 @@ namespace DiscImageChef.Commands Statistics.AddDevice(dev); - var scanner = new MediaScan(mhddLogPath, ibgLogPath, devicePath, dev); + var scanner = new MediaScan(mhddLog, ibgLog, devicePath, dev); scanner.UpdateStatus += Progress.UpdateStatus; scanner.StoppingErrorMessage += Progress.ErrorMessage; scanner.UpdateProgress += Progress.UpdateProgress; @@ -177,9 +156,13 @@ namespace DiscImageChef.Commands DicConsole.WriteLine(); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator + + // ReSharper disable CompareOfFloatsByEqualityOperator if(results.SeekTotal != 0 || results.SeekMin != double.MaxValue || results.SeekMax != double.MinValue) + + // ReSharper restore CompareOfFloatsByEqualityOperator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator DicConsole.WriteLine("Testing {0} seeks, longest seek took {1:F3} ms, fastest one took {2:F3} ms. ({3:F3} ms average)", results.SeekTimes, results.SeekMax, results.SeekMin, results.SeekTotal / 1000); diff --git a/DiscImageChef/Commands/PrintHex.cs b/DiscImageChef/Commands/PrintHex.cs index 7d31a3d03..395a588b0 100644 --- a/DiscImageChef/Commands/PrintHex.cs +++ b/DiscImageChef/Commands/PrintHex.cs @@ -30,93 +30,89 @@ // Copyright © 2011-2019 Natalia Portillo // ****************************************************************************/ -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class PrintHexCommand : Command + internal class PrintHexCommand : Command { - string inputFile; - ulong length = 1; - bool longSectors; - bool showHelp; - ulong? startSector; - ushort widthBytes = 32; - public PrintHexCommand() : base("printhex", "Prints a sector, in hexadecimal values, to the console.") { - Options = new OptionSet + Add(new Option(new[] + { + "--length", "-l" + }, "How many sectors to print.") + { + Argument = new Argument(() => 1), Required = false + }); + + Add(new Option(new[] + { + "--long-sectors", "-r" + }, "Print sectors with tags included.") + { + Argument = new Argument(() => false), Required = false + }); + + Add(new Option(new[] + { + "--start", "-s" + }, "Starting sector.") + { + Argument = new Argument(), Required = true + }); + + Add(new Option(new[] + { + "--width", "-w" + }, "How many bytes to print per line.") + { + Argument = new Argument(() => 32), Required = false + }); + + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] imagefile", - "", - Help, - {"length|l=", "How many sectors to print.", (ulong ul) => length = ul}, - {"long-sectors|r", "Print sectors with tags included.", b => longSectors = b != null}, - {"start|s=", "Name of character encoding to use.", (ulong ul) => startSector = ul}, - {"width|w=", "How many bytes to print per line.", (ushort us) => widthBytes = us}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, string imagePath, ulong length, bool longSectors, ulong startSector, + ushort widthBytes) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("print-hex"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - if(startSector is null) - { - DicConsole.ErrorWriteLine("Missing starting sector."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - - DicConsole.DebugWriteLine("PrintHex command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("PrintHex command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("PrintHex command", "--length={0}", length); + DicConsole.DebugWriteLine("PrintHex command", "--debug={0}", debug); + DicConsole.DebugWriteLine("PrintHex command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("PrintHex command", "--length={0}", length); DicConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", longSectors); - DicConsole.DebugWriteLine("PrintHex command", "--start={0}", startSector); - DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", MainClass.Verbose); - DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", widthBytes); + DicConsole.DebugWriteLine("PrintHex command", "--start={0}", startSector); + DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", verbose); + DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", widthBytes); - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } IMediaImage inputFormat = ImageFormat.Detect(inputFilter); @@ -124,7 +120,8 @@ namespace DiscImageChef.Commands if(inputFormat == null) { DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying"); - return (int)ErrorNumber.UnrecognizedFormat; + + return(int)ErrorNumber.UnrecognizedFormat; } inputFormat.Open(inputFilter); @@ -135,28 +132,29 @@ namespace DiscImageChef.Commands if(inputFormat.Info.ReadableSectorTags == null) { - DicConsole - .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); + DicConsole. + WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); + longSectors = false; } else { if(inputFormat.Info.ReadableSectorTags.Count == 0) { - DicConsole - .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); + DicConsole. + WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); + longSectors = false; } } - byte[] sector = longSectors - ? inputFormat.ReadSectorLong(startSector.Value + i) - : inputFormat.ReadSector(startSector.Value + i); + byte[] sector = longSectors ? inputFormat.ReadSectorLong(startSector + i) + : inputFormat.ReadSector(startSector + i); PrintHex.PrintHexArray(sector, widthBytes); } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/Remote.cs b/DiscImageChef/Commands/Remote.cs index 6afc1dce4..2734f1a06 100644 --- a/DiscImageChef/Commands/Remote.cs +++ b/DiscImageChef/Commands/Remote.cs @@ -33,71 +33,42 @@ // TODO: Fix errors returned using System; -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; using Remote = DiscImageChef.Devices.Remote.Remote; namespace DiscImageChef.Commands { internal class RemoteCommand : Command { - string host; - bool showHelp; - - public RemoteCommand() : base("remote", "Tests connection to a DiscImageChef Remote Server.") => - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] host", "", - Help, - { - "help|h|?", "Show this message and exit.", v => showHelp = v != null - } - }; - - public override int Invoke(IEnumerable arguments) + public RemoteCommand() : base("remote", "Tests connection to a DiscImageChef Remote Server.") { - List extra = Options.Parse(arguments); - - if(showHelp) + AddArgument(new Argument { - Options.WriteOptionDescriptions(CommandSet.Out); + Arity = ArgumentArity.ExactlyOne, Description = "dicremote host", Name = "host" + }); - return(int)ErrorNumber.HelpRequested; - } + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + } + static int Invoke(bool debug, bool verbose, string host) + { MainClass.PrintCopyright(); - if(MainClass.Debug) + if(debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) + if(verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - // Statistics.AddCommand("remote"); + Statistics.AddCommand("remote"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - - return(int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - - return(int)ErrorNumber.MissingArgument; - } - - host = extra[0]; - - DicConsole.DebugWriteLine("Remote command", "--debug={0}", MainClass.Debug); + DicConsole.DebugWriteLine("Remote command", "--debug={0}", debug); DicConsole.DebugWriteLine("Remote command", "--host={0}", host); - DicConsole.DebugWriteLine("Remote command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Remote command", "--verbose={0}", verbose); try { diff --git a/DiscImageChef/Commands/Statistics.cs b/DiscImageChef/Commands/Statistics.cs index a4b0146e8..ff1ed9f56 100644 --- a/DiscImageChef/Commands/Statistics.cs +++ b/DiscImageChef/Commands/Statistics.cs @@ -30,62 +30,44 @@ // Copyright © 2011-2019 Natalia Portillo // ****************************************************************************/ -using System.Collections.Generic; +using System.CommandLine.Invocation; using System.Linq; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Database; using DiscImageChef.Database.Models; -using Mono.Options; -using Command = Mono.Options.Command; +using Command = System.CommandLine.Command; namespace DiscImageChef.Commands { - class StatisticsCommand : Command + internal class StatisticsCommand : Command { - bool showHelp; + public StatisticsCommand() : base("stats", "Shows statistics.") => + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); - public StatisticsCommand() : base("stats", "Shows statistics.") + static int Invoke(bool debug, bool verbose) { - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name}", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; - } - - public override int Invoke(IEnumerable arguments) - { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - if(extra.Count > 0) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - DicContext ctx = DicContext.Create(Settings.Settings.LocalDbPath); + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - if(!ctx.Commands.Any() && !ctx.Filesystems.Any() && !ctx.Filters.Any() && !ctx.MediaFormats.Any() && - !ctx.Medias.Any() && !ctx.Partitions.Any() && !ctx.SeenDevices.Any()) + var ctx = DicContext.Create(Settings.Settings.LocalDbPath); + + if(!ctx.Commands.Any() && + !ctx.Filesystems.Any() && + !ctx.Filters.Any() && + !ctx.MediaFormats.Any() && + !ctx.Medias.Any() && + !ctx.Partitions.Any() && + !ctx.SeenDevices.Any()) { DicConsole.WriteLine("There are no statistics."); - return (int)ErrorNumber.NothingFound; + + return(int)ErrorNumber.NothingFound; } bool thereAreStats = false; @@ -97,11 +79,13 @@ namespace DiscImageChef.Commands foreach(string command in ctx.Commands.OrderBy(c => c.Name).Select(c => c.Name).Distinct()) { - ulong count = ctx.Commands.Where(c => c.Name == command && c.Synchronized).Select(c => c.Count) - .FirstOrDefault(); + ulong count = ctx.Commands.Where(c => c.Name == command && c.Synchronized).Select(c => c.Count). + FirstOrDefault(); + count += (ulong)ctx.Commands.LongCount(c => c.Name == command && !c.Synchronized); - if(count == 0) continue; + if(count == 0) + continue; DicConsole.WriteLine("You have called the {0} command {1} times.", command, count); thereAreStats = true; @@ -117,11 +101,13 @@ namespace DiscImageChef.Commands foreach(string filter in ctx.Filters.OrderBy(c => c.Name).Select(c => c.Name).Distinct()) { - ulong count = ctx.Filters.Where(c => c.Name == filter && c.Synchronized).Select(c => c.Count) - .FirstOrDefault(); + ulong count = ctx.Filters.Where(c => c.Name == filter && c.Synchronized).Select(c => c.Count). + FirstOrDefault(); + count += (ulong)ctx.Filters.LongCount(c => c.Name == filter && !c.Synchronized); - if(count == 0) continue; + if(count == 0) + continue; DicConsole.WriteLine("Filter {0} has been found {1} times.", filter, count); thereAreStats = true; @@ -137,11 +123,13 @@ namespace DiscImageChef.Commands foreach(string format in ctx.MediaFormats.OrderBy(c => c.Name).Select(c => c.Name).Distinct()) { - ulong count = ctx.MediaFormats.Where(c => c.Name == format && c.Synchronized).Select(c => c.Count) - .FirstOrDefault(); + ulong count = ctx.MediaFormats.Where(c => c.Name == format && c.Synchronized).Select(c => c.Count). + FirstOrDefault(); + count += (ulong)ctx.MediaFormats.LongCount(c => c.Name == format && !c.Synchronized); - if(count == 0) continue; + if(count == 0) + continue; DicConsole.WriteLine("Format {0} has been found {1} times.", format, count); thereAreStats = true; @@ -157,11 +145,13 @@ namespace DiscImageChef.Commands foreach(string partition in ctx.Partitions.OrderBy(c => c.Name).Select(c => c.Name).Distinct()) { - ulong count = ctx.Partitions.Where(c => c.Name == partition && c.Synchronized).Select(c => c.Count) - .FirstOrDefault(); + ulong count = ctx.Partitions.Where(c => c.Name == partition && c.Synchronized).Select(c => c.Count). + FirstOrDefault(); + count += (ulong)ctx.Partitions.LongCount(c => c.Name == partition && !c.Synchronized); - if(count == 0) continue; + if(count == 0) + continue; DicConsole.WriteLine("Partitioning scheme {0} has been found {1} times.", partition, count); thereAreStats = true; @@ -177,11 +167,13 @@ namespace DiscImageChef.Commands foreach(string filesystem in ctx.Filesystems.OrderBy(c => c.Name).Select(c => c.Name).Distinct()) { - ulong count = ctx.Filesystems.Where(c => c.Name == filesystem && c.Synchronized) - .Select(c => c.Count).FirstOrDefault(); + ulong count = ctx.Filesystems.Where(c => c.Name == filesystem && c.Synchronized). + Select(c => c.Count).FirstOrDefault(); + count += (ulong)ctx.Filesystems.LongCount(c => c.Name == filesystem && !c.Synchronized); - if(count == 0) continue; + if(count == 0) + continue; DicConsole.WriteLine("Filesystem {0} has been found {1} times.", filesystem, count); thereAreStats = true; @@ -195,10 +187,10 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Device statistics"); DicConsole.WriteLine("================="); - foreach(DeviceStat ds in ctx.SeenDevices.OrderBy(ds => ds.Manufacturer).ThenBy(ds => ds.Model) - .ThenBy(ds => ds.Revision).ThenBy(ds => ds.Bus)) - DicConsole - .WriteLine("Device model {0}, manufactured by {1}, with revision {2} and attached via {3}.", + foreach(DeviceStat ds in ctx.SeenDevices.OrderBy(ds => ds.Manufacturer).ThenBy(ds => ds.Model). + ThenBy(ds => ds.Revision).ThenBy(ds => ds.Bus)) + DicConsole. + WriteLine("Device model {0}, manufactured by {1}, with revision {2} and attached via {3}.", ds.Model, ds.Manufacturer, ds.Revision, ds.Bus); DicConsole.WriteLine(); @@ -212,8 +204,9 @@ namespace DiscImageChef.Commands foreach(string media in ctx.Medias.OrderBy(ms => ms.Type).Select(ms => ms.Type).Distinct()) { - ulong count = ctx.Medias.Where(c => c.Type == media && c.Synchronized && c.Real) - .Select(c => c.Count).FirstOrDefault(); + ulong count = ctx.Medias.Where(c => c.Type == media && c.Synchronized && c.Real). + Select(c => c.Count).FirstOrDefault(); + count += (ulong)ctx.Medias.LongCount(c => c.Type == media && !c.Synchronized && c.Real); if(count > 0) @@ -222,11 +215,13 @@ namespace DiscImageChef.Commands thereAreStats = true; } - count = ctx.Medias.Where(c => c.Type == media && c.Synchronized && !c.Real).Select(c => c.Count) - .FirstOrDefault(); + count = ctx.Medias.Where(c => c.Type == media && c.Synchronized && !c.Real).Select(c => c.Count). + FirstOrDefault(); + count += (ulong)ctx.Medias.LongCount(c => c.Type == media && !c.Synchronized && !c.Real); - if(count == 0) continue; + if(count == 0) + continue; DicConsole.WriteLine("Media type {0} has been found {1} times in a media image.", media, count); thereAreStats = true; @@ -235,8 +230,10 @@ namespace DiscImageChef.Commands DicConsole.WriteLine(); } - if(!thereAreStats) DicConsole.WriteLine("There are no statistics."); - return (int)ErrorNumber.NoError; + if(!thereAreStats) + DicConsole.WriteLine("There are no statistics."); + + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/Commands/Update.cs b/DiscImageChef/Commands/Update.cs index b344da9cb..92071e441 100644 --- a/DiscImageChef/Commands/Update.cs +++ b/DiscImageChef/Commands/Update.cs @@ -30,62 +30,44 @@ // Copyright © 2011-2019 Natalia Portillo // ****************************************************************************/ -using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class UpdateCommand : Command + internal class UpdateCommand : Command { - readonly bool masterDbUpdate; - bool showHelp; + readonly bool _masterDbUpdate; public UpdateCommand(bool masterDbUpdate) : base("update", "Updates the database.") { - this.masterDbUpdate = masterDbUpdate; - Options = new OptionSet - { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name}", - "", - Help, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + _masterDbUpdate = masterDbUpdate; + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + int Invoke(bool debug, bool verbose) { - if(masterDbUpdate) return (int)ErrorNumber.NoError; - - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } + if(_masterDbUpdate) + return(int)ErrorNumber.NoError; MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; - if(extra.Count > 0) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - DicConsole.DebugWriteLine("Update command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Update command", "--verbose={0}", MainClass.Verbose); + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + DicConsole.DebugWriteLine("Update command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Update command", "--verbose={0}", verbose); DoUpdate(false); - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } internal static void DoUpdate(bool create) diff --git a/DiscImageChef/Commands/Verify.cs b/DiscImageChef/Commands/Verify.cs index e8903a973..30693ab9a 100644 --- a/DiscImageChef/Commands/Verify.cs +++ b/DiscImageChef/Commands/Verify.cs @@ -32,81 +32,71 @@ using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; using DiscImageChef.Core; -using Mono.Options; namespace DiscImageChef.Commands { - class VerifyCommand : Command + internal class VerifyCommand : Command { - string inputFile; - bool showHelp; - bool verifyDisc = true; - bool verifySectors = true; - public VerifyCommand() : base("verify", "Verifies a disc image integrity, and if supported, sector integrity.") { - Options = new OptionSet + Add(new Option(new[] + { + "--verify-disc", "-w" + }, "Verify disc image if supported.") + { + Argument = new Argument(() => true), Required = false + }); + + Add(new Option(new[] + { + "--verify-sectors", "-s" + }, "Verify all sectors if supported.") + { + Argument = new Argument(() => true), Required = false + }); + + AddArgument(new Argument { - $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}", - $"{MainClass.AssemblyCopyright}", - "", - $"usage: DiscImageChef {Name} [OPTIONS] imagefile", - "", - Help, - {"verify-disc|w", "Verify disc image if supported.", b => verifyDisc = b != null}, - {"verify-sectors|s", "Verify all sectors if supported.", b => verifySectors = b != null}, - {"help|h|?", "Show this message and exit.", v => showHelp = v != null} - }; + Arity = ArgumentArity.ExactlyOne, Description = "Disc image path", Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } - public override int Invoke(IEnumerable arguments) + static int Invoke(bool debug, bool verbose, string imagePath, bool verifyDisc = true, bool verifySectors = true) { - List extra = Options.Parse(arguments); - - if(showHelp) - { - Options.WriteOptionDescriptions(CommandSet.Out); - return (int)ErrorNumber.HelpRequested; - } - MainClass.PrintCopyright(); - if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; - if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + + if(debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + + if(verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + Statistics.AddCommand("verify"); - if(extra.Count > 1) - { - DicConsole.ErrorWriteLine("Too many arguments."); - return (int)ErrorNumber.UnexpectedArgumentCount; - } - - if(extra.Count == 0) - { - DicConsole.ErrorWriteLine("Missing input image."); - return (int)ErrorNumber.MissingArgument; - } - - inputFile = extra[0]; - - DicConsole.DebugWriteLine("Verify command", "--debug={0}", MainClass.Debug); - DicConsole.DebugWriteLine("Verify command", "--input={0}", inputFile); - DicConsole.DebugWriteLine("Verify command", "--verbose={0}", MainClass.Verbose); - DicConsole.DebugWriteLine("Verify command", "--verify-disc={0}", verifyDisc); + DicConsole.DebugWriteLine("Verify command", "--debug={0}", debug); + DicConsole.DebugWriteLine("Verify command", "--input={0}", imagePath); + DicConsole.DebugWriteLine("Verify command", "--verbose={0}", verbose); + DicConsole.DebugWriteLine("Verify command", "--verify-disc={0}", verifyDisc); DicConsole.DebugWriteLine("Verify command", "--verify-sectors={0}", verifySectors); - FiltersList filtersList = new FiltersList(); - IFilter inputFilter = filtersList.GetFilter(inputFile); + var filtersList = new FiltersList(); + IFilter inputFilter = filtersList.GetFilter(imagePath); if(inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); - return (int)ErrorNumber.CannotOpenFile; + + return(int)ErrorNumber.CannotOpenFile; } IMediaImage inputFormat = ImageFormat.Detect(inputFilter); @@ -114,7 +104,8 @@ namespace DiscImageChef.Commands if(inputFormat == null) { DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying"); - return (int)ErrorNumber.FormatNotFound; + + return(int)ErrorNumber.FormatNotFound; } inputFormat.Open(inputFilter); @@ -123,18 +114,19 @@ namespace DiscImageChef.Commands Statistics.AddFilter(inputFilter.Name); bool? correctImage = null; - long totalSectors = 0; long errorSectors = 0; bool? correctSectors = null; long unknownSectors = 0; - IVerifiableImage verifiableImage = inputFormat as IVerifiableImage; - IVerifiableSectorsImage verifiableSectorsImage = inputFormat as IVerifiableSectorsImage; + var verifiableImage = inputFormat as IVerifiableImage; + var verifiableSectorsImage = inputFormat as IVerifiableSectorsImage; - if(verifiableImage is null && verifiableSectorsImage is null) + if(verifiableImage is null && + verifiableSectorsImage is null) { DicConsole.ErrorWriteLine("The specified image does not support any kind of verification"); - return (int)ErrorNumber.NotVerificable; + + return(int)ErrorNumber.NotVerificable; } if(verifyDisc && verifiableImage != null) @@ -149,12 +141,15 @@ namespace DiscImageChef.Commands { case true: DicConsole.WriteLine("Disc image checksums are correct"); + break; case false: DicConsole.WriteLine("Disc image checksums are incorrect"); + break; case null: DicConsole.WriteLine("Disc image does not contain checksums"); + break; } @@ -175,6 +170,7 @@ namespace DiscImageChef.Commands ulong currentSectorAll = 0; startCheck = DateTime.UtcNow; + foreach(Track currentTrack in inputTracks) { ulong remainingSectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector; @@ -185,20 +181,20 @@ namespace DiscImageChef.Commands DicConsole.Write("\rChecking sector {0} of {1}, on track {2}", currentSectorAll, inputFormat.Info.Sectors, currentTrack.TrackSequence); - List tempfailingLbas; - List tempunknownLbas; + List tempFailingLbas; + List tempUnknownLbas; if(remainingSectors < 512) opticalMediaImage.VerifySectors(currentSector, (uint)remainingSectors, - currentTrack.TrackSequence, out tempfailingLbas, - out tempunknownLbas); + currentTrack.TrackSequence, out tempFailingLbas, + out tempUnknownLbas); else opticalMediaImage.VerifySectors(currentSector, 512, currentTrack.TrackSequence, - out tempfailingLbas, out tempunknownLbas); + out tempFailingLbas, out tempUnknownLbas); - failingLbas.AddRange(tempfailingLbas); + failingLbas.AddRange(tempFailingLbas); - unknownLbas.AddRange(tempunknownLbas); + unknownLbas.AddRange(tempUnknownLbas); if(remainingSectors < 512) { @@ -223,23 +219,24 @@ namespace DiscImageChef.Commands ulong currentSector = 0; startCheck = DateTime.UtcNow; + while(remainingSectors > 0) { DicConsole.Write("\rChecking sector {0} of {1}", currentSector, inputFormat.Info.Sectors); - List tempfailingLbas; - List tempunknownLbas; + List tempFailingLbas; + List tempUnknownLbas; if(remainingSectors < 512) verifiableSectorsImage.VerifySectors(currentSector, (uint)remainingSectors, - out tempfailingLbas, out tempunknownLbas); + out tempFailingLbas, out tempUnknownLbas); else - verifiableSectorsImage.VerifySectors(currentSector, 512, out tempfailingLbas, - out tempunknownLbas); + verifiableSectorsImage.VerifySectors(currentSector, 512, out tempFailingLbas, + out tempUnknownLbas); - failingLbas.AddRange(tempfailingLbas); + failingLbas.AddRange(tempFailingLbas); - unknownLbas.AddRange(tempunknownLbas); + unknownLbas.AddRange(tempUnknownLbas); if(remainingSectors < 512) { @@ -262,15 +259,20 @@ namespace DiscImageChef.Commands if(unknownSectors > 0) DicConsole.WriteLine("There is at least one sector that does not contain a checksum"); + if(errorSectors > 0) DicConsole.WriteLine("There is at least one sector with incorrect checksum or errors"); - if(unknownSectors == 0 && errorSectors == 0) DicConsole.WriteLine("All sector checksums are correct"); + + if(unknownSectors == 0 && + errorSectors == 0) + DicConsole.WriteLine("All sector checksums are correct"); DicConsole.VerboseWriteLine("Checking sector checksums took {0} seconds", checkTime.TotalSeconds); - if(MainClass.Verbose) + if(verbose) { DicConsole.VerboseWriteLine("LBAs with error:"); + if(failingLbas.Count == (int)inputFormat.Info.Sectors) DicConsole.VerboseWriteLine("\tall sectors."); else @@ -278,6 +280,7 @@ namespace DiscImageChef.Commands DicConsole.VerboseWriteLine("\t{0}", t); DicConsole.WriteLine("LBAs without checksum:"); + if(unknownLbas.Count == (int)inputFormat.Info.Sectors) DicConsole.VerboseWriteLine("\tall sectors."); else @@ -290,27 +293,26 @@ namespace DiscImageChef.Commands DicConsole.WriteLine("Total unknowns.......... {0}", unknownLbas.Count); DicConsole.WriteLine("Total errors+unknowns... {0}", failingLbas.Count + unknownLbas.Count); - totalSectors = (long)inputFormat.Info.Sectors; - errorSectors = failingLbas.Count; - unknownSectors = unknownLbas.Count; - if(failingLbas.Count > 0) correctSectors = false; - else if((ulong)unknownLbas.Count < inputFormat.Info.Sectors) correctSectors = true; + if(failingLbas.Count > 0) + correctSectors = false; + else if((ulong)unknownLbas.Count < inputFormat.Info.Sectors) + correctSectors = true; } switch(correctImage) { - case null when correctSectors is null: return (int)ErrorNumber.NotVerificable; - case null when correctSectors == false: return (int)ErrorNumber.BadSectorsImageNotVerified; - case null when correctSectors == true: return (int)ErrorNumber.CorrectSectorsImageNotVerified; - case false when correctSectors is null: return (int)ErrorNumber.BadImageSectorsNotVerified; - case false when correctSectors == false: return (int)ErrorNumber.BadImageBadSectors; - case false when correctSectors == true: return (int)ErrorNumber.CorrectSectorsBadImage; - case true when correctSectors is null: return (int)ErrorNumber.CorrectImageSectorsNotVerified; - case true when correctSectors == false: return (int)ErrorNumber.CorrectImageBadSectors; - case true when correctSectors == true: return (int)ErrorNumber.NoError; + case null when correctSectors is null: return(int)ErrorNumber.NotVerificable; + case null when correctSectors == false: return(int)ErrorNumber.BadSectorsImageNotVerified; + case null when correctSectors == true: return(int)ErrorNumber.CorrectSectorsImageNotVerified; + case false when correctSectors is null: return(int)ErrorNumber.BadImageSectorsNotVerified; + case false when correctSectors == false: return(int)ErrorNumber.BadImageBadSectors; + case false when correctSectors == true: return(int)ErrorNumber.CorrectSectorsBadImage; + case true when correctSectors is null: return(int)ErrorNumber.CorrectImageSectorsNotVerified; + case true when correctSectors == false: return(int)ErrorNumber.CorrectImageBadSectors; + case true when correctSectors == true: return(int)ErrorNumber.NoError; } - return (int)ErrorNumber.NoError; + return(int)ErrorNumber.NoError; } } } \ No newline at end of file diff --git a/DiscImageChef/DiscImageChef.csproj b/DiscImageChef/DiscImageChef.csproj index f073a6de7..38fc64a6c 100644 --- a/DiscImageChef/DiscImageChef.csproj +++ b/DiscImageChef/DiscImageChef.csproj @@ -264,8 +264,8 @@ - + diff --git a/DiscImageChef/Main.cs b/DiscImageChef/Main.cs index f1fb3ba44..3b9691aec 100644 --- a/DiscImageChef/Main.cs +++ b/DiscImageChef/Main.cs @@ -31,44 +31,43 @@ // ****************************************************************************/ using System; +using System.CommandLine; +using System.CommandLine.Invocation; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using DiscImageChef.Commands; -using DiscImageChef.CommonTypes.Interop; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Database; using DiscImageChef.Settings; using Microsoft.EntityFrameworkCore; -using Mono.Options; -using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID; namespace DiscImageChef { internal class MainClass { - internal static bool Verbose; - internal static bool Debug; - internal static string AssemblyCopyright; - internal static string AssemblyTitle; - internal static AssemblyInformationalVersionAttribute AssemblyVersion; + static string _assemblyCopyright; + static string _assemblyTitle; + static AssemblyInformationalVersionAttribute _assemblyVersion; [STAThread] public static int Main(string[] args) { - var attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); - AssemblyTitle = ((AssemblyTitleAttribute) attributes[0]).Title; - attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); - AssemblyVersion = + object[] attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + _assemblyTitle = ((AssemblyTitleAttribute)attributes[0]).Title; + attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + + _assemblyVersion = Attribute.GetCustomAttribute(typeof(MainClass).Assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute; - AssemblyCopyright = ((AssemblyCopyrightAttribute) attributes[0]).Copyright; - DicConsole.WriteLineEvent += System.Console.WriteLine; - DicConsole.WriteEvent += System.Console.Write; + _assemblyCopyright = ((AssemblyCopyrightAttribute)attributes[0]).Copyright; + + DicConsole.WriteLineEvent += System.Console.WriteLine; + DicConsole.WriteEvent += System.Console.Write; DicConsole.ErrorWriteLineEvent += System.Console.Error.WriteLine; Settings.Settings.LoadSettings(); @@ -77,16 +76,17 @@ namespace DiscImageChef ctx.Database.Migrate(); ctx.SaveChanges(); - var masterDbUpdate = false; - if (!File.Exists(Settings.Settings.MasterDbPath)) + bool masterDbUpdate = false; + + if(!File.Exists(Settings.Settings.MasterDbPath)) { masterDbUpdate = true; UpdateCommand.DoUpdate(true); } - var mctx = DicContext.Create(Settings.Settings.MasterDbPath); + var masterContext = DicContext.Create(Settings.Settings.MasterDbPath); - if(mctx.Database.GetPendingMigrations().Any()) + if(masterContext.Database.GetPendingMigrations().Any()) { DicConsole.WriteLine("New database version, updating..."); @@ -103,84 +103,76 @@ namespace DiscImageChef UpdateCommand.DoUpdate(true); } - if ((args.Length < 1 || args[0].ToLowerInvariant() != "gui") && - Settings.Settings.Current.GdprCompliance < DicSettings.GdprLevel) + if((args.Length < 1 || args[0].ToLowerInvariant() != "gui") && + Settings.Settings.Current.GdprCompliance < DicSettings.GdprLevel) new ConfigureCommand(true, true).Invoke(args); - Statistics.LoadStats(); - if (Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.ShareStats) - Task.Run(() => { Statistics.SubmitStats(); }); - var currentPlatform = DetectOS.GetRealPlatformID(); + Statistics.LoadStats(); + + if(Settings.Settings.Current.Stats != null && + Settings.Settings.Current.Stats.ShareStats) + Task.Run(Statistics.SubmitStats); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); - var commands = new CommandSet("DiscImageChef") - { - $"{AssemblyTitle} {AssemblyVersion?.InformationalVersion}", - $"{AssemblyCopyright}", - "", - "usage: DiscImageChef COMMAND [OPTIONS]", - "", - "Global options:", - {"verbose|v", "Shows verbose output.", b => Verbose = b != null}, - {"debug|d", "Shows debug output from plugins.", b => Debug = b != null}, - "", - "Available commands:", - new AnalyzeCommand(), - new BenchmarkCommand(), - new ChecksumCommand(), - new CompareCommand(), - new ConfigureCommand(false, false), - new ConvertImageCommand(), - new CreateSidecarCommand(), - new DecodeCommand() - }; - - if (currentPlatform == PlatformID.FreeBSD || currentPlatform == PlatformID.Linux || - currentPlatform == PlatformID.Win32NT) - { - commands.Add(new DeviceInfoCommand()); - commands.Add(new DeviceReportCommand()); - commands.Add(new DumpMediaCommand()); - } - - commands.Add(new EntropyCommand()); - commands.Add(new ExtractFilesCommand()); - commands.Add(new FormatsCommand()); - commands.Add(new ImageInfoCommand()); - - if (currentPlatform == PlatformID.FreeBSD || currentPlatform == PlatformID.Linux || - currentPlatform == PlatformID.Win32NT) commands.Add(new ListDevicesCommand()); - - commands.Add(new ListEncodingsCommand()); - commands.Add(new ListNamespacesCommand()); - commands.Add(new ListOptionsCommand()); - commands.Add(new LsCommand()); - - if (currentPlatform == PlatformID.FreeBSD || currentPlatform == PlatformID.Linux || - currentPlatform == PlatformID.Win32NT) - { - commands.Add(new MediaInfoCommand()); - commands.Add(new MediaScanCommand()); - } - - commands.Add(new PrintHexCommand()); - commands.Add(new StatisticsCommand()); - commands.Add(new UpdateCommand(masterDbUpdate)); - commands.Add(new VerifyCommand()); - commands.Add(new RemoteCommand()); - - var ret = commands.Run(args); - Statistics.SaveStats(); - return ret; + var rootCommand = new RootCommand + { + new Option(new[] + { + "--verbose", "-v" + }, "Shows verbose output.") + { + Argument = new Argument(() => false) + }, + new Option(new[] + { + "--debug", "-d" + }, "Shows debug output from plugins.") + { + Argument = new Argument(() => false) + } + }; + + rootCommand.Description = + $"{_assemblyTitle} {_assemblyVersion?.InformationalVersion}\n{_assemblyCopyright}"; + + rootCommand.AddCommand(new AnalyzeCommand()); + rootCommand.AddCommand(new BenchmarkCommand()); + rootCommand.AddCommand(new ChecksumCommand()); + rootCommand.AddCommand(new CompareCommand()); + rootCommand.AddCommand(new ConfigureCommand(false, false)); + rootCommand.AddCommand(new ConvertImageCommand()); + rootCommand.AddCommand(new CreateSidecarCommand()); + rootCommand.AddCommand(new DecodeCommand()); + rootCommand.AddCommand(new DeviceInfoCommand()); + rootCommand.AddCommand(new DeviceReportCommand()); + rootCommand.AddCommand(new DumpMediaCommand()); + rootCommand.AddCommand(new EntropyCommand()); + rootCommand.AddCommand(new ExtractFilesCommand()); + rootCommand.AddCommand(new FormatsCommand()); + rootCommand.AddCommand(new ImageInfoCommand()); + rootCommand.AddCommand(new ListDevicesCommand()); + rootCommand.AddCommand(new ListEncodingsCommand()); + rootCommand.AddCommand(new ListNamespacesCommand()); + rootCommand.AddCommand(new ListOptionsCommand()); + rootCommand.AddCommand(new LsCommand()); + rootCommand.AddCommand(new MediaInfoCommand()); + rootCommand.AddCommand(new MediaScanCommand()); + rootCommand.AddCommand(new PrintHexCommand()); + rootCommand.AddCommand(new StatisticsCommand()); + rootCommand.AddCommand(new UpdateCommand(masterDbUpdate)); + rootCommand.AddCommand(new VerifyCommand()); + rootCommand.AddCommand(new RemoteCommand()); + + return rootCommand.Invoke(args); } internal static void PrintCopyright() { - DicConsole.WriteLine("{0} {1}", AssemblyTitle, AssemblyVersion?.InformationalVersion); - DicConsole.WriteLine("{0}", AssemblyCopyright); + DicConsole.WriteLine("{0} {1}", _assemblyTitle, _assemblyVersion?.InformationalVersion); + DicConsole.WriteLine("{0}", _assemblyCopyright); DicConsole.WriteLine(); } }