diff --git a/Aaru/Commands/Image/Print.cs b/Aaru/Commands/Image/Print.cs index f97252084..0c0957cb6 100644 --- a/Aaru/Commands/Image/Print.cs +++ b/Aaru/Commands/Image/Print.cs @@ -41,150 +41,184 @@ using Aaru.Core; using Aaru.Helpers; using Spectre.Console; -namespace Aaru.Commands.Image +namespace Aaru.Commands.Image; + +internal sealed class PrintHexCommand : Command { - internal sealed class PrintHexCommand : Command + public PrintHexCommand() : base("print", "Prints a sector, in hexadecimal values, to the console.") { - public PrintHexCommand() : base("print", "Prints a sector, in hexadecimal values, to the console.") - { - 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 + Add(new Option(new[] { - Arity = ArgumentArity.ExactlyOne, - Description = "Media image path", - Name = "image-path" + "--length", "-l" + }, "How many sectors to print.") + { + Argument = new Argument(() => 1), + Required = false }); - Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + 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 + { + Arity = ArgumentArity.ExactlyOne, + Description = "Media image path", + Name = "image-path" + }); + + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); + } + + public static int Invoke(bool debug, bool verbose, string imagePath, ulong length, bool longSectors, ulong start, + ushort width) + { + MainClass.PrintCopyright(); + + if(debug) + { + IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings + { + Out = new AnsiConsoleOutput(System.Console.Error) + }); + + AaruConsole.DebugWriteLineEvent += (format, objects) => + { + if(objects is null) + stderrConsole.MarkupLine(format); + else + stderrConsole.MarkupLine(format, objects); + }; } - public static int Invoke(bool debug, bool verbose, string imagePath, ulong length, bool longSectors, - ulong start, ushort width) + if(verbose) + AaruConsole.WriteEvent += (format, objects) => + { + if(objects is null) + AnsiConsole.Markup(format); + else + AnsiConsole.Markup(format, objects); + }; + + Statistics.AddCommand("print-hex"); + + AaruConsole.DebugWriteLine("PrintHex command", "--debug={0}", debug); + AaruConsole.DebugWriteLine("PrintHex command", "--input={0}", imagePath); + AaruConsole.DebugWriteLine("PrintHex command", "--length={0}", length); + AaruConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", longSectors); + AaruConsole.DebugWriteLine("PrintHex command", "--start={0}", start); + AaruConsole.DebugWriteLine("PrintHex command", "--verbose={0}", verbose); + AaruConsole.DebugWriteLine("PrintHex command", "--width={0}", width); + + var filtersList = new FiltersList(); + IFilter inputFilter = null; + + Core.Spectre.ProgressSingleSpinner(ctx => { - MainClass.PrintCopyright(); + ctx.AddTask("Identifying file filter...").IsIndeterminate(); + inputFilter = filtersList.GetFilter(imagePath); + }); - if(debug) - { - IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings - { - Out = new AnsiConsoleOutput(System.Console.Error) - }); + if(inputFilter == null) + { + AaruConsole.ErrorWriteLine("Cannot open specified file."); - AaruConsole.DebugWriteLineEvent += (format, objects) => - { - if(objects is null) - stderrConsole.MarkupLine(format); - else - stderrConsole.MarkupLine(format, objects); - }; - } + return (int)ErrorNumber.CannotOpenFile; + } - if(verbose) - AaruConsole.WriteEvent += (format, objects) => - { - if(objects is null) - AnsiConsole.Markup(format); - else - AnsiConsole.Markup(format, objects); - }; + IBaseImage inputFormat = null; - Statistics.AddCommand("print-hex"); + Core.Spectre.ProgressSingleSpinner(ctx => + { + ctx.AddTask("Identifying image format...").IsIndeterminate(); + inputFormat = ImageFormat.Detect(inputFilter); + }); - AaruConsole.DebugWriteLine("PrintHex command", "--debug={0}", debug); - AaruConsole.DebugWriteLine("PrintHex command", "--input={0}", imagePath); - AaruConsole.DebugWriteLine("PrintHex command", "--length={0}", length); - AaruConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", longSectors); - AaruConsole.DebugWriteLine("PrintHex command", "--start={0}", start); - AaruConsole.DebugWriteLine("PrintHex command", "--verbose={0}", verbose); - AaruConsole.DebugWriteLine("PrintHex command", "--width={0}", width); + if(inputFormat == null) + { + AaruConsole.ErrorWriteLine("Unable to recognize image format, not verifying"); - var filtersList = new FiltersList(); - IFilter inputFilter = null; + return (int)ErrorNumber.UnrecognizedFormat; + } + + ErrorNumber opened = ErrorNumber.NoData; + + Core.Spectre.ProgressSingleSpinner(ctx => + { + ctx.AddTask("Opening image file...").IsIndeterminate(); + opened = inputFormat.Open(inputFilter); + }); + + if(opened != ErrorNumber.NoError) + { + AaruConsole.WriteLine("Unable to open image format"); + AaruConsole.WriteLine("Error {0}", opened); + + return (int)opened; + } + + if(inputFormat.Info.XmlMediaType == XmlMediaType.LinearMedia) + { + var byteAddressableImage = inputFormat as IByteAddressableImage; + + AaruConsole.WriteLine("[bold][italic]Start {0}[/][/]", start); + + byte[] data = new byte[length]; + ErrorNumber errno = ErrorNumber.NoError; + int bytesRead = 0; Core.Spectre.ProgressSingleSpinner(ctx => { - ctx.AddTask("Identifying file filter...").IsIndeterminate(); - inputFilter = filtersList.GetFilter(imagePath); + ctx.AddTask("Reading data...").IsIndeterminate(); + + errno = byteAddressableImage?.ReadBytesAt((long)start, data, 0, (int)length, out bytesRead) ?? + ErrorNumber.InvalidArgument; }); - if(inputFilter == null) + // TODO: Span + if(bytesRead != (int)length) { - AaruConsole.ErrorWriteLine("Cannot open specified file."); - - return (int)ErrorNumber.CannotOpenFile; - } - - IMediaImage inputFormat = null; - - Core.Spectre.ProgressSingleSpinner(ctx => - { - ctx.AddTask("Identifying image format...").IsIndeterminate(); - inputFormat = ImageFormat.Detect(inputFilter); - }); - - if(inputFormat == null) - { - AaruConsole.ErrorWriteLine("Unable to recognize image format, not verifying"); - - return (int)ErrorNumber.UnrecognizedFormat; - } - - ErrorNumber opened = ErrorNumber.NoData; - - Core.Spectre.ProgressSingleSpinner(ctx => - { - ctx.AddTask("Opening image file...").IsIndeterminate(); - opened = inputFormat.Open(inputFilter); - }); - - if(opened != ErrorNumber.NoError) - { - AaruConsole.WriteLine("Unable to open image format"); - AaruConsole.WriteLine("Error {0}", opened); - - return (int)opened; + byte[] tmp = new byte[bytesRead]; + Array.Copy(data, 0, tmp, 0, bytesRead); + data = tmp; } + if(errno == ErrorNumber.NoError) + AaruConsole.WriteLine(Markup.Escape(PrintHex.ByteArrayToHexArrayString(data, width, true))); + else + AaruConsole.ErrorWriteLine($"Error {errno} reading data from {start}."); + } + else for(ulong i = 0; i < length; i++) { + var blockImage = inputFormat as IMediaImage; + AaruConsole.WriteLine("[bold][italic]Sector {0}[/][/]", start + i); - if(inputFormat.Info.ReadableSectorTags == null) + if(blockImage?.Info.ReadableSectorTags == null) { AaruConsole. WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); @@ -193,7 +227,7 @@ namespace Aaru.Commands.Image } else { - if(inputFormat.Info.ReadableSectorTags.Count == 0) + if(blockImage.Info.ReadableSectorTags.Count == 0) { AaruConsole. WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); @@ -209,8 +243,8 @@ namespace Aaru.Commands.Image { ctx.AddTask("Reading sector...").IsIndeterminate(); - errno = longSectors ? inputFormat.ReadSectorLong(start + i, out sector) - : inputFormat.ReadSector(start + i, out sector); + errno = longSectors ? blockImage.ReadSectorLong(start + i, out sector) + : blockImage.ReadSector(start + i, out sector); }); if(errno == ErrorNumber.NoError) @@ -219,7 +253,6 @@ namespace Aaru.Commands.Image AaruConsole.ErrorWriteLine($"Error {errno} reading sector {start + i}."); } - return (int)ErrorNumber.NoError; - } + return (int)ErrorNumber.NoError; } } \ No newline at end of file