mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Migrate to Spectre.Console.Cli.
This commit is contained in:
15
.idea/.idea.Aaru/.idea/runConfigurations/Aaru.xml
generated
15
.idea/.idea.Aaru/.idea/runConfigurations/Aaru.xml
generated
@@ -1,18 +1,23 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Aaru" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/Aaru/bin/Debug/net9.0/aaru.exe" />
|
||||
<option name="PROGRAM_PARAMETERS" value="m dump --first-pregap --metadata false -p 1 --fix-subchannel-position --retry-subchannel --fix-subchannel --fix-subchannel-crc --generate-subchannels --eject -O compress=false --trim=false --title-keys=false g: "Super Mario Galaxy 2 for Beginners (RVL-9B4P-EUR-B0).aif"" />
|
||||
<option name="WORKING_DIRECTORY" value="F:/" />
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/Aaru/bin/Debug/net10.0/aaru" />
|
||||
<option name="PROGRAM_PARAMETERS" value="archive extract --help" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Aaru/bin/Debug/net10.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="ENV_FILE_PATHS" value="" />
|
||||
<option name="REDIRECT_INPUT_PATH" value="" />
|
||||
<option name="PTY_MODE" value="Auto" />
|
||||
<option name="MIXED_MODE_DEBUG" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="AUTO_ATTACH_CHILDREN" value="0" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/Aaru/Aaru.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="0" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net9.0" />
|
||||
<option name="PROJECT_TFM" value="net10.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
|
||||
13956
Aaru.Localization/UI.Designer.cs
generated
13956
Aaru.Localization/UI.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -60,9 +60,6 @@
|
||||
</data>
|
||||
<data name="Automation_Device_Serial_Number" xml:space="preserve">
|
||||
<value>Número de serie del dispositivo de automatización</value>
|
||||
</data>
|
||||
<data name="Barcode_of_the_media_by_image" xml:space="preserve">
|
||||
<value>Código de barras del medio representado por la imagen.</value>
|
||||
</data>
|
||||
<data name="Base_Mechanical_Serial_Number" xml:space="preserve">
|
||||
<value>Número de serie de la mecánica base</value>
|
||||
@@ -621,9 +618,6 @@
|
||||
</data>
|
||||
<data name="Decoder_for_sector_tag_type_0_not_yet_implemented_sorry" xml:space="preserve">
|
||||
<value>Aún no se ha implementado un descodificador para la etiqueta de sector "{0}".</value>
|
||||
</data>
|
||||
<data name="Decode_media_tags" xml:space="preserve">
|
||||
<value>Descodificar etiquetas del medio.</value>
|
||||
</data>
|
||||
<data name="Decode_sector_tags" xml:space="preserve">
|
||||
<value>Descodificar etiquetas de sector.</value>
|
||||
@@ -1555,9 +1549,6 @@
|
||||
</data>
|
||||
<data name="Media_image_format_statistics" xml:space="preserve">
|
||||
<value>Estadísticas de formatos de imagen de medio</value>
|
||||
</data>
|
||||
<data name="Media_image_path" xml:space="preserve">
|
||||
<value>Ruta de la imagen</value>
|
||||
</data>
|
||||
<data name="Media_Info_Command_Description" xml:space="preserve">
|
||||
<value>Obtiene información sobre el medio introducido en un dispositivo.</value>
|
||||
@@ -1630,9 +1621,6 @@
|
||||
</data>
|
||||
<data name="Migrating_local_database" xml:space="preserve">
|
||||
<value>Migrando base de datos local...</value>
|
||||
</data>
|
||||
<data name="Model_of_drive_read_the_media_by_image" xml:space="preserve">
|
||||
<value>Modelo de la uinidad usada para leer el medio representado en la imagen.</value>
|
||||
</data>
|
||||
<data name="Model_of_media_by_image" xml:space="preserve">
|
||||
<value>Modelo del medio representado en la imagen.</value>
|
||||
@@ -2104,9 +2092,6 @@
|
||||
</data>
|
||||
<data name="Tape_argument_input_help" xml:space="preserve">
|
||||
<value>Al usarse indica que la entrada es una carpeta conteniendo los ficheros ordenados alfabéticamente extraídos de una cinta lineal de bloques de tamaño fijo (por ej. una unidad de cinta SCSI).</value>
|
||||
</data>
|
||||
<data name="Tape_block_size_argument_help" xml:space="preserve">
|
||||
<value>Sólo usado para cintas, indica el tamaño del bloque. Los ficheros en la carpeta cuyo tamaño no sea múltiple de este serán ignorados.</value>
|
||||
</data>
|
||||
<data name="Text_Authors" xml:space="preserve">
|
||||
<value>Desarrolladores:
|
||||
|
||||
@@ -505,9 +505,6 @@ In you are unsure, please press N to not continue.</value>
|
||||
</data>
|
||||
<data name="Searches_and_interprets_partitions" xml:space="preserve">
|
||||
<value>Searches and interprets partitions.</value>
|
||||
</data>
|
||||
<data name="Media_image_path" xml:space="preserve">
|
||||
<value>Media image path</value>
|
||||
</data>
|
||||
<data name="Image_format_not_identified_not_proceeding_with_analysis" xml:space="preserve">
|
||||
<value>Image format not identified, not proceeding with analysis.</value>
|
||||
@@ -897,9 +894,6 @@ In you are unsure, please press N to not continue.</value>
|
||||
</data>
|
||||
<data name="Manufacturer_of_drive_read_the_media_by_image" xml:space="preserve">
|
||||
<value>Manufacturer of the drive used to read the media represented by the image.</value>
|
||||
</data>
|
||||
<data name="Model_of_drive_read_the_media_by_image" xml:space="preserve">
|
||||
<value>Model of the drive used to read the media represented by the image.</value>
|
||||
</data>
|
||||
<data name="Firmware_revision_of_drive_read_the_media_by_image" xml:space="preserve">
|
||||
<value>Firmware revision of the drive used to read the media represented by the image.</value>
|
||||
@@ -912,9 +906,6 @@ In you are unsure, please press N to not continue.</value>
|
||||
</data>
|
||||
<data name="Format_of_the_output_image_as_plugin_name_or_plugin_id" xml:space="preserve">
|
||||
<value>Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.</value>
|
||||
</data>
|
||||
<data name="Barcode_of_the_media_by_image" xml:space="preserve">
|
||||
<value>Barcode of the media represented by the image.</value>
|
||||
</data>
|
||||
<data name="Last_media_of_sequence_by_image" xml:space="preserve">
|
||||
<value>Last media of the sequence the media represented by the image corresponds to.</value>
|
||||
@@ -1171,9 +1162,6 @@ In you are unsure, please press N to not continue.</value>
|
||||
</data>
|
||||
<data name="Conversion_done" xml:space="preserve">
|
||||
<value>Conversion done.</value>
|
||||
</data>
|
||||
<data name="Tape_block_size_argument_help" xml:space="preserve">
|
||||
<value>Only used for tapes, indicates block size. Files in the folder whose size is not a multiple of this value will simply be ignored.</value>
|
||||
</data>
|
||||
<data name="Tape_argument_input_help" xml:space="preserve">
|
||||
<value>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).</value>
|
||||
@@ -1186,9 +1174,6 @@ In you are unsure, please press N to not continue.</value>
|
||||
</data>
|
||||
<data name="The_specified_input_file_cannot_be_found" xml:space="preserve">
|
||||
<value>The specified input file cannot be found.</value>
|
||||
</data>
|
||||
<data name="Decode_media_tags" xml:space="preserve">
|
||||
<value>Decode media tags.</value>
|
||||
</data>
|
||||
<data name="Parameter_response_all_sectors" xml:space="preserve">
|
||||
<value>all</value>
|
||||
@@ -3111,4 +3096,7 @@ Do you want to continue?</value>
|
||||
<data name="Dialog_Aaru_Resume" xml:space="preserve">
|
||||
<value>Aaru resume file</value>
|
||||
</data>
|
||||
<data name="Archive_List_Command_Description" xml:space="preserve">
|
||||
<value>List the contents of an archive file.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -76,8 +76,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite"/>
|
||||
<PackageReference Include="Spectre.Console"/>
|
||||
<PackageReference Include="System.CommandLine"/>
|
||||
<PackageReference Include="System.CommandLine.NamingConventionBinder"/>
|
||||
<PackageReference Include="Spectre.Console.Cli"/>
|
||||
<PackageReference Include="System.Text.Encoding.CodePages"/>
|
||||
<PackageReference Include="System.Text.Json"/>
|
||||
<PackageReference Include="System.ValueTuple"/>
|
||||
|
||||
@@ -31,19 +31,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.CommandLine;
|
||||
using Aaru.Localization;
|
||||
|
||||
namespace Aaru.Commands.Archive;
|
||||
|
||||
sealed class ArchiveFamily : Command
|
||||
{
|
||||
internal ArchiveFamily() : base("archive", UI.Archive_Command_Family_Description)
|
||||
{
|
||||
AddAlias("arc");
|
||||
|
||||
AddCommand(new ArchiveInfoCommand());
|
||||
AddCommand(new ArchiveListCommand());
|
||||
AddCommand(new ArchiveExtractCommand());
|
||||
}
|
||||
}
|
||||
class ArchiveFamily : BaseSettings {}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
@@ -46,45 +45,20 @@ using Aaru.Core;
|
||||
using Aaru.Helpers;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Archive;
|
||||
|
||||
sealed class ArchiveExtractCommand : Command
|
||||
sealed class ArchiveExtractCommand : Command<ArchiveExtractCommand.Settings>
|
||||
{
|
||||
const int BUFFER_SIZE = 16777216;
|
||||
const string MODULE_NAME = "Extract-Files command";
|
||||
|
||||
public ArchiveExtractCommand() : base("extract", UI.Archive_Extract_Command_Description)
|
||||
{
|
||||
AddAlias("x");
|
||||
|
||||
Add(new Option<string>(["--encoding", "-e"], () => null, UI.Name_of_character_encoding_to_use));
|
||||
|
||||
Add(new Option<bool>(["--xattrs", "-x"], () => false, UI.Extract_extended_attributes_if_present));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Archive_file_path,
|
||||
Name = "archive-path"
|
||||
});
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Directory_where_extracted_files_will_be_created,
|
||||
Name = "output-dir"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string encoding, bool xattrs, string archivePath,
|
||||
string outputDir)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -102,7 +76,7 @@ sealed class ArchiveExtractCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -115,19 +89,19 @@ sealed class ArchiveExtractCommand : Command
|
||||
|
||||
Statistics.AddCommand("archive-extract");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(archivePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output={0}", Markup.Escape(outputDir ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--xattrs={0}", xattrs);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(settings.Encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.Path ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output={0}", Markup.Escape(settings.OutputDir ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--xattrs={0}", settings.XAttrs);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(archivePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.Path);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -139,13 +113,13 @@ sealed class ArchiveExtractCommand : Command
|
||||
|
||||
Encoding encodingClass = null;
|
||||
|
||||
if(encoding != null)
|
||||
if(settings.Encoding != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(settings.Encoding);
|
||||
|
||||
if(verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
if(settings.Verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
@@ -172,7 +146,7 @@ sealed class ArchiveExtractCommand : Command
|
||||
return (int)ErrorNumber.UnrecognizedFormat;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AaruConsole.VerboseWriteLine(UI.Archive_format_identified_by_0_1, archive.Name, archive.Id);
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Archive_format_identified_by_0, archive.Name);
|
||||
@@ -211,7 +185,7 @@ sealed class ArchiveExtractCommand : Command
|
||||
}
|
||||
|
||||
|
||||
for(var i = 0; i < archive.NumberOfEntries; i++)
|
||||
for(int i = 0; i < archive.NumberOfEntries; i++)
|
||||
{
|
||||
ErrorNumber errno = archive.GetFilename(i, out string fileName);
|
||||
|
||||
@@ -264,7 +238,7 @@ sealed class ArchiveExtractCommand : Command
|
||||
// Prevent absolute path attack
|
||||
fileName = fileName.TrimStart('\\').TrimStart('/');
|
||||
|
||||
string outputPath = Path.Combine(outputDir, fileName);
|
||||
string outputPath = Path.Combine(settings.OutputDir, fileName);
|
||||
string destinationDir = Path.GetDirectoryName(outputPath);
|
||||
|
||||
if(File.Exists(destinationDir))
|
||||
@@ -284,7 +258,7 @@ sealed class ArchiveExtractCommand : Command
|
||||
.Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn())
|
||||
.Start(ctx =>
|
||||
{
|
||||
var position = 0;
|
||||
int position = 0;
|
||||
|
||||
var outputFile =
|
||||
new FileStream(outputPath,
|
||||
@@ -296,7 +270,7 @@ sealed class ArchiveExtractCommand : Command
|
||||
ctx.AddTask(string.Format(UI.Reading_file_0, Markup.Escape(fileName)));
|
||||
|
||||
task.MaxValue = uncompressedSize;
|
||||
var outBuf = new byte[BUFFER_SIZE];
|
||||
byte[] outBuf = new byte[BUFFER_SIZE];
|
||||
Stream inputFile = filter.GetDataForkStream();
|
||||
|
||||
while(position < stat.Length)
|
||||
@@ -357,7 +331,7 @@ sealed class ArchiveExtractCommand : Command
|
||||
else
|
||||
AaruConsole.ErrorWriteLine(UI.Cannot_write_file_0_output_exists, Markup.Escape(fileName));
|
||||
|
||||
if(!xattrs) continue;
|
||||
if(!settings.XAttrs) continue;
|
||||
|
||||
errno = archive.ListXAttr(i, out List<string> xattrNames);
|
||||
|
||||
@@ -389,7 +363,7 @@ sealed class ArchiveExtractCommand : Command
|
||||
continue;
|
||||
}
|
||||
|
||||
outputPath = Path.Combine(outputDir, ".xattrs", xattrName, fileName);
|
||||
outputPath = Path.Combine(settings.OutputDir, ".xattrs", xattrName, fileName);
|
||||
|
||||
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
@@ -469,4 +443,29 @@ sealed class ArchiveExtractCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ArchiveFamily
|
||||
{
|
||||
[Description("Name of character encoding to use.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-e|--encoding")]
|
||||
public string Encoding { get; init; }
|
||||
|
||||
[Description("Extract extended attributes if present.")]
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("-x|--xattrs")]
|
||||
public bool XAttrs { get; init; }
|
||||
|
||||
[Description("Archive file path")]
|
||||
[CommandArgument(0, "<path>")]
|
||||
public string Path { get; init; }
|
||||
|
||||
[Description("Directory where extracted files will be created. Will abort if it exists")]
|
||||
[CommandArgument(1, "<output>")]
|
||||
public string OutputDir { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -32,8 +32,7 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -42,33 +41,19 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Archive;
|
||||
|
||||
sealed class ArchiveInfoCommand : Command
|
||||
sealed class ArchiveInfoCommand : Command<ArchiveInfoCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Analyze command";
|
||||
|
||||
public ArchiveInfoCommand() : base("info", UI.Archive_Info_Command_Description)
|
||||
{
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Archive_file_path,
|
||||
Name = "archive-path"
|
||||
});
|
||||
|
||||
Add(new Option<string>(["--encoding", "-e"], () => null, UI.Name_of_character_encoding_to_use));
|
||||
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string archivePath, string encoding)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -86,7 +71,7 @@ sealed class ArchiveInfoCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -99,17 +84,17 @@ sealed class ArchiveInfoCommand : Command
|
||||
|
||||
Statistics.AddCommand("archive-info");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "input={0}", Markup.Escape(archivePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "encoding={0}", Markup.Escape(encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "input={0}", Markup.Escape(settings.Path ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "encoding={0}", Markup.Escape(settings.Encoding ?? ""));
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(archivePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.Path);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -121,13 +106,13 @@ sealed class ArchiveInfoCommand : Command
|
||||
|
||||
Encoding encodingClass = null;
|
||||
|
||||
if(encoding != null)
|
||||
if(settings.Encoding != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(settings.Encoding);
|
||||
|
||||
if(verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
if(settings.Verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
@@ -188,4 +173,20 @@ sealed class ArchiveInfoCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ArchiveFamily
|
||||
{
|
||||
[CommandOption("-e|--encoding")]
|
||||
[Description("Name of character encoding to use.")]
|
||||
[DefaultValue(null)]
|
||||
public string Encoding { get; init; }
|
||||
|
||||
[Description("Archive file path")]
|
||||
[CommandArgument(0, "<path>")]
|
||||
public string Path { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -31,8 +31,7 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -42,36 +41,19 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Archive;
|
||||
|
||||
sealed class ArchiveListCommand : Command
|
||||
sealed class ArchiveListCommand : Command<ArchiveListCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Archive list command";
|
||||
|
||||
public ArchiveListCommand() : base("list", "Lists files contained in an archive.")
|
||||
{
|
||||
AddAlias("l");
|
||||
|
||||
Add(new Option<string>(["--encoding", "-e"], () => null, UI.Name_of_character_encoding_to_use));
|
||||
|
||||
Add(new Option<bool>(["--long-format", "-l"], () => false, UI.Use_long_format));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Archive_file_path,
|
||||
Name = "archive-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string encoding, string archivePath, bool longFormat)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -89,7 +71,7 @@ sealed class ArchiveListCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -100,11 +82,11 @@ sealed class ArchiveListCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--long-format={0}", longFormat);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(archivePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(settings.Encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--long-format={0}", settings.LongFormat);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.Path ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
Statistics.AddCommand("archive-list");
|
||||
|
||||
IFilter inputFilter = null;
|
||||
@@ -112,7 +94,7 @@ sealed class ArchiveListCommand : Command
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(archivePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.Path);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -124,13 +106,13 @@ sealed class ArchiveListCommand : Command
|
||||
|
||||
Encoding encodingClass = null;
|
||||
|
||||
if(encoding != null)
|
||||
if(settings.Encoding != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(settings.Encoding);
|
||||
|
||||
if(verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
if(settings.Verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
@@ -159,7 +141,7 @@ sealed class ArchiveListCommand : Command
|
||||
return (int)ErrorNumber.UnrecognizedFormat;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AaruConsole.VerboseWriteLine(UI.Archive_format_identified_by_0_1, archive.Name, archive.Id);
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Archive_format_identified_by_0, archive.Name);
|
||||
@@ -197,9 +179,9 @@ sealed class ArchiveListCommand : Command
|
||||
return (int)ErrorNumber.CannotOpenFormat;
|
||||
}
|
||||
|
||||
if(!longFormat)
|
||||
if(!settings.LongFormat)
|
||||
{
|
||||
for(var i = 0; i < archive.NumberOfEntries; i++)
|
||||
for(int i = 0; i < archive.NumberOfEntries; i++)
|
||||
{
|
||||
ErrorNumber errno = archive.GetFilename(i, out string fileName);
|
||||
|
||||
@@ -218,8 +200,8 @@ sealed class ArchiveListCommand : Command
|
||||
}
|
||||
|
||||
var table = new Table();
|
||||
var files = 0;
|
||||
var folders = 0;
|
||||
int files = 0;
|
||||
int folders = 0;
|
||||
long totalSize = 0;
|
||||
long totalUncompressed = 0;
|
||||
|
||||
@@ -278,7 +260,7 @@ sealed class ArchiveListCommand : Command
|
||||
|
||||
ctx.Refresh();
|
||||
|
||||
for(var i = 0; i < archive.NumberOfEntries; i++)
|
||||
for(int i = 0; i < archive.NumberOfEntries; i++)
|
||||
{
|
||||
ErrorNumber errno = archive.GetFilename(i, out string fileName);
|
||||
|
||||
@@ -302,7 +284,7 @@ sealed class ArchiveListCommand : Command
|
||||
continue;
|
||||
}
|
||||
|
||||
var attr = new char[5];
|
||||
char[] attr = new char[5];
|
||||
|
||||
if(stat.Attributes.HasFlag(FileAttributes.Directory))
|
||||
{
|
||||
@@ -422,4 +404,25 @@ sealed class ArchiveListCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ArchiveFamily
|
||||
{
|
||||
[CommandOption("-e|--encoding")]
|
||||
[Description("Name of character encoding to use.")]
|
||||
[DefaultValue(null)]
|
||||
public string Encoding { get; init; }
|
||||
|
||||
[CommandOption("-l|--long-format")]
|
||||
[Description("Use long format.")]
|
||||
[DefaultValue(false)]
|
||||
public bool LongFormat { get; init; }
|
||||
|
||||
[Description("Archive file path")]
|
||||
[CommandArgument(0, "<path>")]
|
||||
public string Path { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
25
Aaru/Commands/BaseSettings.cs
Normal file
25
Aaru/Commands/BaseSettings.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands;
|
||||
|
||||
public class BaseSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("-v|--verbose")]
|
||||
[Description("Shows verbose output.")]
|
||||
[DefaultValue(false)]
|
||||
public bool Verbose { get; init; }
|
||||
|
||||
[CommandOption("-d|--debug")]
|
||||
[Description("Shows debug output from plugins.")]
|
||||
[DefaultValue(false)]
|
||||
public bool Debug { get; init; }
|
||||
|
||||
// TODO: Add support for this
|
||||
/*
|
||||
[CommandOption("--pause")]
|
||||
[Description("Pauses before exiting.")]
|
||||
[DefaultValue(false)]
|
||||
public bool Pause { get; init; }
|
||||
*/
|
||||
}
|
||||
@@ -30,27 +30,22 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.Console;
|
||||
using Aaru.Localization;
|
||||
using Aaru.Settings;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands;
|
||||
|
||||
sealed class ConfigureCommand : Command
|
||||
sealed class ConfigureCommand : Command<ConfigureCommand.Settings>
|
||||
{
|
||||
public ConfigureCommand() : base("configure", UI.Configure_Command_Description) =>
|
||||
Handler = CommandHandler.Create((Func<bool, bool, int>)Invoke);
|
||||
|
||||
int Invoke(bool debug, bool verbose)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -68,7 +63,7 @@ sealed class ConfigureCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -101,7 +96,7 @@ sealed class ConfigureCommand : Command
|
||||
|
||||
AaruConsole.WriteLine(UI.Configure_enable_decryption_disclaimer);
|
||||
|
||||
Settings.Settings.Current.EnableDecryption =
|
||||
Aaru.Settings.Settings.Current.EnableDecryption =
|
||||
AnsiConsole.Confirm($"[italic]{UI.Do_you_want_to_enable_decryption_of_copy_protected_media_Q}[/]");
|
||||
|
||||
#region Device reports
|
||||
@@ -110,14 +105,14 @@ sealed class ConfigureCommand : Command
|
||||
|
||||
AaruConsole.WriteLine(UI.Configure_Device_Report_information_disclaimer);
|
||||
|
||||
Settings.Settings.Current.SaveReportsGlobally = AnsiConsole.Confirm($"[italic]{UI.
|
||||
Aaru.Settings.Settings.Current.SaveReportsGlobally = AnsiConsole.Confirm($"[italic]{UI.
|
||||
Configure_Do_you_want_to_save_device_reports_in_shared_folder_of_your_computer_Q}[/]");
|
||||
|
||||
AaruConsole.WriteLine();
|
||||
|
||||
AaruConsole.WriteLine(UI.Configure_share_report_disclaimer);
|
||||
|
||||
Settings.Settings.Current.ShareReports =
|
||||
Aaru.Settings.Settings.Current.ShareReports =
|
||||
AnsiConsole.Confirm($"[italic]{UI.Do_you_want_to_share_your_device_reports_with_us_Q}[/]");
|
||||
|
||||
#endregion Device reports
|
||||
@@ -130,7 +125,7 @@ sealed class ConfigureCommand : Command
|
||||
|
||||
if(AnsiConsole.Confirm($"[italic]{UI.Do_you_want_to_save_stats_about_your_Aaru_usage_Q}[/]"))
|
||||
{
|
||||
Settings.Settings.Current.Stats = new StatsSettings
|
||||
Aaru.Settings.Settings.Current.Stats = new StatsSettings
|
||||
{
|
||||
ShareStats = AnsiConsole.Confirm($"[italic]{UI.Do_you_want_to_share_your_stats__anonymously_Q}[/]"),
|
||||
CommandStats =
|
||||
@@ -156,13 +151,19 @@ sealed class ConfigureCommand : Command
|
||||
};
|
||||
}
|
||||
else
|
||||
Settings.Settings.Current.Stats = null;
|
||||
Aaru.Settings.Settings.Current.Stats = null;
|
||||
|
||||
#endregion Statistics
|
||||
|
||||
Settings.Settings.Current.GdprCompliance = DicSettings.GDPR_LEVEL;
|
||||
Settings.Settings.SaveSettings();
|
||||
Aaru.Settings.Settings.Current.GdprCompliance = DicSettings.GDPR_LEVEL;
|
||||
Aaru.Settings.Settings.SaveSettings();
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : BaseSettings {}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,18 +30,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.CommandLine;
|
||||
using Aaru.Localization;
|
||||
|
||||
namespace Aaru.Commands.Database;
|
||||
|
||||
sealed class DatabaseFamily : Command
|
||||
{
|
||||
internal DatabaseFamily(bool mainDbUpdate) : base("database", UI.Database_Command_Family_Description)
|
||||
{
|
||||
AddAlias("db");
|
||||
|
||||
AddCommand(new StatisticsCommand());
|
||||
AddCommand(new UpdateCommand(mainDbUpdate));
|
||||
}
|
||||
}
|
||||
class DatabaseFamily : BaseSettings {}
|
||||
@@ -30,8 +30,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.Console;
|
||||
@@ -39,20 +37,19 @@ using Aaru.Database;
|
||||
using Aaru.Database.Models;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Command = System.CommandLine.Command;
|
||||
using Spectre.Console.Cli;
|
||||
using Command = Aaru.Database.Models.Command;
|
||||
|
||||
namespace Aaru.Commands.Database;
|
||||
|
||||
sealed class StatisticsCommand : Command
|
||||
sealed class StatisticsCommand : Command<StatisticsCommand.Settings>
|
||||
{
|
||||
public StatisticsCommand() : base("stats", UI.Database_Stats_Command_Description) =>
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
|
||||
public static int Invoke(bool debug, bool verbose)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -70,7 +67,7 @@ sealed class StatisticsCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -81,7 +78,7 @@ sealed class StatisticsCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
var ctx = AaruContext.Create(Settings.Settings.LocalDbPath);
|
||||
var ctx = AaruContext.Create(Aaru.Settings.Settings.LocalDbPath);
|
||||
|
||||
if(!ctx.Commands.Any() &&
|
||||
!ctx.Filesystems.Any() &&
|
||||
@@ -96,7 +93,7 @@ sealed class StatisticsCommand : Command
|
||||
return (int)ErrorNumber.NothingFound;
|
||||
}
|
||||
|
||||
var thereAreStats = false;
|
||||
bool thereAreStats = false;
|
||||
Table table;
|
||||
|
||||
if(ctx.Commands.Any())
|
||||
@@ -112,7 +109,7 @@ sealed class StatisticsCommand : Command
|
||||
|
||||
if(ctx.Commands.Any(c => c.Name == "analyze"))
|
||||
{
|
||||
foreach(Aaru.Database.Models.Command oldAnalyze in ctx.Commands.Where(c => c.Name == "analyze"))
|
||||
foreach(Command oldAnalyze in ctx.Commands.Where(c => c.Name == "analyze"))
|
||||
{
|
||||
oldAnalyze.Name = "fs-info";
|
||||
ctx.Commands.Update(oldAnalyze);
|
||||
@@ -120,8 +117,7 @@ sealed class StatisticsCommand : Command
|
||||
|
||||
ulong count = 0;
|
||||
|
||||
foreach(Aaru.Database.Models.Command fsInfo in ctx.Commands.Where(c => c.Name == "fs-info" &&
|
||||
c.Synchronized))
|
||||
foreach(Command fsInfo in ctx.Commands.Where(c => c.Name == "fs-info" && c.Synchronized))
|
||||
{
|
||||
count += fsInfo.Count;
|
||||
ctx.Remove(fsInfo);
|
||||
@@ -129,7 +125,7 @@ sealed class StatisticsCommand : Command
|
||||
|
||||
if(count > 0)
|
||||
{
|
||||
ctx.Commands.Add(new Aaru.Database.Models.Command
|
||||
ctx.Commands.Add(new Command
|
||||
{
|
||||
Count = count,
|
||||
Name = "fs-info",
|
||||
@@ -366,4 +362,10 @@ sealed class StatisticsCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : DatabaseFamily {}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -31,8 +31,7 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
@@ -43,31 +42,20 @@ using Aaru.Database;
|
||||
using Aaru.Localization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Database;
|
||||
|
||||
sealed class UpdateCommand : Command
|
||||
sealed class UpdateCommand : AsyncCommand<UpdateCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Update command";
|
||||
readonly bool _mainDbUpdate;
|
||||
|
||||
public UpdateCommand(bool mainDbUpdate) : base("update", UI.Database_Update_Command_Description)
|
||||
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
|
||||
{
|
||||
_mainDbUpdate = mainDbUpdate;
|
||||
|
||||
Add(new Option<bool>("--clear", () => false, UI.Clear_existing_main_database));
|
||||
Add(new Option<bool>("--clear-all", () => false, UI.Clear_existing_main_and_local_database));
|
||||
|
||||
Handler = CommandHandler.Create((Func<bool, bool, bool, bool, Task<int>>)InvokeAsync);
|
||||
}
|
||||
|
||||
async Task<int> InvokeAsync(bool debug, bool verbose, bool clear, bool clearAll)
|
||||
{
|
||||
if(_mainDbUpdate) return (int)ErrorNumber.NoError;
|
||||
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -85,7 +73,7 @@ sealed class UpdateCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => stderrConsole.WriteException(ex);
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -96,16 +84,16 @@ sealed class UpdateCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
if(clearAll)
|
||||
if(settings.ClearAll)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(Settings.Settings.LocalDbPath);
|
||||
File.Delete(Aaru.Settings.Settings.LocalDbPath);
|
||||
|
||||
var ctx = AaruContext.Create(Settings.Settings.LocalDbPath);
|
||||
var ctx = AaruContext.Create(Aaru.Settings.Settings.LocalDbPath);
|
||||
await ctx.Database.MigrateAsync();
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
@@ -117,11 +105,11 @@ sealed class UpdateCommand : Command
|
||||
}
|
||||
}
|
||||
|
||||
if(clear || clearAll)
|
||||
if(settings.Clear || settings.ClearAll)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(Settings.Settings.MainDbPath);
|
||||
File.Delete(Aaru.Settings.Settings.MainDbPath);
|
||||
}
|
||||
catch(Exception) when(!Debugger.IsAttached)
|
||||
{
|
||||
@@ -131,7 +119,7 @@ sealed class UpdateCommand : Command
|
||||
}
|
||||
}
|
||||
|
||||
await DoUpdateAsync(clear || clearAll);
|
||||
await DoUpdateAsync(settings.Clear || settings.ClearAll);
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
@@ -141,4 +129,20 @@ sealed class UpdateCommand : Command
|
||||
await Remote.UpdateMainDatabaseAsync(create);
|
||||
Statistics.AddCommand("update");
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : DatabaseFamily
|
||||
{
|
||||
[CommandOption("--clear")]
|
||||
[Description("Clear existing main database.")]
|
||||
[DefaultValue(false)]
|
||||
public bool Clear { get; init; }
|
||||
[CommandOption("--clear-all")]
|
||||
[Description("Clear existing main and local database.")]
|
||||
[DefaultValue(false)]
|
||||
public bool ClearAll { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,19 +30,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.CommandLine;
|
||||
using Aaru.Localization;
|
||||
|
||||
namespace Aaru.Commands.Device;
|
||||
|
||||
sealed class DeviceFamily : Command
|
||||
{
|
||||
public DeviceFamily() : base("device", UI.Device_Command_Family_Description)
|
||||
{
|
||||
AddAlias("dev");
|
||||
|
||||
AddCommand(new DeviceInfoCommand());
|
||||
AddCommand(new DeviceReportCommand());
|
||||
AddCommand(new ListDevicesCommand());
|
||||
}
|
||||
}
|
||||
class DeviceFamily : BaseSettings {}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
@@ -52,34 +51,20 @@ using Aaru.Decoders.SCSI.MMC;
|
||||
using Aaru.Helpers;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Command = System.CommandLine.Command;
|
||||
using Spectre.Console.Cli;
|
||||
using Profile = Aaru.Decoders.SCSI.MMC.Profile;
|
||||
|
||||
namespace Aaru.Commands.Device;
|
||||
|
||||
sealed class DeviceReportCommand : Command
|
||||
sealed class DeviceReportCommand : AsyncCommand<DeviceReportCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Device-Report command";
|
||||
|
||||
public DeviceReportCommand() : base("report", UI.Device_Report_Command_Description)
|
||||
{
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Device_path,
|
||||
Name = "device-path"
|
||||
});
|
||||
|
||||
Add(new Option<bool>(["--trap-disc", "-t"], () => false, UI.Device_report_using_trap_disc));
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(InvokeAsync)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static async Task<int> InvokeAsync(bool debug, bool verbose, string devicePath, bool trapDisc)
|
||||
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -97,7 +82,7 @@ sealed class DeviceReportCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -110,9 +95,11 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
Statistics.AddCommand("device-report");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--device={0}", Markup.Escape(devicePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--device={0}", Markup.Escape(settings.Path ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
string devicePath = settings.Path;
|
||||
|
||||
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
|
||||
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
|
||||
@@ -163,7 +150,7 @@ sealed class DeviceReportCommand : Command
|
||||
Type = dev.Type
|
||||
};
|
||||
|
||||
var removable = false;
|
||||
bool removable = false;
|
||||
string jsonFile;
|
||||
|
||||
switch(string.IsNullOrWhiteSpace(dev.Manufacturer))
|
||||
@@ -189,7 +176,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
jsonFile = jsonFile.Replace('\\', '_').Replace('/', '_').Replace('?', '_');
|
||||
|
||||
if(trapDisc && dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice)
|
||||
if(settings.TrapDisc && dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Device_does_not_report_with_trap_discs);
|
||||
|
||||
@@ -400,7 +387,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
string mediumManufacturer;
|
||||
byte[] senseBuffer = [];
|
||||
var sense = true;
|
||||
bool sense = true;
|
||||
|
||||
switch(dev.ScsiType)
|
||||
{
|
||||
@@ -416,7 +403,7 @@ sealed class DeviceReportCommand : Command
|
||||
dev.Manufacturer.Equals("iomega", StringComparison.InvariantCultureIgnoreCase) &&
|
||||
dev.Model.StartsWith("rrd", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if(trapDisc)
|
||||
if(settings.TrapDisc)
|
||||
{
|
||||
if(iomegaRev)
|
||||
{
|
||||
@@ -699,7 +686,8 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
tryNec |= dev.Manufacturer.Equals("nec", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
tryLiteOn |= dev.Manufacturer.Equals("lite-on", StringComparison.InvariantCultureIgnoreCase);
|
||||
tryLiteOn |=
|
||||
dev.Manufacturer.Equals("lite-on", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if(!iomegaRev)
|
||||
{
|
||||
@@ -755,7 +743,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
System.Console.ReadKey(true);
|
||||
|
||||
var mediaIsRecognized = true;
|
||||
bool mediaIsRecognized = true;
|
||||
|
||||
await AnsiConsole.Status()
|
||||
.StartAsync(Localization.Core.Waiting_for_drive_to_become_ready,
|
||||
@@ -778,7 +766,7 @@ sealed class DeviceReportCommand : Command
|
||||
case 0x04 when decSense.Value.ASCQ == 0x01:
|
||||
case 0x28:
|
||||
{
|
||||
var leftRetries = 50;
|
||||
int leftRetries = 50;
|
||||
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
@@ -857,7 +845,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
task.MaxValue = ushort.MaxValue;
|
||||
|
||||
for(var i = (ushort)(mediaTest.BlockSize ?? 0);; i++)
|
||||
for(ushort i = (ushort)(mediaTest.BlockSize ?? 0);; i++)
|
||||
{
|
||||
task.Description =
|
||||
string.Format(Localization.Core
|
||||
@@ -969,7 +957,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
mediumModel = AnsiConsole.Ask<string>(Localization.Core.Please_write_media_model);
|
||||
|
||||
var mediaIsRecognized = true;
|
||||
bool mediaIsRecognized = true;
|
||||
|
||||
await AnsiConsole.Status()
|
||||
.StartAsync(Localization.Core.Waiting_for_drive_to_become_ready,
|
||||
@@ -996,7 +984,7 @@ sealed class DeviceReportCommand : Command
|
||||
case 0x04 when decSense.Value.ASCQ == 0x01:
|
||||
case 0x28:
|
||||
{
|
||||
var leftRetries = 50;
|
||||
int leftRetries = 50;
|
||||
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
@@ -1088,7 +1076,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
System.Console.ReadKey(true);
|
||||
|
||||
var mediaIsRecognized = true;
|
||||
bool mediaIsRecognized = true;
|
||||
|
||||
await AnsiConsole.Status()
|
||||
.StartAsync(Localization.Core.Waiting_for_drive_to_become_ready,
|
||||
@@ -1111,7 +1099,7 @@ sealed class DeviceReportCommand : Command
|
||||
case 0x04 when decSense.Value.ASCQ == 0x01:
|
||||
case 0x28:
|
||||
{
|
||||
var leftRetries = 50;
|
||||
int leftRetries = 50;
|
||||
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
@@ -1178,7 +1166,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
task.MaxValue = ushort.MaxValue;
|
||||
|
||||
for(var i = (ushort)(mediaTest.BlockSize ?? 0);; i++)
|
||||
for(ushort i = (ushort)(mediaTest.BlockSize ?? 0);; i++)
|
||||
{
|
||||
task.Value = i;
|
||||
|
||||
@@ -1302,7 +1290,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
mediumModel = AnsiConsole.Ask<string>(Localization.Core.Please_write_media_model);
|
||||
|
||||
var mediaIsRecognized = true;
|
||||
bool mediaIsRecognized = true;
|
||||
|
||||
await AnsiConsole.Status()
|
||||
.StartAsync(Localization.Core.Waiting_for_drive_to_become_ready,
|
||||
@@ -1323,7 +1311,7 @@ sealed class DeviceReportCommand : Command
|
||||
case 0x3A:
|
||||
case 0x04 when decSense.Value.ASCQ == 0x01:
|
||||
{
|
||||
var leftRetries = 20;
|
||||
int leftRetries = 20;
|
||||
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
@@ -1379,7 +1367,7 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
task.MaxValue = ushort.MaxValue;
|
||||
|
||||
for(var i = (ushort)(mediaTest.BlockSize ?? 0);; i++)
|
||||
for(ushort i = (ushort)(mediaTest.BlockSize ?? 0);; i++)
|
||||
{
|
||||
task.Value = i;
|
||||
|
||||
@@ -1496,7 +1484,8 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
task.MaxValue = ushort.MaxValue;
|
||||
|
||||
for(var i = (ushort)(report.SCSI.ReadCapabilities.BlockSize ?? 0);; i++)
|
||||
for(ushort i = (ushort)(report.SCSI.ReadCapabilities.BlockSize ?? 0);;
|
||||
i++)
|
||||
{
|
||||
task.Value = i;
|
||||
|
||||
@@ -1592,15 +1581,30 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
jsonFs.Close();
|
||||
|
||||
await using(var ctx = AaruContext.Create(Settings.Settings.LocalDbPath))
|
||||
await using(var ctx = AaruContext.Create(Aaru.Settings.Settings.LocalDbPath))
|
||||
{
|
||||
ctx.Reports.Add(new Report(report));
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// TODO:
|
||||
if(Settings.Settings.Current.ShareReports) await Remote.SubmitReportAsync(report);
|
||||
if(Aaru.Settings.Settings.Current.ShareReports) await Remote.SubmitReportAsync(report);
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : DeviceFamily
|
||||
{
|
||||
[Description("Does a device report using a trap disc.")]
|
||||
[CommandOption("-t|--trap-disc")]
|
||||
public bool TrapDisc { get; init; }
|
||||
|
||||
[Description("Device path")]
|
||||
[CommandArgument(0, "<device-path>")]
|
||||
public string Path { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -33,8 +33,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -55,36 +54,23 @@ using Aaru.Localization;
|
||||
using Humanizer;
|
||||
using Humanizer.Localisation;
|
||||
using Spectre.Console;
|
||||
using Command = System.CommandLine.Command;
|
||||
using Spectre.Console.Cli;
|
||||
using DeviceInfo = Aaru.Core.Devices.Info.DeviceInfo;
|
||||
using Inquiry = Aaru.Decoders.SCSI.Inquiry;
|
||||
using Tuple = Aaru.Decoders.PCMCIA.Tuple;
|
||||
|
||||
namespace Aaru.Commands.Device;
|
||||
|
||||
sealed class DeviceInfoCommand : Command
|
||||
[Description("Gets information about a device.")]
|
||||
sealed class DeviceInfoCommand : Command<DeviceInfoCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Device-Info command";
|
||||
|
||||
public DeviceInfoCommand() : base("info", UI.Device_Info_Command_Description)
|
||||
{
|
||||
Add(new Option<string>(["--output-prefix", "-w"], () => null, UI.Prefix_for_saving_binary_information));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Device_path,
|
||||
Name = "device-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string devicePath, string outputPrefix)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -102,7 +88,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -115,10 +101,12 @@ sealed class DeviceInfoCommand : Command
|
||||
|
||||
Statistics.AddCommand("device-info");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--device={0}", Markup.Escape(devicePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output-prefix={0}", Markup.Escape(outputPrefix ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--device={0}", Markup.Escape(settings.Path ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output-prefix={0}", Markup.Escape(settings.OutputPrefix ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
string devicePath = settings.Path;
|
||||
|
||||
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
|
||||
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
|
||||
@@ -282,7 +270,11 @@ sealed class DeviceInfoCommand : Command
|
||||
|
||||
if(devInfo.AtaIdentify != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_ata_identify.bin", "ATA IDENTIFY", devInfo.AtaIdentify);
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
settings.OutputPrefix,
|
||||
"_ata_identify.bin",
|
||||
"ATA IDENTIFY",
|
||||
devInfo.AtaIdentify);
|
||||
|
||||
Identify.IdentifyDevice? decodedIdentify = Identify.Decode(devInfo.AtaIdentify);
|
||||
AaruConsole.WriteLine(Decoders.ATA.Identify.Prettify(decodedIdentify));
|
||||
@@ -323,8 +315,8 @@ sealed class DeviceInfoCommand : Command
|
||||
if((devInfo.AtaMcptError.Value.DeviceHead & 0x08) == 0x08)
|
||||
AaruConsole.WriteLine(Localization.Core.Media_card_is_write_protected);
|
||||
|
||||
var specificData = (ushort)(devInfo.AtaMcptError.Value.CylinderHigh * 0x100 +
|
||||
devInfo.AtaMcptError.Value.CylinderLow);
|
||||
ushort specificData = (ushort)(devInfo.AtaMcptError.Value.CylinderHigh * 0x100 +
|
||||
devInfo.AtaMcptError.Value.CylinderLow);
|
||||
|
||||
if(specificData != 0) AaruConsole.WriteLine(Localization.Core.Card_specific_data_0, specificData);
|
||||
}
|
||||
@@ -368,7 +360,11 @@ sealed class DeviceInfoCommand : Command
|
||||
|
||||
if(devInfo.AtapiIdentify != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_atapi_identify.bin", "ATAPI IDENTIFY", devInfo.AtapiIdentify);
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
settings.OutputPrefix,
|
||||
"_atapi_identify.bin",
|
||||
"ATAPI IDENTIFY",
|
||||
devInfo.AtapiIdentify);
|
||||
|
||||
AaruConsole.WriteLine(Decoders.ATA.Identify.Prettify(devInfo.AtapiIdentify));
|
||||
}
|
||||
@@ -378,7 +374,7 @@ sealed class DeviceInfoCommand : Command
|
||||
if(dev.Type != DeviceType.ATAPI) AaruConsole.WriteLine($"[bold]{UI.Title_SCSI_device}[/]");
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_scsi_inquiry.bin",
|
||||
UI.Title_SCSI_INQUIRY,
|
||||
devInfo.ScsiInquiryData);
|
||||
@@ -396,7 +392,7 @@ sealed class DeviceInfoCommand : Command
|
||||
page.Key,
|
||||
EVPD.DecodeASCIIPage(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, page.Value);
|
||||
DataFile.WriteTo(MODULE_NAME, settings.OutputPrefix, page.Value);
|
||||
|
||||
break;
|
||||
case 0x80:
|
||||
@@ -404,7 +400,7 @@ sealed class DeviceInfoCommand : Command
|
||||
EVPD.DecodePage80(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -414,7 +410,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_81(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -425,7 +421,7 @@ sealed class DeviceInfoCommand : Command
|
||||
EVPD.DecodePage82(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -435,7 +431,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_83(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -445,7 +441,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_84(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -455,7 +451,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_85(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -465,7 +461,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_86(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -475,7 +471,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_89(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -485,7 +481,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_B0(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -496,7 +492,7 @@ sealed class DeviceInfoCommand : Command
|
||||
EVPD.DecodePageB1(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -507,7 +503,7 @@ sealed class DeviceInfoCommand : Command
|
||||
EVPD.DecodePageB2(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -518,7 +514,7 @@ sealed class DeviceInfoCommand : Command
|
||||
EVPD.DecodePageB3(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -529,7 +525,7 @@ sealed class DeviceInfoCommand : Command
|
||||
EVPD.DecodePageB4(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -542,7 +538,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Quantum(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -555,7 +551,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Seagate(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -568,7 +564,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_IBM(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -581,7 +577,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C1_IBM(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -595,7 +591,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_C1_Certance(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -609,7 +605,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -623,7 +619,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_to_C5_HP(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -636,7 +632,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_DF_Certance(page.Value));
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -651,7 +647,7 @@ sealed class DeviceInfoCommand : Command
|
||||
page.Key);
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
$"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h",
|
||||
page.Value);
|
||||
@@ -665,7 +661,7 @@ sealed class DeviceInfoCommand : Command
|
||||
if(devInfo.ScsiModeSense6 != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_scsi_modesense6.bin",
|
||||
"SCSI MODE SENSE",
|
||||
devInfo.ScsiModeSense6);
|
||||
@@ -674,7 +670,7 @@ sealed class DeviceInfoCommand : Command
|
||||
if(devInfo.ScsiModeSense10 != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_scsi_modesense10.bin",
|
||||
"SCSI MODE SENSE",
|
||||
devInfo.ScsiModeSense10);
|
||||
@@ -690,7 +686,7 @@ sealed class DeviceInfoCommand : Command
|
||||
if(devInfo.MmcConfiguration != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_mmc_getconfiguration.bin",
|
||||
"MMC GET CONFIGURATION",
|
||||
devInfo.MmcConfiguration);
|
||||
@@ -966,7 +962,7 @@ sealed class DeviceInfoCommand : Command
|
||||
if(devInfo.PlextorFeatures?.Eeprom != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_plextor_eeprom.bin",
|
||||
"PLEXTOR READ EEPROM",
|
||||
devInfo.PlextorFeatures.Eeprom);
|
||||
@@ -1144,7 +1140,7 @@ sealed class DeviceInfoCommand : Command
|
||||
if(devInfo.BlockLimits != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_ssc_readblocklimits.bin",
|
||||
"SSC READ BLOCK LIMITS",
|
||||
devInfo.BlockLimits);
|
||||
@@ -1156,7 +1152,7 @@ sealed class DeviceInfoCommand : Command
|
||||
if(devInfo.DensitySupport != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_ssc_reportdensitysupport.bin",
|
||||
"SSC REPORT DENSITY SUPPORT",
|
||||
devInfo.DensitySupport);
|
||||
@@ -1171,7 +1167,7 @@ sealed class DeviceInfoCommand : Command
|
||||
if(devInfo.MediumDensitySupport != null)
|
||||
{
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_ssc_reportdensitysupport_medium.bin",
|
||||
"SSC REPORT DENSITY SUPPORT (MEDIUM)",
|
||||
devInfo.MediumDensitySupport);
|
||||
@@ -1190,26 +1186,26 @@ sealed class DeviceInfoCommand : Command
|
||||
{
|
||||
case DeviceType.MMC:
|
||||
{
|
||||
var noInfo = true;
|
||||
bool noInfo = true;
|
||||
|
||||
if(devInfo.CID != null)
|
||||
{
|
||||
noInfo = false;
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_mmc_cid.bin", "MMC CID", devInfo.CID);
|
||||
DataFile.WriteTo(MODULE_NAME, settings.OutputPrefix, "_mmc_cid.bin", "MMC CID", devInfo.CID);
|
||||
AaruConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyCID(devInfo.CID));
|
||||
}
|
||||
|
||||
if(devInfo.CSD != null)
|
||||
{
|
||||
noInfo = false;
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_mmc_csd.bin", "MMC CSD", devInfo.CSD);
|
||||
DataFile.WriteTo(MODULE_NAME, settings.OutputPrefix, "_mmc_csd.bin", "MMC CSD", devInfo.CSD);
|
||||
AaruConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyCSD(devInfo.CSD));
|
||||
}
|
||||
|
||||
if(devInfo.OCR != null)
|
||||
{
|
||||
noInfo = false;
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_mmc_ocr.bin", "MMC OCR", devInfo.OCR);
|
||||
DataFile.WriteTo(MODULE_NAME, settings.OutputPrefix, "_mmc_ocr.bin", "MMC OCR", devInfo.OCR);
|
||||
AaruConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyOCR(devInfo.OCR));
|
||||
}
|
||||
|
||||
@@ -1218,7 +1214,7 @@ sealed class DeviceInfoCommand : Command
|
||||
noInfo = false;
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
outputPrefix,
|
||||
settings.OutputPrefix,
|
||||
"_mmc_ecsd.bin",
|
||||
"MMC Extended CSD",
|
||||
devInfo.ExtendedCSD);
|
||||
@@ -1232,13 +1228,17 @@ sealed class DeviceInfoCommand : Command
|
||||
break;
|
||||
case DeviceType.SecureDigital:
|
||||
{
|
||||
var noInfo = true;
|
||||
bool noInfo = true;
|
||||
|
||||
if(devInfo.CID != null)
|
||||
{
|
||||
noInfo = false;
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_sd_cid.bin", "SecureDigital CID", devInfo.CID);
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
settings.OutputPrefix,
|
||||
"_sd_cid.bin",
|
||||
"SecureDigital CID",
|
||||
devInfo.CID);
|
||||
|
||||
AaruConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyCID(devInfo.CID));
|
||||
}
|
||||
@@ -1247,7 +1247,11 @@ sealed class DeviceInfoCommand : Command
|
||||
{
|
||||
noInfo = false;
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_sd_csd.bin", "SecureDigital CSD", devInfo.CSD);
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
settings.OutputPrefix,
|
||||
"_sd_csd.bin",
|
||||
"SecureDigital CSD",
|
||||
devInfo.CSD);
|
||||
|
||||
AaruConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyCSD(devInfo.CSD));
|
||||
}
|
||||
@@ -1256,7 +1260,11 @@ sealed class DeviceInfoCommand : Command
|
||||
{
|
||||
noInfo = false;
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_sd_ocr.bin", "SecureDigital OCR", devInfo.OCR);
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
settings.OutputPrefix,
|
||||
"_sd_ocr.bin",
|
||||
"SecureDigital OCR",
|
||||
devInfo.OCR);
|
||||
|
||||
AaruConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyOCR(devInfo.OCR));
|
||||
}
|
||||
@@ -1265,7 +1273,11 @@ sealed class DeviceInfoCommand : Command
|
||||
{
|
||||
noInfo = false;
|
||||
|
||||
DataFile.WriteTo(MODULE_NAME, outputPrefix, "_sd_scr.bin", "SecureDigital SCR", devInfo.SCR);
|
||||
DataFile.WriteTo(MODULE_NAME,
|
||||
settings.OutputPrefix,
|
||||
"_sd_scr.bin",
|
||||
"SecureDigital SCR",
|
||||
devInfo.SCR);
|
||||
|
||||
AaruConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifySCR(devInfo.SCR));
|
||||
}
|
||||
@@ -1281,7 +1293,7 @@ sealed class DeviceInfoCommand : Command
|
||||
AaruConsole.WriteLine();
|
||||
|
||||
// Open main database
|
||||
var ctx = AaruContext.Create(Settings.Settings.MainDbPath);
|
||||
var ctx = AaruContext.Create(Aaru.Settings.Settings.MainDbPath);
|
||||
|
||||
// Search for device in main database
|
||||
Aaru.Database.Models.Device dbDev =
|
||||
@@ -1313,4 +1325,19 @@ sealed class DeviceInfoCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : DeviceFamily
|
||||
{
|
||||
[Description("Prefix for saving binary information from device.")]
|
||||
[CommandOption("-w|--output-prefix")]
|
||||
public string OutputPrefix { get; init; }
|
||||
|
||||
[Description("Device path")]
|
||||
[CommandArgument(0, "<device-path>")]
|
||||
public string Path { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,9 +30,7 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.Console;
|
||||
@@ -41,30 +39,20 @@ using Aaru.Devices;
|
||||
using Aaru.Localization;
|
||||
using JetBrains.Annotations;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Device;
|
||||
|
||||
sealed class ListDevicesCommand : Command
|
||||
sealed class ListDevicesCommand : Command<ListDevicesCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "List-Devices command";
|
||||
|
||||
public ListDevicesCommand() : base("list", UI.Device_List_Command_Description)
|
||||
{
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
Description = UI.aaruremote_host,
|
||||
Name = "aaru-remote-host"
|
||||
});
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, [CanBeNull] string aaruRemoteHost)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -82,7 +70,7 @@ sealed class ListDevicesCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -95,8 +83,8 @@ sealed class ListDevicesCommand : Command
|
||||
|
||||
Statistics.AddCommand("list-devices");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
DeviceInfo[] devices = Devices.Device.ListDevices(out bool isRemote,
|
||||
out string serverApplication,
|
||||
@@ -104,7 +92,7 @@ sealed class ListDevicesCommand : Command
|
||||
out string serverOperatingSystem,
|
||||
out string serverOperatingSystemVersion,
|
||||
out string serverArchitecture,
|
||||
aaruRemoteHost);
|
||||
settings.AaruRemoteHost);
|
||||
|
||||
if(isRemote)
|
||||
{
|
||||
@@ -142,4 +130,17 @@ sealed class ListDevicesCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : DeviceFamily
|
||||
{
|
||||
[CanBeNull]
|
||||
[Description("aaruremote host")]
|
||||
[CommandArgument(0, "[aaru-remote-host]")]
|
||||
[DefaultValue(null)]
|
||||
public string AaruRemoteHost { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
@@ -46,50 +45,21 @@ using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using JetBrains.Annotations;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using FileAttributes = Aaru.CommonTypes.Structs.FileAttributes;
|
||||
|
||||
namespace Aaru.Commands.Filesystem;
|
||||
|
||||
sealed class ExtractFilesCommand : Command
|
||||
sealed class ExtractFilesCommand : Command<ExtractFilesCommand.Settings>
|
||||
{
|
||||
const long BUFFER_SIZE = 16777216;
|
||||
const string MODULE_NAME = "Extract-Files command";
|
||||
|
||||
public ExtractFilesCommand() : base("extract", UI.Filesystem_Extract_Command_Description)
|
||||
{
|
||||
Add(new Option<string>(["--encoding", "-e"], () => null, UI.Name_of_character_encoding_to_use));
|
||||
|
||||
Add(new Option<string>(["--options", "-O"],
|
||||
() => null,
|
||||
UI.Comma_separated_name_value_pairs_of_filesystem_options));
|
||||
|
||||
Add(new Option<bool>(["--xattrs", "-x"], () => false, UI.Extract_extended_attributes_if_present));
|
||||
|
||||
Add(new Option<string>(["--namespace", "-n"], () => null, UI.Namespace_to_use_for_filenames));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Disc_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Directory_where_extracted_files_will_be_created,
|
||||
Name = "output-dir"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string encoding, bool xattrs, string imagePath,
|
||||
string @namespace, string outputDir, string options)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -107,7 +77,7 @@ sealed class ExtractFilesCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -120,29 +90,29 @@ sealed class ExtractFilesCommand : Command
|
||||
|
||||
Statistics.AddCommand("extract-files");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--options={0}", Markup.Escape(options ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output={0}", Markup.Escape(outputDir ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--xattrs={0}", xattrs);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(settings.Encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--options={0}", Markup.Escape(settings.Options ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output={0}", Markup.Escape(settings.OutputDir ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--xattrs={0}", settings.Xattrs);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
|
||||
Dictionary<string, string> parsedOptions = Options.Parse(settings.Options);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, UI.Parsed_options);
|
||||
|
||||
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "{0} = {1}", parsedOption.Key, parsedOption.Value);
|
||||
|
||||
parsedOptions.Add("debug", debug.ToString());
|
||||
parsedOptions.Add("debug", settings.Debug.ToString());
|
||||
|
||||
if(inputFilter == null)
|
||||
{
|
||||
@@ -153,13 +123,13 @@ sealed class ExtractFilesCommand : Command
|
||||
|
||||
Encoding encodingClass = null;
|
||||
|
||||
if(encoding != null)
|
||||
if(settings.Encoding != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(settings.Encoding);
|
||||
|
||||
if(verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
if(settings.Verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
@@ -197,26 +167,26 @@ sealed class ExtractFilesCommand : Command
|
||||
return (int)ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AaruConsole.VerboseWriteLine(UI.Image_format_identified_by_0_1, imageFormat.Name, imageFormat.Id);
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Image_format_identified_by_0, imageFormat.Name);
|
||||
|
||||
if(outputDir == null)
|
||||
if(settings.OutputDir == null)
|
||||
{
|
||||
AaruConsole.WriteLine(UI.Output_directory_missing);
|
||||
|
||||
return (int)ErrorNumber.MissingArgument;
|
||||
}
|
||||
|
||||
if(Directory.Exists(outputDir) || File.Exists(outputDir))
|
||||
if(Directory.Exists(settings.OutputDir) || File.Exists(settings.OutputDir))
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Destination_exists_aborting);
|
||||
|
||||
return (int)ErrorNumber.FileExists;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(outputDir);
|
||||
Directory.CreateDirectory(settings.OutputDir);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -288,7 +258,7 @@ sealed class ExtractFilesCommand : Command
|
||||
|
||||
AaruConsole.WriteLine(UI._0_partitions_found, partitions.Count);
|
||||
|
||||
for(var i = 0; i < partitions.Count; i++)
|
||||
for(int i = 0; i < partitions.Count; i++)
|
||||
{
|
||||
AaruConsole.WriteLine();
|
||||
AaruConsole.WriteLine($"[bold]{string.Format(UI.Partition_0, partitions[i].Sequence)}[/]");
|
||||
@@ -326,7 +296,11 @@ sealed class ExtractFilesCommand : Command
|
||||
{
|
||||
ctx.AddTask(UI.Mounting_filesystem).IsIndeterminate();
|
||||
|
||||
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace);
|
||||
error = fs.Mount(imageFormat,
|
||||
partitions[i],
|
||||
encodingClass,
|
||||
parsedOptions,
|
||||
settings.Namespace);
|
||||
});
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
@@ -335,7 +309,7 @@ sealed class ExtractFilesCommand : Command
|
||||
? "NO NAME"
|
||||
: fs.Metadata.VolumeName;
|
||||
|
||||
ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs);
|
||||
ExtractFilesInDir("/", fs, volumeName, settings.OutputDir, settings.Xattrs);
|
||||
|
||||
Statistics.AddFilesystem(fs.Metadata.Type);
|
||||
}
|
||||
@@ -354,7 +328,12 @@ sealed class ExtractFilesCommand : Command
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Mounting_filesystem).IsIndeterminate();
|
||||
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace);
|
||||
|
||||
error = fs.Mount(imageFormat,
|
||||
partitions[i],
|
||||
encodingClass,
|
||||
parsedOptions,
|
||||
settings.Namespace);
|
||||
});
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
@@ -363,7 +342,7 @@ sealed class ExtractFilesCommand : Command
|
||||
? "NO NAME"
|
||||
: fs.Metadata.VolumeName;
|
||||
|
||||
ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs);
|
||||
ExtractFilesInDir("/", fs, volumeName, settings.OutputDir, settings.Xattrs);
|
||||
|
||||
Statistics.AddFilesystem(fs.Metadata.Type);
|
||||
}
|
||||
@@ -630,7 +609,7 @@ sealed class ExtractFilesCommand : Command
|
||||
ctx.AddTask(string.Format(UI.Reading_file_0, Markup.Escape(entry)));
|
||||
|
||||
task.MaxValue = stat.Length;
|
||||
var outBuf = new byte[BUFFER_SIZE];
|
||||
byte[] outBuf = new byte[BUFFER_SIZE];
|
||||
error = fs.OpenFile(path + "/" + entry, out IFileNode fileNode);
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
@@ -710,4 +689,34 @@ sealed class ExtractFilesCommand : Command
|
||||
|
||||
fs.CloseDir(node);
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : FilesystemFamily
|
||||
{
|
||||
[CommandOption("-e|--encoding")]
|
||||
[Description("Name of character encoding to use.")]
|
||||
[DefaultValue(null)]
|
||||
public string Encoding { get; init; }
|
||||
[CommandOption("-O|--options")]
|
||||
[Description("Comma separated name=value pairs of options to pass to filesystem plugin.")]
|
||||
[DefaultValue(null)]
|
||||
public string Options { get; init; }
|
||||
[CommandOption("-x|--xattrs")]
|
||||
[Description("Extract extended attributes if present.")]
|
||||
[DefaultValue(false)]
|
||||
public bool Xattrs { get; init; }
|
||||
[CommandOption("-n|--namespace")]
|
||||
[Description("Namespace to use for filenames.")]
|
||||
[DefaultValue(null)]
|
||||
public string Namespace { get; init; }
|
||||
[CommandArgument(1, "<output-dir>")]
|
||||
[Description("Directory where extracted files will be created. Will abort if it exists")]
|
||||
public string OutputDir { get; init; }
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
[Description("Disc image path")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,21 +30,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.CommandLine;
|
||||
using Aaru.Localization;
|
||||
|
||||
namespace Aaru.Commands.Filesystem;
|
||||
|
||||
sealed class FilesystemFamily : Command
|
||||
{
|
||||
public FilesystemFamily() : base("filesystem", UI.Filesystem_Command_Family_Description)
|
||||
{
|
||||
AddAlias("fi");
|
||||
AddAlias("fs");
|
||||
|
||||
AddCommand(new FilesystemInfoCommand());
|
||||
AddCommand(new ListOptionsCommand());
|
||||
AddCommand(new ExtractFilesCommand());
|
||||
AddCommand(new LsCommand());
|
||||
}
|
||||
}
|
||||
class FilesystemFamily : BaseSettings {}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.AaruMetadata;
|
||||
@@ -43,40 +42,20 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using Partition = Aaru.CommonTypes.Partition;
|
||||
|
||||
namespace Aaru.Commands.Filesystem;
|
||||
|
||||
sealed class FilesystemInfoCommand : Command
|
||||
sealed class FilesystemInfoCommand : Command<FilesystemInfoCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Fs-info command";
|
||||
|
||||
public FilesystemInfoCommand() : base("info", UI.Filesystem_Info_Command_Description)
|
||||
{
|
||||
Add(new Option<string>(["--encoding", "-e"], () => null, UI.Name_of_character_encoding_to_use));
|
||||
|
||||
Add(new Option<bool>(["--filesystems", "-f"],
|
||||
() => true,
|
||||
UI.Searches_and_prints_information_about_filesystems));
|
||||
|
||||
Add(new Option<bool>(["--partitions", "-p"], () => true, UI.Searches_and_interprets_partitions));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Media_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(typeof(FilesystemInfoCommand).GetMethod(nameof(Invoke)));
|
||||
}
|
||||
|
||||
public static int Invoke(bool verbose, bool debug, string encoding, bool filesystems, bool partitions,
|
||||
string imagePath)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -94,7 +73,7 @@ sealed class FilesystemInfoCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -107,19 +86,19 @@ sealed class FilesystemInfoCommand : Command
|
||||
|
||||
Statistics.AddCommand("fs-info");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--filesystems={0}", filesystems);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--partitions={0}", partitions);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(settings.Encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--filesystems={0}", settings.Filesystems);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--partitions={0}", settings.Partitions);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -131,13 +110,13 @@ sealed class FilesystemInfoCommand : Command
|
||||
|
||||
Encoding encodingClass = null;
|
||||
|
||||
if(encoding != null)
|
||||
if(settings.Encoding != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(settings.Encoding);
|
||||
|
||||
if(verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
if(settings.Verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
@@ -149,7 +128,7 @@ sealed class FilesystemInfoCommand : Command
|
||||
|
||||
PluginRegister plugins = PluginRegister.Singleton;
|
||||
|
||||
var checkRaw = false;
|
||||
bool checkRaw = false;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -177,7 +156,7 @@ sealed class FilesystemInfoCommand : Command
|
||||
return (int)ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AaruConsole.VerboseWriteLine(UI.Image_format_identified_by_0_1, imageFormat.Name, imageFormat.Id);
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Image_format_identified_by_0, imageFormat.Name);
|
||||
@@ -202,7 +181,7 @@ sealed class FilesystemInfoCommand : Command
|
||||
return (int)opened;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
ImageInfo.PrintImageInfo(imageFormat);
|
||||
AaruConsole.WriteLine();
|
||||
@@ -225,7 +204,7 @@ sealed class FilesystemInfoCommand : Command
|
||||
IFilesystem fs;
|
||||
string information;
|
||||
|
||||
if(partitions)
|
||||
if(settings.Partitions)
|
||||
{
|
||||
List<Partition> partitionsList = null;
|
||||
|
||||
@@ -241,7 +220,7 @@ sealed class FilesystemInfoCommand : Command
|
||||
{
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, UI.No_partitions_found);
|
||||
|
||||
if(!filesystems)
|
||||
if(!settings.Filesystems)
|
||||
{
|
||||
AaruConsole.WriteLine(UI.No_partitions_found_not_searching_for_filesystems);
|
||||
|
||||
@@ -254,7 +233,7 @@ sealed class FilesystemInfoCommand : Command
|
||||
{
|
||||
AaruConsole.WriteLine(UI._0_partitions_found, partitionsList.Count);
|
||||
|
||||
for(var i = 0; i < partitionsList.Count; i++)
|
||||
for(int i = 0; i < partitionsList.Count; i++)
|
||||
{
|
||||
Table table = new()
|
||||
{
|
||||
@@ -283,7 +262,7 @@ sealed class FilesystemInfoCommand : Command
|
||||
|
||||
AnsiConsole.Write(table);
|
||||
|
||||
if(!filesystems) continue;
|
||||
if(!settings.Filesystems) continue;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
@@ -425,4 +404,27 @@ sealed class FilesystemInfoCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : FilesystemFamily
|
||||
{
|
||||
[Description("Name of character encoding to use.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-e|--encoding")]
|
||||
public string Encoding { get; init; }
|
||||
[Description("Searches and prints information about filesystems.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-p|--partitions")]
|
||||
public bool Partitions { get; init; }
|
||||
[Description("Searches and interprets partitions.")]
|
||||
[CommandOption("-f|--filesystems")]
|
||||
[DefaultValue(true)]
|
||||
public bool Filesystems { get; init; }
|
||||
[Description("Media image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes;
|
||||
@@ -45,43 +44,19 @@ using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using JetBrains.Annotations;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Filesystem;
|
||||
|
||||
sealed class LsCommand : Command
|
||||
sealed class LsCommand : Command<LsCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Ls command";
|
||||
|
||||
public LsCommand() : base("list", UI.Filesystem_List_Command_Description)
|
||||
{
|
||||
AddAlias("ls");
|
||||
|
||||
Add(new Option<string>(["--encoding", "-e"], () => null, UI.Name_of_character_encoding_to_use));
|
||||
|
||||
Add(new Option<bool>(["--long-format", "-l"], () => true, UI.Use_long_format));
|
||||
|
||||
Add(new Option<string>(["--options", "-O"],
|
||||
() => null,
|
||||
UI.Comma_separated_name_value_pairs_of_filesystem_options));
|
||||
|
||||
Add(new Option<string>(["--namespace", "-n"], () => null, UI.Namespace_to_use_for_filenames));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Media_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string encoding, string imagePath, bool longFormat,
|
||||
string @namespace, string options)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -99,7 +74,7 @@ sealed class LsCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -110,11 +85,11 @@ sealed class LsCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--options={0}", Markup.Escape(options ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(settings.Encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--options={0}", Markup.Escape(settings.Options ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
Statistics.AddCommand("ls");
|
||||
|
||||
IFilter inputFilter = null;
|
||||
@@ -122,16 +97,16 @@ sealed class LsCommand : Command
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
|
||||
Dictionary<string, string> parsedOptions = Options.Parse(settings.Options);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, UI.Parsed_options);
|
||||
|
||||
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "{0} = {1}", parsedOption.Key, parsedOption.Value);
|
||||
|
||||
parsedOptions.Add("debug", debug.ToString());
|
||||
parsedOptions.Add("debug", settings.Debug.ToString());
|
||||
|
||||
if(inputFilter == null)
|
||||
{
|
||||
@@ -142,13 +117,13 @@ sealed class LsCommand : Command
|
||||
|
||||
Encoding encodingClass = null;
|
||||
|
||||
if(encoding != null)
|
||||
if(settings.Encoding != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(settings.Encoding);
|
||||
|
||||
if(verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
if(settings.Verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
@@ -186,7 +161,7 @@ sealed class LsCommand : Command
|
||||
return (int)ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AaruConsole.VerboseWriteLine(UI.Image_format_identified_by_0_1, imageFormat.Name, imageFormat.Id);
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Image_format_identified_by_0, imageFormat.Name);
|
||||
@@ -261,7 +236,7 @@ sealed class LsCommand : Command
|
||||
|
||||
AaruConsole.WriteLine(UI._0_partitions_found, partitions.Count);
|
||||
|
||||
for(var i = 0; i < partitions.Count; i++)
|
||||
for(int i = 0; i < partitions.Count; i++)
|
||||
{
|
||||
AaruConsole.WriteLine();
|
||||
AaruConsole.WriteLine($"[bold]{string.Format(UI.Partition_0, partitions[i].Sequence)}[/]");
|
||||
@@ -298,12 +273,16 @@ sealed class LsCommand : Command
|
||||
{
|
||||
ctx.AddTask(UI.Mounting_filesystem).IsIndeterminate();
|
||||
|
||||
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace);
|
||||
error = fs.Mount(imageFormat,
|
||||
partitions[i],
|
||||
encodingClass,
|
||||
parsedOptions,
|
||||
settings.Namespace);
|
||||
});
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
{
|
||||
ListFilesInDir("/", fs, longFormat);
|
||||
ListFilesInDir("/", fs, settings.LongFormat);
|
||||
|
||||
Statistics.AddFilesystem(fs.Metadata.Type);
|
||||
}
|
||||
@@ -322,12 +301,17 @@ sealed class LsCommand : Command
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Mounting_filesystem).IsIndeterminate();
|
||||
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace);
|
||||
|
||||
error = fs.Mount(imageFormat,
|
||||
partitions[i],
|
||||
encodingClass,
|
||||
parsedOptions,
|
||||
settings.Namespace);
|
||||
});
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
{
|
||||
ListFilesInDir("/", fs, longFormat);
|
||||
ListFilesInDir("/", fs, settings.LongFormat);
|
||||
|
||||
Statistics.AddFilesystem(fs.Metadata.Type);
|
||||
}
|
||||
@@ -442,4 +426,31 @@ sealed class LsCommand : Command
|
||||
stats.Where(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == true))
|
||||
ListFilesInDir(path + "/" + subdirectory.Key, fs, longFormat);
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : FilesystemFamily
|
||||
{
|
||||
[Description("Name of character encoding to use.")]
|
||||
[CommandOption("-e|--encoding")]
|
||||
[DefaultValue(null)]
|
||||
public string Encoding { get; init; }
|
||||
[Description("Use long format.")]
|
||||
[CommandOption("-l|--long-format")]
|
||||
[DefaultValue(true)]
|
||||
public bool LongFormat { get; init; }
|
||||
[Description("Comma separated name=value pairs of options to pass to filesystem plugin.")]
|
||||
[CommandOption("-O|--options")]
|
||||
[DefaultValue(null)]
|
||||
public string Options { get; init; }
|
||||
[Description("Namespace to use for filenames.")]
|
||||
[CommandOption("-n|--namespace")]
|
||||
[DefaultValue(null)]
|
||||
public string Namespace { get; init; }
|
||||
[Description("Media image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -31,8 +31,6 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -42,21 +40,20 @@ using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using JetBrains.Annotations;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Filesystem;
|
||||
|
||||
sealed class ListOptionsCommand : Command
|
||||
sealed class ListOptionsCommand : Command<ListOptionsCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "List-Options command";
|
||||
|
||||
public ListOptionsCommand() : base("options", UI.Filesystem_Options_Command_Description) =>
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
|
||||
public static int Invoke(bool debug, bool verbose)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -74,7 +71,7 @@ sealed class ListOptionsCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -85,8 +82,8 @@ sealed class ListOptionsCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
Statistics.AddCommand("list-options");
|
||||
|
||||
PluginRegister plugins = PluginRegister.Singleton;
|
||||
@@ -141,4 +138,10 @@ sealed class ListOptionsCommand : Command
|
||||
|
||||
return type == typeof(string) ? UI.TypeToString_string : type.ToString();
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : FilesystemFamily {}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,9 +30,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -41,21 +38,20 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands;
|
||||
|
||||
sealed class FormatsCommand : Command
|
||||
sealed class FormatsCommand : Command<FormatsCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Formats command";
|
||||
|
||||
public FormatsCommand() : base("formats", UI.List_Formats_Command_Description) =>
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
|
||||
public static int Invoke(bool verbose, bool debug)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -73,7 +69,7 @@ sealed class FormatsCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -86,8 +82,8 @@ sealed class FormatsCommand : Command
|
||||
|
||||
Statistics.AddCommand("formats");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
PluginRegister plugins = PluginRegister.Singleton;
|
||||
|
||||
@@ -96,13 +92,13 @@ sealed class FormatsCommand : Command
|
||||
Title = new TableTitle(string.Format(UI.Supported_filters_0, PluginRegister.Singleton.Filters.Count))
|
||||
};
|
||||
|
||||
if(verbose) table.AddColumn(UI.Title_GUID);
|
||||
if(settings.Verbose) table.AddColumn(UI.Title_GUID);
|
||||
|
||||
table.AddColumn(UI.Title_Filter);
|
||||
|
||||
foreach(IFilter filter in PluginRegister.Singleton.Filters.Values)
|
||||
{
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
table.AddRow(filter.Id.ToString(), Markup.Escape(filter.Name));
|
||||
else
|
||||
table.AddRow(Markup.Escape(filter.Name));
|
||||
@@ -119,14 +115,14 @@ sealed class FormatsCommand : Command
|
||||
.ContainsKey(t.Key))))
|
||||
};
|
||||
|
||||
if(verbose) table.AddColumn(UI.Title_GUID);
|
||||
if(settings.Verbose) table.AddColumn(UI.Title_GUID);
|
||||
|
||||
table.AddColumn(UI.Title_Media_image_format);
|
||||
|
||||
foreach(IMediaImage imagePlugin in
|
||||
plugins.MediaImages.Values.Where(t => !plugins.WritableImages.ContainsKey(t.Name)))
|
||||
{
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
table.AddRow(imagePlugin.Id.ToString(), Markup.Escape(imagePlugin.Name));
|
||||
else
|
||||
table.AddRow(Markup.Escape(imagePlugin.Name));
|
||||
@@ -141,7 +137,7 @@ sealed class FormatsCommand : Command
|
||||
Title = new TableTitle(string.Format(UI.Read_write_media_image_formats_0, plugins.WritableImages.Count))
|
||||
};
|
||||
|
||||
if(verbose) table.AddColumn(UI.Title_GUID);
|
||||
if(settings.Verbose) table.AddColumn(UI.Title_GUID);
|
||||
|
||||
table.AddColumn(UI.Title_Media_image_format);
|
||||
|
||||
@@ -149,7 +145,7 @@ sealed class FormatsCommand : Command
|
||||
{
|
||||
if(plugin is null) continue;
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
table.AddRow(plugin.Id.ToString(), Markup.Escape(plugin.Name));
|
||||
else
|
||||
table.AddRow(Markup.Escape(plugin.Name));
|
||||
@@ -170,13 +166,13 @@ sealed class FormatsCommand : Command
|
||||
idOnlyFilesystems.Count))
|
||||
};
|
||||
|
||||
if(verbose) table.AddColumn(UI.Title_GUID);
|
||||
if(settings.Verbose) table.AddColumn(UI.Title_GUID);
|
||||
|
||||
table.AddColumn(UI.Title_Filesystem);
|
||||
|
||||
foreach(IFilesystem fs in idOnlyFilesystems)
|
||||
{
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
table.AddRow(fs.Id.ToString(), Markup.Escape(fs.Name));
|
||||
else
|
||||
table.AddRow(Markup.Escape(fs.Name));
|
||||
@@ -192,7 +188,7 @@ sealed class FormatsCommand : Command
|
||||
plugins.ReadOnlyFilesystems.Count))
|
||||
};
|
||||
|
||||
if(verbose) table.AddColumn(UI.Title_GUID);
|
||||
if(settings.Verbose) table.AddColumn(UI.Title_GUID);
|
||||
|
||||
table.AddColumn(UI.Title_Filesystem);
|
||||
|
||||
@@ -200,7 +196,7 @@ sealed class FormatsCommand : Command
|
||||
{
|
||||
if(fs is null) continue;
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
table.AddRow(fs.Id.ToString(), Markup.Escape(fs.Name));
|
||||
else
|
||||
table.AddRow(Markup.Escape(fs.Name));
|
||||
@@ -215,7 +211,7 @@ sealed class FormatsCommand : Command
|
||||
Title = new TableTitle(string.Format(UI.Supported_partitioning_schemes_0, plugins.Partitions.Count))
|
||||
};
|
||||
|
||||
if(verbose) table.AddColumn(UI.Title_GUID);
|
||||
if(settings.Verbose) table.AddColumn(UI.Title_GUID);
|
||||
|
||||
table.AddColumn(UI.Title_Scheme);
|
||||
|
||||
@@ -223,7 +219,7 @@ sealed class FormatsCommand : Command
|
||||
{
|
||||
if(plugin is null) continue;
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
table.AddRow(plugin.Id.ToString(), Markup.Escape(plugin.Name));
|
||||
else
|
||||
table.AddRow(Markup.Escape(plugin.Name));
|
||||
@@ -238,7 +234,7 @@ sealed class FormatsCommand : Command
|
||||
Title = new TableTitle(string.Format(UI.Supported_archive_formats_0, plugins.Archives.Count))
|
||||
};
|
||||
|
||||
if(verbose) table.AddColumn(UI.Title_GUID);
|
||||
if(settings.Verbose) table.AddColumn(UI.Title_GUID);
|
||||
|
||||
table.AddColumn("Archive format");
|
||||
|
||||
@@ -246,7 +242,7 @@ sealed class FormatsCommand : Command
|
||||
{
|
||||
if(archive is null) continue;
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
table.AddRow(archive.Id.ToString(), Markup.Escape(archive.Name));
|
||||
else
|
||||
table.AddRow(Markup.Escape(archive.Name));
|
||||
@@ -256,4 +252,10 @@ sealed class FormatsCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : BaseSettings {}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
@@ -42,10 +41,11 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class ChecksumCommand : Command
|
||||
sealed class ChecksumCommand : Command<ChecksumCommand.Settings>
|
||||
{
|
||||
// How many sectors to read at once
|
||||
const uint SECTORS_TO_READ = 256;
|
||||
@@ -54,51 +54,11 @@ sealed class ChecksumCommand : Command
|
||||
const int BYTES_TO_READ = 65536;
|
||||
const string MODULE_NAME = "Checksum command";
|
||||
|
||||
public ChecksumCommand() : base("checksum", UI.Image_Checksum_Command_Description)
|
||||
{
|
||||
AddAlias("chk");
|
||||
|
||||
Add(new Option<bool>(["--adler32", "-a"], () => false, UI.Calculates_Adler_32));
|
||||
|
||||
Add(new Option<bool>("--crc16", () => true, UI.Calculates_CRC16));
|
||||
|
||||
Add(new Option<bool>(["--crc32", "-c"], () => true, UI.Calculates_CRC32));
|
||||
|
||||
Add(new Option<bool>("--crc64", () => true, UI.Calculates_CRC64_ECMA));
|
||||
Add(new Option<bool>("--fletcher16", () => false, UI.Calculates_Fletcher_16));
|
||||
Add(new Option<bool>("--fletcher32", () => false, UI.Calculates_Fletcher_32));
|
||||
|
||||
Add(new Option<bool>(["--md5", "-m"], () => true, UI.Calculates_MD5));
|
||||
|
||||
Add(new Option<bool>(["--separated-tracks", "-t"], () => true, UI.Checksums_each_track_separately));
|
||||
|
||||
Add(new Option<bool>(["--sha1", "-s"], () => true, UI.Calculates_SHA1));
|
||||
|
||||
Add(new Option<bool>("--sha256", () => false, UI.Calculates_SHA256));
|
||||
Add(new Option<bool>("--sha384", () => false, UI.Calculates_SHA384));
|
||||
Add(new Option<bool>("--sha512", () => true, UI.Calculates_SHA512));
|
||||
|
||||
Add(new Option<bool>(["--spamsum", "-f"], () => true, UI.Calculates_SpamSum_fuzzy_hash));
|
||||
|
||||
Add(new Option<bool>(["--whole-disc", "-w"], () => true, UI.Checksums_the_whole_disc));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Media_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public 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)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -116,7 +76,7 @@ sealed class ChecksumCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -129,30 +89,30 @@ sealed class ChecksumCommand : Command
|
||||
|
||||
Statistics.AddCommand("checksum");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--adler32={0}", adler32);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--crc16={0}", crc16);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--crc32={0}", crc32);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--crc64={0}", crc64);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fletcher16={0}", fletcher16);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fletcher32={0}", fletcher32);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--md5={0}", md5);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--separated-tracks={0}", separatedTracks);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sha1={0}", sha1);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sha256={0}", sha256);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sha384={0}", sha384);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sha512={0}", sha512);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--spamsum={0}", spamSum);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--whole-disc={0}", wholeDisc);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--adler32={0}", settings.Adler32);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--crc16={0}", settings.Crc16);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--crc32={0}", settings.Crc32);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--crc64={0}", settings.Crc64);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fletcher16={0}", settings.Fletcher16);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fletcher32={0}", settings.Fletcher32);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--md5={0}", settings.Md5);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--separated-tracks={0}", settings.SeparatedTracks);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sha1={0}", settings.Sha1);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sha256={0}", settings.Sha256);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sha384={0}", settings.Sha384);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sha512={0}", settings.Sha512);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--spamsum={0}", settings.SpamSum);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--whole-disc={0}", settings.WholeDisc);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -198,29 +158,29 @@ sealed class ChecksumCommand : Command
|
||||
Statistics.AddFilter(inputFilter.Name);
|
||||
var enabledChecksums = new EnableChecksum();
|
||||
|
||||
if(adler32) enabledChecksums |= EnableChecksum.Adler32;
|
||||
if(settings.Adler32) enabledChecksums |= EnableChecksum.Adler32;
|
||||
|
||||
if(crc16) enabledChecksums |= EnableChecksum.Crc16;
|
||||
if(settings.Crc16) enabledChecksums |= EnableChecksum.Crc16;
|
||||
|
||||
if(crc32) enabledChecksums |= EnableChecksum.Crc32;
|
||||
if(settings.Crc32) enabledChecksums |= EnableChecksum.Crc32;
|
||||
|
||||
if(crc64) enabledChecksums |= EnableChecksum.Crc64;
|
||||
if(settings.Crc64) enabledChecksums |= EnableChecksum.Crc64;
|
||||
|
||||
if(md5) enabledChecksums |= EnableChecksum.Md5;
|
||||
if(settings.Md5) enabledChecksums |= EnableChecksum.Md5;
|
||||
|
||||
if(sha1) enabledChecksums |= EnableChecksum.Sha1;
|
||||
if(settings.Sha1) enabledChecksums |= EnableChecksum.Sha1;
|
||||
|
||||
if(sha256) enabledChecksums |= EnableChecksum.Sha256;
|
||||
if(settings.Sha256) enabledChecksums |= EnableChecksum.Sha256;
|
||||
|
||||
if(sha384) enabledChecksums |= EnableChecksum.Sha384;
|
||||
if(settings.Sha384) enabledChecksums |= EnableChecksum.Sha384;
|
||||
|
||||
if(sha512) enabledChecksums |= EnableChecksum.Sha512;
|
||||
if(settings.Sha512) enabledChecksums |= EnableChecksum.Sha512;
|
||||
|
||||
if(spamSum) enabledChecksums |= EnableChecksum.SpamSum;
|
||||
if(settings.SpamSum) enabledChecksums |= EnableChecksum.SpamSum;
|
||||
|
||||
if(fletcher16) enabledChecksums |= EnableChecksum.Fletcher16;
|
||||
if(settings.Fletcher16) enabledChecksums |= EnableChecksum.Fletcher16;
|
||||
|
||||
if(fletcher32) enabledChecksums |= EnableChecksum.Fletcher32;
|
||||
if(settings.Fletcher32) enabledChecksums |= EnableChecksum.Fletcher32;
|
||||
|
||||
Checksum mediaChecksum = null;
|
||||
|
||||
@@ -233,7 +193,7 @@ sealed class ChecksumCommand : Command
|
||||
{
|
||||
Checksum trackChecksum = null;
|
||||
|
||||
if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums);
|
||||
if(settings.WholeDisc) mediaChecksum = new Checksum(enabledChecksums);
|
||||
|
||||
List<Track> inputTracks = opticalInput.Tracks;
|
||||
|
||||
@@ -273,7 +233,7 @@ sealed class ChecksumCommand : Command
|
||||
currentTrack.StartSector,
|
||||
currentTrack.EndSector);
|
||||
|
||||
if(separatedTracks) trackChecksum = new Checksum(enabledChecksums);
|
||||
if(settings.SeparatedTracks) trackChecksum = new Checksum(enabledChecksums);
|
||||
|
||||
ulong sectors = currentTrack.EndSector - currentTrack.StartSector + 1;
|
||||
|
||||
@@ -342,9 +302,9 @@ sealed class ChecksumCommand : Command
|
||||
doneSectors += sectors - doneSectors;
|
||||
}
|
||||
|
||||
if(wholeDisc) mediaChecksum?.Update(sector);
|
||||
if(settings.WholeDisc) mediaChecksum?.Update(sector);
|
||||
|
||||
if(separatedTracks) trackChecksum?.Update(sector);
|
||||
if(settings.SeparatedTracks) trackChecksum?.Update(sector);
|
||||
|
||||
trackTask.Value = doneSectors;
|
||||
}
|
||||
@@ -352,7 +312,7 @@ sealed class ChecksumCommand : Command
|
||||
trackTask.StopTask();
|
||||
AaruConsole.WriteLine();
|
||||
|
||||
if(!separatedTracks) continue;
|
||||
if(!settings.SeparatedTracks) continue;
|
||||
|
||||
if(trackChecksum == null) continue;
|
||||
|
||||
@@ -376,7 +336,7 @@ sealed class ChecksumCommand : Command
|
||||
}
|
||||
*/
|
||||
|
||||
if(!wholeDisc) return;
|
||||
if(!settings.WholeDisc) return;
|
||||
|
||||
if(mediaChecksum == null) return;
|
||||
|
||||
@@ -393,7 +353,7 @@ sealed class ChecksumCommand : Command
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
AaruConsole.DebugWriteLine(Localization.Core.Could_not_get_tracks_because_0, ex.Message);
|
||||
else
|
||||
AaruConsole.WriteLine("Unable to get separate tracks, not checksumming them");
|
||||
@@ -405,7 +365,7 @@ sealed class ChecksumCommand : Command
|
||||
{
|
||||
Checksum trackChecksum = null;
|
||||
|
||||
if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums);
|
||||
if(settings.WholeDisc) mediaChecksum = new Checksum(enabledChecksums);
|
||||
|
||||
ulong previousFileEnd = 0;
|
||||
|
||||
@@ -423,7 +383,7 @@ sealed class ChecksumCommand : Command
|
||||
tapeTask.Description =
|
||||
string.Format(UI.Hashing_file_0_of_1, currentFile.File, tapeImage.Files.Count);
|
||||
|
||||
if(currentFile.FirstBlock - previousFileEnd != 0 && wholeDisc)
|
||||
if(currentFile.FirstBlock - previousFileEnd != 0 && settings.WholeDisc)
|
||||
{
|
||||
ProgressTask preFileTask = ctx.AddTask(UI.Hashing_sector);
|
||||
preFileTask.MaxValue = currentFile.FirstBlock - previousFileEnd;
|
||||
@@ -457,7 +417,7 @@ sealed class ChecksumCommand : Command
|
||||
currentFile.FirstBlock,
|
||||
currentFile.LastBlock);
|
||||
|
||||
if(separatedTracks) trackChecksum = new Checksum(enabledChecksums);
|
||||
if(settings.SeparatedTracks) trackChecksum = new Checksum(enabledChecksums);
|
||||
|
||||
ulong sectors = currentFile.LastBlock - currentFile.FirstBlock + 1;
|
||||
ulong doneSectors = 0;
|
||||
@@ -524,15 +484,15 @@ sealed class ChecksumCommand : Command
|
||||
|
||||
fileTask.Value = doneSectors;
|
||||
|
||||
if(wholeDisc) mediaChecksum?.Update(sector);
|
||||
if(settings.WholeDisc) mediaChecksum?.Update(sector);
|
||||
|
||||
if(separatedTracks) trackChecksum?.Update(sector);
|
||||
if(settings.SeparatedTracks) trackChecksum?.Update(sector);
|
||||
}
|
||||
|
||||
fileTask.StopTask();
|
||||
AaruConsole.WriteLine();
|
||||
|
||||
if(separatedTracks)
|
||||
if(settings.SeparatedTracks)
|
||||
{
|
||||
if(trackChecksum != null)
|
||||
{
|
||||
@@ -549,7 +509,7 @@ sealed class ChecksumCommand : Command
|
||||
tapeTask.Increment(1);
|
||||
}
|
||||
|
||||
if(tapeImage.Info.Sectors - previousFileEnd == 0 || !wholeDisc) return;
|
||||
if(tapeImage.Info.Sectors - previousFileEnd == 0 || !settings.WholeDisc) return;
|
||||
|
||||
ProgressTask postFileTask = ctx.AddTask(UI.Hashing_sector);
|
||||
postFileTask.MaxValue = tapeImage.Info.Sectors - previousFileEnd;
|
||||
@@ -576,7 +536,7 @@ sealed class ChecksumCommand : Command
|
||||
|
||||
if(errno != ErrorNumber.NoError) return (int)errno;
|
||||
|
||||
if(wholeDisc && mediaChecksum != null)
|
||||
if(settings.WholeDisc && mediaChecksum != null)
|
||||
{
|
||||
AaruConsole.WriteLine();
|
||||
|
||||
@@ -603,8 +563,8 @@ sealed class ChecksumCommand : Command
|
||||
ProgressTask imageTask = ctx.AddTask(UI.Hashing_image);
|
||||
ulong length = byteAddressableImage.Info.Sectors;
|
||||
imageTask.MaxValue = length;
|
||||
ulong doneBytes = 0;
|
||||
var data = new byte[BYTES_TO_READ];
|
||||
ulong doneBytes = 0;
|
||||
byte[] data = new byte[BYTES_TO_READ];
|
||||
|
||||
while(doneBytes < length)
|
||||
{
|
||||
@@ -763,4 +723,71 @@ sealed class ChecksumCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[Description("Calculates Adler-32.")]
|
||||
[CommandOption("-a|--adler32")]
|
||||
[DefaultValue(false)]
|
||||
public bool Adler32 { get; init; }
|
||||
[Description("Calculates CRC16.")]
|
||||
[CommandOption("--crc16")]
|
||||
[DefaultValue(true)]
|
||||
public bool Crc16 { get; init; }
|
||||
[Description("Calculates CRC32.")]
|
||||
[CommandOption("-c|--crc32")]
|
||||
[DefaultValue(true)]
|
||||
public bool Crc32 { get; init; }
|
||||
[Description("Calculates CRC64 (ECMA).")]
|
||||
[CommandOption("--crc64")]
|
||||
[DefaultValue(true)]
|
||||
public bool Crc64 { get; init; }
|
||||
[Description("Calculates Fletcher-16.")]
|
||||
[CommandOption("--fletcher16")]
|
||||
[DefaultValue(false)]
|
||||
public bool Fletcher16 { get; init; }
|
||||
[Description("Calculates Fletcher-32.")]
|
||||
[CommandOption("--fletcher32")]
|
||||
[DefaultValue(false)]
|
||||
public bool Fletcher32 { get; init; }
|
||||
[Description("Calculates MD5.")]
|
||||
[CommandOption("-m|--md5")]
|
||||
[DefaultValue(true)]
|
||||
public bool Md5 { get; init; }
|
||||
[Description("Calculates SHA1.")]
|
||||
[CommandOption("-s|--sha1")]
|
||||
[DefaultValue(true)]
|
||||
public bool Sha1 { get; init; }
|
||||
[Description("Calculates SHA256.")]
|
||||
[CommandOption("--sha256")]
|
||||
[DefaultValue(false)]
|
||||
public bool Sha256 { get; init; }
|
||||
[Description("Calculates SHA384.")]
|
||||
[CommandOption("--sha384")]
|
||||
[DefaultValue(false)]
|
||||
public bool Sha384 { get; init; }
|
||||
[Description("Calculates SHA512.")]
|
||||
[CommandOption("--sha512")]
|
||||
[DefaultValue(true)]
|
||||
public bool Sha512 { get; init; }
|
||||
[Description("Calculates SpamSum fuzzy hash.")]
|
||||
[CommandOption("-f|--spamsum")]
|
||||
[DefaultValue(true)]
|
||||
public bool SpamSum { get; init; }
|
||||
[Description("Checksums the whole disc.")]
|
||||
[CommandOption("-w|--whole-disc")]
|
||||
[DefaultValue(true)]
|
||||
public bool WholeDisc { get; init; }
|
||||
[Description("Checksums each track separately.")]
|
||||
[CommandOption("-t|--separated-tracks")]
|
||||
[DefaultValue(true)]
|
||||
public bool SeparatedTracks { get; init; }
|
||||
[Description("Media image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -45,40 +44,20 @@ using Aaru.Core;
|
||||
using Aaru.Helpers;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class CompareCommand : Command
|
||||
sealed class CompareCommand : Command<CompareCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Compare command";
|
||||
|
||||
public CompareCommand() : base("compare", UI.Image_Compare_Command_Description)
|
||||
{
|
||||
AddAlias("cmp");
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.First_media_image_path,
|
||||
Name = "image-path1"
|
||||
});
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Second_media_image_path,
|
||||
Name = "image-path2"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string imagePath1, string imagePath2)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -96,7 +75,7 @@ sealed class CompareCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -109,10 +88,10 @@ sealed class CompareCommand : Command
|
||||
|
||||
Statistics.AddCommand("compare");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input1={0}", Markup.Escape(imagePath1 ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input2={0}", Markup.Escape(imagePath2 ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input1={0}", Markup.Escape(settings.ImagePath1 ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input2={0}", Markup.Escape(settings.ImagePath2 ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
IFilter inputFilter1 = null;
|
||||
IFilter inputFilter2 = null;
|
||||
@@ -120,13 +99,13 @@ sealed class CompareCommand : Command
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_first_file_filter).IsIndeterminate();
|
||||
inputFilter1 = PluginRegister.Singleton.GetFilter(imagePath1);
|
||||
inputFilter1 = PluginRegister.Singleton.GetFilter(settings.ImagePath1);
|
||||
});
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_second_file_filter).IsIndeterminate();
|
||||
inputFilter2 = PluginRegister.Singleton.GetFilter(imagePath2);
|
||||
inputFilter2 = PluginRegister.Singleton.GetFilter(settings.ImagePath2);
|
||||
});
|
||||
|
||||
if(inputFilter1 == null)
|
||||
@@ -165,7 +144,7 @@ sealed class CompareCommand : Command
|
||||
return (int)ErrorNumber.UnrecognizedFormat;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.VerboseWriteLine(UI.First_input_file_format_identified_by_0_1,
|
||||
input1Format.Name,
|
||||
@@ -181,7 +160,7 @@ sealed class CompareCommand : Command
|
||||
return (int)ErrorNumber.UnrecognizedFormat;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.VerboseWriteLine(UI.Second_input_file_format_identified_by_0_1,
|
||||
input2Format.Name,
|
||||
@@ -235,18 +214,18 @@ sealed class CompareCommand : Command
|
||||
table.AddColumn(UI.Title_Second_Media_image);
|
||||
table.Columns[0].RightAligned();
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
table.AddRow(UI.Title_File, Markup.Escape(imagePath1), Markup.Escape(imagePath2));
|
||||
table.AddRow(UI.Title_Media_image_format, input1Format.Name, input2Format.Name);
|
||||
table.AddRow(UI.Title_File, Markup.Escape(settings.ImagePath1), Markup.Escape(settings.ImagePath2));
|
||||
table.AddRow(UI.Title_Media_image_format, input1Format.Name, input2Format.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendFormat($"[bold]{UI.Title_First_Media_image}:[/] {imagePath1}").AppendLine();
|
||||
sb.AppendFormat($"[bold]{UI.Title_Second_Media_image}:[/] {imagePath2}").AppendLine();
|
||||
sb.AppendFormat($"[bold]{UI.Title_First_Media_image}:[/] {settings.ImagePath1}").AppendLine();
|
||||
sb.AppendFormat($"[bold]{UI.Title_Second_Media_image}:[/] {settings.ImagePath2}").AppendLine();
|
||||
}
|
||||
|
||||
var imagesDiffer = false;
|
||||
bool imagesDiffer = false;
|
||||
ErrorNumber errno;
|
||||
|
||||
ImageInfo image1Info = input1Format.Info;
|
||||
@@ -276,7 +255,7 @@ sealed class CompareCommand : Command
|
||||
}
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
table.AddRow(UI.Has_partitions_Question,
|
||||
image1Info.HasPartitions.ToString(),
|
||||
@@ -373,35 +352,35 @@ sealed class CompareCommand : Command
|
||||
{
|
||||
imagesDiffer = true;
|
||||
|
||||
if(!verbose) sb.AppendLine(UI.Image_partitioned_status_differ);
|
||||
if(!settings.Verbose) sb.AppendLine(UI.Image_partitioned_status_differ);
|
||||
}
|
||||
|
||||
if(image1Info.HasSessions != image2Info.HasSessions)
|
||||
{
|
||||
imagesDiffer = true;
|
||||
|
||||
if(!verbose) sb.AppendLine(UI.Image_session_status_differ);
|
||||
if(!settings.Verbose) sb.AppendLine(UI.Image_session_status_differ);
|
||||
}
|
||||
|
||||
if(image1Info.Sectors != image2Info.Sectors)
|
||||
{
|
||||
imagesDiffer = true;
|
||||
|
||||
if(!verbose) sb.AppendLine(UI.Image_sectors_differ);
|
||||
if(!settings.Verbose) sb.AppendLine(UI.Image_sectors_differ);
|
||||
}
|
||||
|
||||
if(image1Info.SectorSize != image2Info.SectorSize)
|
||||
{
|
||||
imagesDiffer = true;
|
||||
|
||||
if(!verbose) sb.AppendLine(UI.Image_sector_size_differ);
|
||||
if(!settings.Verbose) sb.AppendLine(UI.Image_sector_size_differ);
|
||||
}
|
||||
|
||||
if(image1Info.MediaType != image2Info.MediaType)
|
||||
{
|
||||
imagesDiffer = true;
|
||||
|
||||
if(!verbose) sb.AppendLine(UI.Media_type_differs);
|
||||
if(!settings.Verbose) sb.AppendLine(UI.Media_type_differs);
|
||||
}
|
||||
|
||||
if(image1Info.Sectors < image2Info.Sectors)
|
||||
@@ -409,14 +388,14 @@ sealed class CompareCommand : Command
|
||||
imagesDiffer = true;
|
||||
leastSectors = image1Info.Sectors;
|
||||
|
||||
if(!verbose) sb.AppendLine(UI.Second_image_has_more_sectors);
|
||||
if(!settings.Verbose) sb.AppendLine(UI.Second_image_has_more_sectors);
|
||||
}
|
||||
else if(image1Info.Sectors > image2Info.Sectors)
|
||||
{
|
||||
imagesDiffer = true;
|
||||
leastSectors = image2Info.Sectors;
|
||||
|
||||
if(!verbose) sb.AppendLine(UI.First_image_has_more_sectors);
|
||||
if(!settings.Verbose) sb.AppendLine(UI.First_image_has_more_sectors);
|
||||
}
|
||||
else
|
||||
leastSectors = image1Info.Sectors;
|
||||
@@ -506,8 +485,8 @@ sealed class CompareCommand : Command
|
||||
ProgressTask task = ctx.AddTask(UI.Comparing_images);
|
||||
task.IsIndeterminate = true;
|
||||
|
||||
var data1 = new byte[input1ByteAddressable.Info.Sectors];
|
||||
var data2 = new byte[input2ByteAddressable.Info.Sectors];
|
||||
byte[] data1 = new byte[input1ByteAddressable.Info.Sectors];
|
||||
byte[] data2 = new byte[input2ByteAddressable.Info.Sectors];
|
||||
byte[] tmp;
|
||||
|
||||
input1ByteAddressable.ReadBytes(data1, 0, data1.Length, out int bytesRead);
|
||||
@@ -540,11 +519,25 @@ sealed class CompareCommand : Command
|
||||
|
||||
sb.AppendLine(imagesDiffer ? UI.Images_differ : UI.Images_do_not_differ);
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AnsiConsole.Write(table);
|
||||
else
|
||||
AaruConsole.WriteLine(sb.ToString());
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[Description("First media image path")]
|
||||
[CommandArgument(0, "<image-path1>")]
|
||||
public string ImagePath1 { get; init; }
|
||||
[Description("Second media image path")]
|
||||
[CommandArgument(1, "<image-path1>")]
|
||||
public string ImagePath2 { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -52,6 +51,7 @@ using Aaru.Devices;
|
||||
using Aaru.Localization;
|
||||
using Schemas;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using File = System.IO.File;
|
||||
using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo;
|
||||
using MediaType = Aaru.CommonTypes.MediaType;
|
||||
@@ -63,95 +63,15 @@ using Version = Aaru.CommonTypes.Interop.Version;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class ConvertImageCommand : Command
|
||||
sealed class ConvertImageCommand : Command<ConvertImageCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Convert-image command";
|
||||
|
||||
public ConvertImageCommand() : base("convert", UI.Image_Convert_Command_Description)
|
||||
{
|
||||
Add(new Option<string>(["--cicm-xml", "-x"], () => null, UI.Take_metadata_from_existing_CICM_XML_sidecar));
|
||||
|
||||
Add(new Option<string>("--comments", () => null, UI.Image_comments));
|
||||
|
||||
Add(new Option<int>(["--count", "-c"], () => 64, UI.How_many_sectors_to_convert_at_once));
|
||||
|
||||
Add(new Option<string>("--creator", () => null, UI.Who_person_created_the_image));
|
||||
|
||||
Add(new Option<string>("--drive-manufacturer", () => null, UI.Manufacturer_of_drive_read_the_media_by_image));
|
||||
|
||||
Add(new Option<string>("--drive-model", () => null, UI.Model_of_drive_read_the_media_by_image));
|
||||
|
||||
Add(new Option<string>("--drive-revision", () => null, UI.Firmware_revision_of_drive_read_the_media_by_image));
|
||||
|
||||
Add(new Option<string>("--drive-serial", () => null, UI.Serial_number_of_drive_read_the_media_by_image));
|
||||
|
||||
Add(new Option<bool>(["--force", "-f"], UI.Continue_conversion_even_if_data_lost));
|
||||
|
||||
Add(new Option<string>(["--format", "-p"],
|
||||
() => null,
|
||||
UI.Format_of_the_output_image_as_plugin_name_or_plugin_id));
|
||||
|
||||
Add(new Option<string>("--media-barcode", () => null, UI.Barcode_of_the_media_by_image));
|
||||
|
||||
Add(new Option<int>("--media-lastsequence", () => 0, UI.Last_media_of_sequence_by_image));
|
||||
|
||||
Add(new Option<string>("--media-manufacturer", () => null, UI.Manufacturer_of_media_by_image));
|
||||
|
||||
Add(new Option<string>("--media-model", () => null, UI.Model_of_media_by_image));
|
||||
Add(new Option<string>("--media-partnumber", () => null, UI.Part_number_of_media_by_image));
|
||||
Add(new Option<int>("--media-sequence", () => 0, UI.Number_in_sequence_for_media_by_image));
|
||||
Add(new Option<string>("--media-serial", () => null, UI.Serial_number_of_media_by_image));
|
||||
Add(new Option<string>("--media-title", () => null, UI.Title_of_media_represented_by_image));
|
||||
|
||||
Add(new Option<string>(["--options", "-O"], () => null, UI.Comma_separated_name_value_pairs_of_image_options));
|
||||
|
||||
Add(new Option<string>(["--resume-file", "-r"], () => null, UI.Take_dump_hardware_from_existing_resume));
|
||||
|
||||
Add(new Option<string>(["--geometry", "-g"], () => null, UI.Force_geometry_help));
|
||||
|
||||
Add(new Option<bool>(["--fix-subchannel-position"], () => true, UI.Fix_subchannel_position_help));
|
||||
|
||||
Add(new Option<bool>(["--fix-subchannel"], () => false, UI.Fix_subchannel_help));
|
||||
|
||||
Add(new Option<bool>(["--fix-subchannel-crc"], () => false, UI.Fix_subchannel_crc_help));
|
||||
|
||||
Add(new Option<bool>(["--generate-subchannels"], () => false, UI.Generates_subchannels_help));
|
||||
|
||||
Add(new Option<bool>(["--decrypt"], () => false, UI.Decrypt_sectors_help));
|
||||
|
||||
Add(new Option<string>(["--aaru-metadata", "-m"],
|
||||
() => null,
|
||||
"Take metadata from existing Aaru Metadata sidecar."));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Input_image_path,
|
||||
Name = "input-path"
|
||||
});
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Output_image_path,
|
||||
Name = "output-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public 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 options, string resumeFile, string format, string geometry,
|
||||
bool fixSubchannelPosition, bool fixSubchannel, bool fixSubchannelCrc,
|
||||
bool generateSubchannels, bool decrypt, string aaruMetadata)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -169,7 +89,7 @@ sealed class ConvertImageCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -180,51 +100,71 @@ sealed class ConvertImageCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
bool fixSubchannel = settings.FixSubchannel;
|
||||
bool fixSubchannelCrc = settings.FixSubchannelCrc;
|
||||
bool fixSubchannelPosition = settings.FixSubchannelPosition;
|
||||
|
||||
if(fixSubchannelCrc) fixSubchannel = true;
|
||||
|
||||
if(fixSubchannel) fixSubchannelPosition = true;
|
||||
|
||||
Statistics.AddCommand("convert-image");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--cicm-xml={0}", Markup.Escape(cicmXml ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--comments={0}", Markup.Escape(comments ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--count={0}", count);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--creator={0}", Markup.Escape(creator ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--drive-manufacturer={0}", Markup.Escape(driveManufacturer ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--drive-model={0}", Markup.Escape(driveModel ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--drive-revision={0}", Markup.Escape(driveFirmwareRevision ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--drive-serial={0}", Markup.Escape(driveSerialNumber ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--force={0}", force);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--format={0}", Markup.Escape(format ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--geometry={0}", Markup.Escape(geometry ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(inputPath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-barcode={0}", Markup.Escape(mediaBarcode ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-lastsequence={0}", lastMediaSequence);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-manufacturer={0}", Markup.Escape(mediaManufacturer ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-model={0}", Markup.Escape(mediaModel ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-partnumber={0}", Markup.Escape(mediaPartNumber ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-sequence={0}", mediaSequence);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-serial={0}", Markup.Escape(mediaSerialNumber ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-title={0}", Markup.Escape(mediaTitle ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--options={0}", Markup.Escape(options ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output={0}", Markup.Escape(outputPath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--resume-file={0}", Markup.Escape(resumeFile ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--cicm-xml={0}", Markup.Escape(settings.CicmXml ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--comments={0}", Markup.Escape(settings.Comments ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--count={0}", settings.Count);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--creator={0}", Markup.Escape(settings.Creator ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
"--drive-manufacturer={0}",
|
||||
Markup.Escape(settings.DriveManufacturer ?? ""));
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--drive-model={0}", Markup.Escape(settings.DriveModel ?? ""));
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
"--drive-revision={0}",
|
||||
Markup.Escape(settings.DriveFirmwareRevision ?? ""));
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--drive-serial={0}", Markup.Escape(settings.DriveSerialNumber ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--force={0}", settings.Force);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--format={0}", Markup.Escape(settings.Format ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--geometry={0}", Markup.Escape(settings.Geometry ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.InputPath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-barcode={0}", Markup.Escape(settings.MediaBarcode ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-lastsequence={0}", settings.LastMediaSequence);
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
"--media-manufacturer={0}",
|
||||
Markup.Escape(settings.MediaManufacturer ?? ""));
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-model={0}", Markup.Escape(settings.MediaModel ?? ""));
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
"--media-partnumber={0}",
|
||||
Markup.Escape(settings.MediaPartNumber ?? ""));
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-sequence={0}", settings.MediaSequence);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-serial={0}", Markup.Escape(settings.MediaSerialNumber ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--media-title={0}", Markup.Escape(settings.MediaTitle ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--options={0}", Markup.Escape(settings.Options ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output={0}", Markup.Escape(settings.OutputPath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--resume-file={0}", Markup.Escape(settings.ResumeFile ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel-position={0}", fixSubchannelPosition);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel={0}", fixSubchannel);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel-crc={0}", fixSubchannelCrc);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--generate-subchannels={0}", generateSubchannels);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--decrypt={0}", decrypt);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--aaru-metadata={0}", Markup.Escape(aaruMetadata ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--generate-subchannels={0}", settings.GenerateSubchannels);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--decrypt={0}", settings.Decrypt);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--aaru-metadata={0}", Markup.Escape(settings.AaruMetadata ?? ""));
|
||||
|
||||
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
|
||||
Dictionary<string, string> parsedOptions = Options.Parse(settings.Options);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, UI.Parsed_options);
|
||||
|
||||
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "{0} = {1}", parsedOption.Key, parsedOption.Value);
|
||||
|
||||
if(count == 0)
|
||||
if(settings.Count == 0)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Need_to_specify_more_than_zero_sectors_to_copy_at_once);
|
||||
|
||||
@@ -233,11 +173,11 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
(uint cylinders, uint heads, uint sectors)? geometryValues = null;
|
||||
|
||||
if(geometry != null)
|
||||
if(settings.Geometry != null)
|
||||
{
|
||||
string[] geometryPieces = geometry.Split('/');
|
||||
string[] geometryPieces = settings.Geometry.Split('/');
|
||||
|
||||
if(geometryPieces.Length == 0) geometryPieces = geometry.Split('-');
|
||||
if(geometryPieces.Length == 0) geometryPieces = settings.Geometry.Split('-');
|
||||
|
||||
if(geometryPieces.Length != 3)
|
||||
{
|
||||
@@ -274,14 +214,14 @@ sealed class ConvertImageCommand : Command
|
||||
Metadata sidecar = null;
|
||||
MediaType mediaType;
|
||||
|
||||
if(aaruMetadata != null)
|
||||
if(settings.AaruMetadata != null)
|
||||
|
||||
{
|
||||
if(File.Exists(aaruMetadata))
|
||||
if(File.Exists(settings.AaruMetadata))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fs = new FileStream(aaruMetadata, FileMode.Open);
|
||||
var fs = new FileStream(settings.AaruMetadata, FileMode.Open);
|
||||
|
||||
sidecar =
|
||||
(JsonSerializer.Deserialize(fs, typeof(MetadataJson), MetadataJsonContext.Default) as
|
||||
@@ -305,9 +245,9 @@ sealed class ConvertImageCommand : Command
|
||||
}
|
||||
}
|
||||
|
||||
else if(cicmXml != null)
|
||||
else if(settings.CicmXml != null)
|
||||
{
|
||||
if(File.Exists(cicmXml))
|
||||
if(File.Exists(settings.CicmXml))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -316,7 +256,7 @@ sealed class ConvertImageCommand : Command
|
||||
var xs = new XmlSerializer(typeof(CICMMetadataType));
|
||||
#pragma warning restore IL2026
|
||||
|
||||
var sr = new StreamReader(cicmXml);
|
||||
var sr = new StreamReader(settings.CicmXml);
|
||||
|
||||
// Should be covered by virtue of being the same exact class as the JSON above
|
||||
#pragma warning disable IL2026
|
||||
@@ -341,15 +281,15 @@ sealed class ConvertImageCommand : Command
|
||||
}
|
||||
}
|
||||
|
||||
if(resumeFile != null)
|
||||
if(settings.ResumeFile != null)
|
||||
{
|
||||
if(File.Exists(resumeFile))
|
||||
if(File.Exists(settings.ResumeFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
if(resumeFile.EndsWith(".metadata.json", StringComparison.CurrentCultureIgnoreCase))
|
||||
if(settings.ResumeFile.EndsWith(".metadata.json", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
var fs = new FileStream(resumeFile, FileMode.Open);
|
||||
var fs = new FileStream(settings.ResumeFile, FileMode.Open);
|
||||
|
||||
resume =
|
||||
(JsonSerializer.Deserialize(fs,
|
||||
@@ -365,7 +305,7 @@ sealed class ConvertImageCommand : Command
|
||||
var xs = new XmlSerializer(typeof(Resume));
|
||||
#pragma warning restore IL2026
|
||||
|
||||
var sr = new StreamReader(resumeFile);
|
||||
var sr = new StreamReader(settings.ResumeFile);
|
||||
|
||||
// Bypassed by JSON source generator used above
|
||||
#pragma warning disable IL2026
|
||||
@@ -396,7 +336,7 @@ sealed class ConvertImageCommand : Command
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(inputPath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.InputPath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -406,7 +346,7 @@ sealed class ConvertImageCommand : Command
|
||||
return (int)ErrorNumber.CannotOpenFile;
|
||||
}
|
||||
|
||||
if(File.Exists(outputPath))
|
||||
if(File.Exists(settings.OutputPath))
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Output_file_already_exists);
|
||||
|
||||
@@ -439,7 +379,7 @@ sealed class ConvertImageCommand : Command
|
||||
return (int)ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AaruConsole.VerboseWriteLine(UI.Input_image_format_identified_by_0_1, inputFormat.Name, inputFormat.Id);
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Input_image_format_identified_by_0, inputFormat.Name);
|
||||
@@ -499,16 +439,16 @@ sealed class ConvertImageCommand : Command
|
||||
List<IBaseWritableImage> candidates = [];
|
||||
|
||||
// Try extension
|
||||
if(string.IsNullOrEmpty(format))
|
||||
if(string.IsNullOrEmpty(settings.Format))
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
where plugin.KnownExtensions.Contains(Path.GetExtension(outputPath))
|
||||
where plugin.KnownExtensions.Contains(Path.GetExtension(settings.OutputPath))
|
||||
select plugin);
|
||||
}
|
||||
|
||||
// Try Id
|
||||
else if(Guid.TryParse(format, out Guid outId))
|
||||
else if(Guid.TryParse(settings.Format, out Guid outId))
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
@@ -521,7 +461,7 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
where plugin.Name.Equals(format, StringComparison.InvariantCultureIgnoreCase)
|
||||
where plugin.Name.Equals(settings.Format, StringComparison.InvariantCultureIgnoreCase)
|
||||
select plugin);
|
||||
}
|
||||
|
||||
@@ -539,7 +479,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
IBaseWritableImage outputFormat = candidates[0];
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AaruConsole.VerboseWriteLine(UI.Output_image_format_0_1, outputFormat.Name, outputFormat.Id);
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Output_image_format_0, outputFormat.Name);
|
||||
@@ -552,7 +492,7 @@ sealed class ConvertImageCommand : Command
|
||||
}
|
||||
|
||||
foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags.Where(mediaTag =>
|
||||
!outputFormat.SupportedMediaTags.Contains(mediaTag) && !force))
|
||||
!outputFormat.SupportedMediaTags.Contains(mediaTag) && !settings.Force))
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Converting_image_will_lose_media_tag_0, mediaTag);
|
||||
AaruConsole.ErrorWriteLine(UI.If_you_dont_care_use_force_option);
|
||||
@@ -565,7 +505,7 @@ sealed class ConvertImageCommand : Command
|
||||
foreach(SectorTagType sectorTag in inputFormat.Info.ReadableSectorTags.Where(sectorTag =>
|
||||
!outputFormat.SupportedSectorTags.Contains(sectorTag)))
|
||||
{
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
if(sectorTag != SectorTagType.CdTrackFlags &&
|
||||
sectorTag != SectorTagType.CdTrackIsrc &&
|
||||
@@ -593,7 +533,7 @@ sealed class ConvertImageCommand : Command
|
||||
return (int)ErrorNumber.UnsupportedMedia;
|
||||
}
|
||||
|
||||
var ret = false;
|
||||
bool ret = false;
|
||||
|
||||
if(inputTape?.IsTape == true && outputTape != null)
|
||||
{
|
||||
@@ -641,13 +581,13 @@ sealed class ConvertImageCommand : Command
|
||||
AaruConsole.ErrorWriteLine("Output format does not support sessions, this will end in a loss of data, continuing...");*/
|
||||
}
|
||||
|
||||
var created = false;
|
||||
bool created = false;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Invoke_Opening_image_file).IsIndeterminate();
|
||||
|
||||
created = outputFormat.Create(outputPath,
|
||||
created = outputFormat.Create(settings.OutputPath,
|
||||
mediaType,
|
||||
parsedOptions,
|
||||
inputFormat.Info.Sectors,
|
||||
@@ -665,25 +605,26 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
Application = "Aaru",
|
||||
ApplicationVersion = Version.GetVersion(),
|
||||
Comments = comments ?? inputFormat.Info.Comments,
|
||||
Creator = creator ?? inputFormat.Info.Creator,
|
||||
DriveFirmwareRevision = driveFirmwareRevision ?? inputFormat.Info.DriveFirmwareRevision,
|
||||
DriveManufacturer = driveManufacturer ?? inputFormat.Info.DriveManufacturer,
|
||||
DriveModel = driveModel ?? inputFormat.Info.DriveModel,
|
||||
DriveSerialNumber = driveSerialNumber ?? inputFormat.Info.DriveSerialNumber,
|
||||
LastMediaSequence = lastMediaSequence != 0 ? lastMediaSequence : inputFormat.Info.LastMediaSequence,
|
||||
MediaBarcode = mediaBarcode ?? inputFormat.Info.MediaBarcode,
|
||||
MediaManufacturer = mediaManufacturer ?? inputFormat.Info.MediaManufacturer,
|
||||
MediaModel = mediaModel ?? inputFormat.Info.MediaModel,
|
||||
MediaPartNumber = mediaPartNumber ?? inputFormat.Info.MediaPartNumber,
|
||||
MediaSequence = mediaSequence != 0 ? mediaSequence : inputFormat.Info.MediaSequence,
|
||||
MediaSerialNumber = mediaSerialNumber ?? inputFormat.Info.MediaSerialNumber,
|
||||
MediaTitle = mediaTitle ?? inputFormat.Info.MediaTitle
|
||||
Comments = settings.Comments ?? inputFormat.Info.Comments,
|
||||
Creator = settings.Creator ?? inputFormat.Info.Creator,
|
||||
DriveFirmwareRevision = settings.DriveFirmwareRevision ?? inputFormat.Info.DriveFirmwareRevision,
|
||||
DriveManufacturer = settings.DriveManufacturer ?? inputFormat.Info.DriveManufacturer,
|
||||
DriveModel = settings.DriveModel ?? inputFormat.Info.DriveModel,
|
||||
DriveSerialNumber = settings.DriveSerialNumber ?? inputFormat.Info.DriveSerialNumber,
|
||||
LastMediaSequence =
|
||||
settings.LastMediaSequence != 0 ? settings.LastMediaSequence : inputFormat.Info.LastMediaSequence,
|
||||
MediaBarcode = settings.MediaBarcode ?? inputFormat.Info.MediaBarcode,
|
||||
MediaManufacturer = settings.MediaManufacturer ?? inputFormat.Info.MediaManufacturer,
|
||||
MediaModel = settings.MediaModel ?? inputFormat.Info.MediaModel,
|
||||
MediaPartNumber = settings.MediaPartNumber ?? inputFormat.Info.MediaPartNumber,
|
||||
MediaSequence = settings.MediaSequence != 0 ? settings.MediaSequence : inputFormat.Info.MediaSequence,
|
||||
MediaSerialNumber = settings.MediaSerialNumber ?? inputFormat.Info.MediaSerialNumber,
|
||||
MediaTitle = settings.MediaTitle ?? inputFormat.Info.MediaTitle
|
||||
};
|
||||
|
||||
if(!outputFormat.SetImageInfo(imageInfo))
|
||||
{
|
||||
if(!force)
|
||||
if(!settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_setting_metadata_not_continuing, outputFormat.ErrorMessage);
|
||||
|
||||
@@ -696,8 +637,8 @@ sealed class ConvertImageCommand : Command
|
||||
Metadata metadata = inputFormat.AaruMetadata;
|
||||
List<DumpHardware> dumpHardware = inputFormat.DumpHardware;
|
||||
|
||||
foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags.Where(mediaTag =>
|
||||
!force || outputFormat.SupportedMediaTags.Contains(mediaTag)))
|
||||
foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags.Where(mediaTag => !settings.Force ||
|
||||
outputFormat.SupportedMediaTags.Contains(mediaTag)))
|
||||
{
|
||||
ErrorNumber errorNumber = ErrorNumber.NoError;
|
||||
|
||||
@@ -712,7 +653,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
{
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_media_tag, errno);
|
||||
else
|
||||
{
|
||||
@@ -726,7 +667,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if((outputFormat as IWritableImage)?.WriteMediaTag(tag, mediaTag) == true) return;
|
||||
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_writing_media_tag, outputFormat.ErrorMessage);
|
||||
else
|
||||
{
|
||||
@@ -756,7 +697,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
ErrorNumber errno = ErrorNumber.NoError;
|
||||
|
||||
if(decrypt) AaruConsole.WriteLine("Decrypting encrypted sectors.");
|
||||
if(settings.Decrypt) AaruConsole.WriteLine("Decrypting encrypted sectors.");
|
||||
|
||||
AnsiConsole.Progress()
|
||||
.AutoClear(true)
|
||||
@@ -786,8 +727,8 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
uint sectorsToDo;
|
||||
|
||||
if(trackSectors - doneSectors >= (ulong)count)
|
||||
sectorsToDo = (uint)count;
|
||||
if(trackSectors - doneSectors >= (ulong)settings.Count)
|
||||
sectorsToDo = (uint)settings.Count;
|
||||
else
|
||||
sectorsToDo = (uint)(trackSectors - doneSectors);
|
||||
|
||||
@@ -796,8 +737,8 @@ sealed class ConvertImageCommand : Command
|
||||
doneSectors + sectorsToDo + track.StartSector,
|
||||
track.Sequence);
|
||||
|
||||
var useNotLong = false;
|
||||
var result = false;
|
||||
bool useNotLong = false;
|
||||
bool result = false;
|
||||
|
||||
if(useLong)
|
||||
{
|
||||
@@ -821,7 +762,7 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
result = true;
|
||||
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_sector_1_continuing,
|
||||
errno,
|
||||
@@ -841,7 +782,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if(!result && sector.Length % 2352 != 0)
|
||||
{
|
||||
if(!force)
|
||||
if(!settings.Force)
|
||||
{
|
||||
AaruConsole
|
||||
.ErrorWriteLine(UI
|
||||
@@ -871,7 +812,7 @@ sealed class ConvertImageCommand : Command
|
||||
or MediaType.DVDRDL
|
||||
or MediaType.DVDPR
|
||||
or MediaType.DVDPRDL &&
|
||||
decrypt)
|
||||
settings.Decrypt)
|
||||
{
|
||||
// Only sectors which are MPEG packets can be encrypted.
|
||||
if(Mpeg.ContainsMpegPackets(sector, sectorsToDo))
|
||||
@@ -1009,7 +950,7 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
result = true;
|
||||
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_sector_1_continuing,
|
||||
errno,
|
||||
@@ -1030,7 +971,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if(!result)
|
||||
{
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_writing_sector_1_continuing,
|
||||
outputOptical.ErrorMessage,
|
||||
@@ -1066,7 +1007,7 @@ sealed class ConvertImageCommand : Command
|
||||
Dictionary<byte, int> smallestPregapLbaPerTrack = new();
|
||||
var tracks = new Track[inputOptical.Tracks.Count];
|
||||
|
||||
for(var i = 0; i < tracks.Length; i++)
|
||||
for(int i = 0; i < tracks.Length; i++)
|
||||
{
|
||||
tracks[i] = new Track
|
||||
{
|
||||
@@ -1143,7 +1084,7 @@ sealed class ConvertImageCommand : Command
|
||||
continue;
|
||||
}
|
||||
|
||||
if(force && !outputOptical.SupportedSectorTags.Contains(tag)) continue;
|
||||
if(settings.Force && !outputOptical.SupportedSectorTags.Contains(tag)) continue;
|
||||
|
||||
errno = ErrorNumber.NoError;
|
||||
|
||||
@@ -1186,7 +1127,7 @@ sealed class ConvertImageCommand : Command
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_writing_tag_continuing,
|
||||
outputOptical.ErrorMessage);
|
||||
@@ -1205,7 +1146,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if(!result)
|
||||
{
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_writing_tag_continuing,
|
||||
outputOptical.ErrorMessage);
|
||||
@@ -1231,8 +1172,8 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
uint sectorsToDo;
|
||||
|
||||
if(trackSectors - doneSectors >= (ulong)count)
|
||||
sectorsToDo = (uint)count;
|
||||
if(trackSectors - doneSectors >= (ulong)settings.Count)
|
||||
sectorsToDo = (uint)settings.Count;
|
||||
else
|
||||
sectorsToDo = (uint)(trackSectors - doneSectors);
|
||||
|
||||
@@ -1290,7 +1231,7 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
result = true;
|
||||
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole
|
||||
.ErrorWriteLine(UI.Error_0_reading_tag_for_sector_1_continuing,
|
||||
@@ -1358,7 +1299,7 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
result = true;
|
||||
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole
|
||||
.ErrorWriteLine(UI.Error_0_reading_tag_for_sector_1_continuing,
|
||||
@@ -1380,7 +1321,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if(!result)
|
||||
{
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole
|
||||
.ErrorWriteLine(UI.Error_0_writing_tag_for_sector_1_continuing,
|
||||
@@ -1409,13 +1350,11 @@ sealed class ConvertImageCommand : Command
|
||||
}
|
||||
});
|
||||
|
||||
if(errno != ErrorNumber.NoError && !force) return (int)errno;
|
||||
if(errno != ErrorNumber.NoError && !settings.Force) return (int)errno;
|
||||
}
|
||||
|
||||
foreach(KeyValuePair<byte, string> isrc in isrcs)
|
||||
{
|
||||
outputOptical.WriteSectorTag(Encoding.UTF8.GetBytes(isrc.Value), isrc.Key, SectorTagType.CdTrackIsrc);
|
||||
}
|
||||
|
||||
if(trackFlags.Count > 0)
|
||||
{
|
||||
@@ -1466,7 +1405,7 @@ sealed class ConvertImageCommand : Command
|
||||
or MediaType.VideoNowColor
|
||||
or MediaType.VideoNowXp
|
||||
or MediaType.CVD &&
|
||||
generateSubchannels)
|
||||
settings.GenerateSubchannels)
|
||||
{
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
@@ -1527,8 +1466,8 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if(inputTape?.IsTape == true)
|
||||
sectorsToDo = 1;
|
||||
else if(inputFormat.Info.Sectors - doneSectors >= (ulong)count)
|
||||
sectorsToDo = (uint)count;
|
||||
else if(inputFormat.Info.Sectors - doneSectors >= (ulong)settings.Count)
|
||||
sectorsToDo = (uint)settings.Count;
|
||||
else
|
||||
sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors);
|
||||
|
||||
@@ -1553,7 +1492,7 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
result = true;
|
||||
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_sector_1_continuing,
|
||||
errno,
|
||||
@@ -1585,7 +1524,7 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
result = true;
|
||||
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_sector_1_continuing,
|
||||
errno,
|
||||
@@ -1604,7 +1543,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if(!result)
|
||||
{
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_writing_sector_1_continuing,
|
||||
outputMedia.ErrorMessage,
|
||||
@@ -1644,7 +1583,7 @@ sealed class ConvertImageCommand : Command
|
||||
continue;
|
||||
}
|
||||
|
||||
if(force && !outputMedia.SupportedSectorTags.Contains(tag)) continue;
|
||||
if(settings.Force && !outputMedia.SupportedSectorTags.Contains(tag)) continue;
|
||||
|
||||
doneSectors = 0;
|
||||
|
||||
@@ -1655,8 +1594,8 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
uint sectorsToDo;
|
||||
|
||||
if(inputFormat.Info.Sectors - doneSectors >= (ulong)count)
|
||||
sectorsToDo = (uint)count;
|
||||
if(inputFormat.Info.Sectors - doneSectors >= (ulong)settings.Count)
|
||||
sectorsToDo = (uint)settings.Count;
|
||||
else
|
||||
sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors);
|
||||
|
||||
@@ -1684,7 +1623,7 @@ sealed class ConvertImageCommand : Command
|
||||
{
|
||||
result = true;
|
||||
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_sector_1_continuing,
|
||||
errno,
|
||||
@@ -1702,7 +1641,7 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
if(!result)
|
||||
{
|
||||
if(force)
|
||||
if(settings.Force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_writing_sector_1_continuing,
|
||||
outputMedia.ErrorMessage,
|
||||
@@ -1836,7 +1775,7 @@ sealed class ConvertImageCommand : Command
|
||||
if(ret) AaruConsole.WriteLine(UI.Written_Aaru_Metadata_to_output_image);
|
||||
}
|
||||
|
||||
var closed = false;
|
||||
bool closed = false;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
@@ -1856,4 +1795,126 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[Description("Take metadata from existing CICM XML sidecar.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-x|--cicm-xml")]
|
||||
public string CicmXml { get; init; }
|
||||
[Description("Image comments.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--comments")]
|
||||
public string Comments { get; init; }
|
||||
[Description("How many sectors to convert at once.")]
|
||||
[DefaultValue(64)]
|
||||
[CommandOption("-c|--count")]
|
||||
public int Count { get; init; }
|
||||
[Description("Who (person) created the image?")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--creator")]
|
||||
public string Creator { get; init; }
|
||||
[Description("Manufacturer of the drive used to read the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--drive-manufacturer")]
|
||||
public string DriveManufacturer { get; init; }
|
||||
[Description("Model of the drive used to read the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--drive-model")]
|
||||
public string DriveModel { get; init; }
|
||||
[Description("Firmware revision of the drive used to read the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--drive-revision")]
|
||||
public string DriveFirmwareRevision { get; init; }
|
||||
[Description("Serial number of the drive used to read the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--drive-serial")]
|
||||
public string DriveSerialNumber { get; init; }
|
||||
[Description("Continue conversion even if sector or media tags will be lost in the process.")]
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("-f|--force")]
|
||||
public bool Force { get; init; }
|
||||
[Description("Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-p|--format")]
|
||||
public string Format { get; init; }
|
||||
[Description("Barcode of the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--media-barcode")]
|
||||
public string MediaBarcode { get; init; }
|
||||
[Description("Last media of the sequence the media represented by the image corresponds to.")]
|
||||
[DefaultValue(0)]
|
||||
[CommandOption("--media-lastsequence")]
|
||||
public int LastMediaSequence { get; init; }
|
||||
[Description("Manufacturer of the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--media-manufacturer")]
|
||||
public string MediaManufacturer { get; init; }
|
||||
[Description("Model of the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--media-model")]
|
||||
public string MediaModel { get; init; }
|
||||
[Description("Part number of the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--media-partnumber")]
|
||||
public string MediaPartNumber { get; init; }
|
||||
[Description("Number in sequence for the media represented by the image.")]
|
||||
[DefaultValue(0)]
|
||||
[CommandOption("--media-sequence")]
|
||||
public int MediaSequence { get; init; }
|
||||
[Description("Serial number of the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--media-serial")]
|
||||
public string MediaSerialNumber { get; init; }
|
||||
[Description("Title of the media represented by the image.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("--media-title")]
|
||||
public string MediaTitle { get; init; }
|
||||
[Description("Comma separated name=value pairs of options to pass to output image plugin.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-O|--options")]
|
||||
public string Options { get; init; }
|
||||
[Description("Take list of dump hardware from existing resume file.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-r|--resume-file")]
|
||||
public string ResumeFile { get; init; }
|
||||
[Description("Force geometry, only supported in not tape block media. Specify as C/H/S.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-g|--geometry")]
|
||||
public string Geometry { get; init; }
|
||||
[Description("Store subchannel according to the sector they describe.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("--fix-subchannel-position")]
|
||||
public bool FixSubchannelPosition { get; init; }
|
||||
[Description("Try to fix subchannel. Implies fixing subchannel position.")]
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("--fix-subchannel")]
|
||||
public bool FixSubchannel { get; init; }
|
||||
[Description("If subchannel looks OK but CRC fails, rewrite it. Implies fixing subchannel.")]
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("--fix-subchannel-crc")]
|
||||
public bool FixSubchannelCrc { get; init; }
|
||||
[Description("Generates missing subchannels.")]
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("--generate-subchannels")]
|
||||
public bool GenerateSubchannels { get; init; }
|
||||
[Description("Try to decrypt encrypted sectors.")]
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("--decrypt")]
|
||||
public bool Decrypt { get; init; }
|
||||
[Description("Take metadata from existing Aaru Metadata sidecar.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-m|--aaru-metadata")]
|
||||
public string AaruMetadata { get; init; }
|
||||
[Description("Input image path")]
|
||||
[CommandArgument(0, "<input-image>")]
|
||||
public string InputPath { get; init; }
|
||||
[Description("Output image path")]
|
||||
[CommandArgument(1, "<output-image>")]
|
||||
public string OutputPath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -31,8 +31,7 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -44,43 +43,24 @@ using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using JetBrains.Annotations;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using Directory = System.IO.Directory;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class CreateSidecarCommand : Command
|
||||
sealed class CreateSidecarCommand : Command<CreateSidecarCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Create sidecar command";
|
||||
static ProgressTask _progressTask1;
|
||||
static ProgressTask _progressTask2;
|
||||
|
||||
public CreateSidecarCommand() : base("create-sidecar", UI.Image_Create_Sidecar_Command_Description)
|
||||
{
|
||||
Add(new Option<int>(["--block-size", "-b"], () => 512, UI.Tape_block_size_argument_help));
|
||||
|
||||
Add(new Option<string>(["--encoding", "-e"], () => null, UI.Name_of_character_encoding_to_use));
|
||||
|
||||
Add(new Option<bool>(["--tape", "-t"], () => false, UI.Tape_argument_input_help));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Media_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, uint blockSize, [CanBeNull] string encodingName,
|
||||
string imagePath, bool tape)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -98,7 +78,7 @@ sealed class CreateSidecarCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -111,22 +91,22 @@ sealed class CreateSidecarCommand : Command
|
||||
|
||||
Statistics.AddCommand("create-sidecar");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--block-size={0}", blockSize);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(encodingName ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--tape={0}", tape);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--block-size={0}", settings.BlockSize);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(settings.Encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--tape={0}", settings.Tape);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
Encoding encodingClass = null;
|
||||
|
||||
if(encodingName != null)
|
||||
if(settings.Encoding != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encodingName);
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(settings.Encoding);
|
||||
|
||||
if(verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
if(settings.Verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
@@ -136,9 +116,9 @@ sealed class CreateSidecarCommand : Command
|
||||
}
|
||||
}
|
||||
|
||||
if(File.Exists(imagePath))
|
||||
if(File.Exists(settings.ImagePath))
|
||||
{
|
||||
if(tape)
|
||||
if(settings.Tape)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.You_cannot_use_tape_option_when_input_is_a_file);
|
||||
|
||||
@@ -150,7 +130,7 @@ sealed class CreateSidecarCommand : Command
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -177,7 +157,7 @@ sealed class CreateSidecarCommand : Command
|
||||
return (int)ErrorNumber.UnrecognizedFormat;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
AaruConsole.VerboseWriteLine(UI.Image_format_identified_by_0_1, imageFormat.Name, imageFormat.Id);
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Image_format_identified_by_0, imageFormat.Name);
|
||||
@@ -214,7 +194,7 @@ sealed class CreateSidecarCommand : Command
|
||||
Statistics.AddMediaFormat(imageFormat.Format);
|
||||
Statistics.AddFilter(inputFilter.Name);
|
||||
|
||||
var sidecarClass = new Sidecar(imageFormat, imagePath, inputFilter.Id, encodingClass);
|
||||
var sidecarClass = new Sidecar(imageFormat, settings.ImagePath, inputFilter.Id, encodingClass);
|
||||
Metadata sidecar = new();
|
||||
|
||||
AnsiConsole.Progress()
|
||||
@@ -274,9 +254,10 @@ sealed class CreateSidecarCommand : Command
|
||||
ctx.AddTask(Localization.Core.Writing_metadata_sidecar).IsIndeterminate();
|
||||
|
||||
var jsonFs =
|
||||
new FileStream(Path.Combine(Path.GetDirectoryName(imagePath) ??
|
||||
new FileStream(Path.Combine(Path.GetDirectoryName(settings.ImagePath) ??
|
||||
throw new InvalidOperationException(),
|
||||
Path.GetFileNameWithoutExtension(imagePath) + ".metadata.json"),
|
||||
Path.GetFileNameWithoutExtension(settings.ImagePath) +
|
||||
".metadata.json"),
|
||||
FileMode.Create);
|
||||
|
||||
JsonSerializer.Serialize(jsonFs,
|
||||
@@ -298,17 +279,17 @@ sealed class CreateSidecarCommand : Command
|
||||
return (int)ErrorNumber.UnexpectedException;
|
||||
}
|
||||
}
|
||||
else if(Directory.Exists(imagePath))
|
||||
else if(Directory.Exists(settings.ImagePath))
|
||||
{
|
||||
if(!tape)
|
||||
if(!settings.Tape)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(Localization.Core.Cannot_create_a_sidecar_from_a_directory);
|
||||
|
||||
return (int)ErrorNumber.IsDirectory;
|
||||
}
|
||||
|
||||
string[] contents = Directory.GetFiles(imagePath, "*", SearchOption.TopDirectoryOnly);
|
||||
var files = contents.Where(file => new FileInfo(file).Length % blockSize == 0).ToList();
|
||||
string[] contents = Directory.GetFiles(settings.ImagePath, "*", SearchOption.TopDirectoryOnly);
|
||||
var files = contents.Where(file => new FileInfo(file).Length % settings.BlockSize == 0).ToList();
|
||||
|
||||
files.Sort(StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
@@ -361,7 +342,9 @@ sealed class CreateSidecarCommand : Command
|
||||
sidecarClass.Abort();
|
||||
};
|
||||
|
||||
sidecar = sidecarClass.BlockTape(Path.GetFileName(imagePath), files, blockSize);
|
||||
sidecar = sidecarClass.BlockTape(Path.GetFileName(settings.ImagePath),
|
||||
files,
|
||||
settings.BlockSize);
|
||||
});
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
@@ -369,9 +352,10 @@ sealed class CreateSidecarCommand : Command
|
||||
ctx.AddTask(Localization.Core.Writing_metadata_sidecar).IsIndeterminate();
|
||||
|
||||
var jsonFs =
|
||||
new FileStream(Path.Combine(Path.GetDirectoryName(imagePath) ??
|
||||
new FileStream(Path.Combine(Path.GetDirectoryName(settings.ImagePath) ??
|
||||
throw new InvalidOperationException(),
|
||||
Path.GetFileNameWithoutExtension(imagePath) + ".metadata.json"),
|
||||
Path.GetFileNameWithoutExtension(settings.ImagePath) +
|
||||
".metadata.json"),
|
||||
FileMode.Create);
|
||||
|
||||
JsonSerializer.Serialize(jsonFs,
|
||||
@@ -390,4 +374,27 @@ sealed class CreateSidecarCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[CommandOption("-b|--block-size")]
|
||||
[Description("Only used for tapes, indicates block size. Files in the folder whose size is not a multiple of this value will simply be ignored.")]
|
||||
[DefaultValue(512)]
|
||||
public uint BlockSize { get; init; }
|
||||
[CommandOption("-e|--encoding")]
|
||||
[Description("Name of character encoding to use.")]
|
||||
[DefaultValue(null)]
|
||||
public string Encoding { get; init; }
|
||||
[CommandOption("-t|--tape")]
|
||||
[Description("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).")]
|
||||
[DefaultValue(false)]
|
||||
public bool Tape { get; init; }
|
||||
[Description("Media image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,9 +30,7 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -44,41 +42,19 @@ using Aaru.Decoders.CD;
|
||||
using Aaru.Decoders.SCSI;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class DecodeCommand : Command
|
||||
sealed class DecodeCommand : Command<DecodeCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Decode command";
|
||||
|
||||
public DecodeCommand() : base("decode", UI.Image_Decode_Command_Description)
|
||||
{
|
||||
Add(new Option<bool>(["--disk-tags", "-f"], () => true, UI.Decode_media_tags));
|
||||
|
||||
Add(new Option<string>(["--length", "-l"],
|
||||
() => UI.Parameter_response_all_sectors,
|
||||
UI.How_many_sectors_to_decode_or_all));
|
||||
|
||||
Add(new Option<bool>(["--sector-tags", "-p"], () => true, UI.Decode_sector_tags));
|
||||
|
||||
Add(new Option<ulong>(["--start", "-s"], () => 0, UI.Sector_to_start_decoding_from));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Media_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool verbose, bool debug, bool diskTags, string imagePath, string length, bool sectorTags,
|
||||
ulong startSector)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -96,7 +72,7 @@ sealed class DecodeCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -109,20 +85,20 @@ sealed class DecodeCommand : Command
|
||||
|
||||
Statistics.AddCommand("decode");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--disk-tags={0}", diskTags);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--length={0}", Markup.Escape(length ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sector-tags={0}", sectorTags);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--start={0}", startSector);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--disk-tags={0}", settings.DiskTags);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--length={0}", Markup.Escape(settings.Length ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--sector-tags={0}", settings.SectorTags);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--start={0}", settings.StartSector);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -176,7 +152,7 @@ sealed class DecodeCommand : Command
|
||||
Statistics.AddMedia(inputFormat.Info.MediaType, false);
|
||||
Statistics.AddFilter(inputFilter.Name);
|
||||
|
||||
if(diskTags)
|
||||
if(settings.DiskTags)
|
||||
{
|
||||
if(inputFormat.Info.ReadableMediaTags.Count == 0)
|
||||
AaruConsole.WriteLine(UI.There_are_no_media_tags_in_chosen_disc_image);
|
||||
@@ -393,14 +369,14 @@ sealed class DecodeCommand : Command
|
||||
}
|
||||
}
|
||||
|
||||
if(!sectorTags) return (int)ErrorNumber.NoError;
|
||||
if(!settings.SectorTags) return (int)ErrorNumber.NoError;
|
||||
|
||||
if(length.ToLower(CultureInfo.CurrentUICulture) == UI.Parameter_response_all_sectors) {}
|
||||
if(settings.Length.ToLower(CultureInfo.CurrentUICulture) == UI.Parameter_response_all_sectors) {}
|
||||
else
|
||||
{
|
||||
if(!ulong.TryParse(length, out ulong _))
|
||||
if(!ulong.TryParse(settings.Length, out ulong _))
|
||||
{
|
||||
AaruConsole.WriteLine(UI.Value_0_is_not_a_valid_number_for_length, length);
|
||||
AaruConsole.WriteLine(UI.Value_0_is_not_a_valid_number_for_length, settings.Length);
|
||||
AaruConsole.WriteLine(UI.Not_decoding_sectors_tags);
|
||||
|
||||
return 3;
|
||||
@@ -429,4 +405,31 @@ sealed class DecodeCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[Description("Decode media tags.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-f|--disk-tags")]
|
||||
public bool DiskTags { get; init; }
|
||||
[Description("How many sectors to decode, or \"all\".")]
|
||||
[DefaultValue("all")]
|
||||
[CommandOption("-l|--length")]
|
||||
public string Length { get; init; }
|
||||
[Description("Decode sector tags.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-p|--sector-tags")]
|
||||
public bool SectorTags { get; init; }
|
||||
[Description("Sector to start decoding from.")]
|
||||
[DefaultValue(0)]
|
||||
[CommandOption("-s|--start")]
|
||||
public ulong StartSector { get; init; }
|
||||
[Description("Media image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,9 +30,7 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
@@ -40,43 +38,21 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class EntropyCommand : Command
|
||||
sealed class EntropyCommand : Command<EntropyCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Entropy command";
|
||||
static ProgressTask _progressTask1;
|
||||
static ProgressTask _progressTask2;
|
||||
|
||||
public EntropyCommand() : base("entropy", UI.Image_Entropy_Command_Description)
|
||||
{
|
||||
Add(new Option<bool>(["--duplicated-sectors", "-p"],
|
||||
() => true,
|
||||
UI.Calculates_how_many_sectors_are_duplicated));
|
||||
|
||||
Add(new Option<bool>(["--separated-tracks", "-t"],
|
||||
() => true,
|
||||
UI.Calculates_entropy_for_each_track_separately));
|
||||
|
||||
Add(new Option<bool>(["--whole-disc", "-w"], () => true, UI.Calculates_entropy_for_the_whole_disc));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Media_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, bool duplicatedSectors, string imagePath, bool separatedTracks,
|
||||
bool wholeDisc)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -94,7 +70,7 @@ sealed class EntropyCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -107,19 +83,19 @@ sealed class EntropyCommand : Command
|
||||
|
||||
Statistics.AddCommand("entropy");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--duplicated-sectors={0}", duplicatedSectors);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--separated-tracks={0}", separatedTracks);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--whole-disc={0}", wholeDisc);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--duplicated-sectors={0}", settings.DuplicatedSectors);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--separated-tracks={0}", settings.SeparatedTracks);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--whole-disc={0}", settings.WholeDisc);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -164,7 +140,10 @@ sealed class EntropyCommand : Command
|
||||
Statistics.AddMedia(inputFormat.Info.MediaType, false);
|
||||
Statistics.AddFilter(inputFilter.Name);
|
||||
|
||||
var entropyCalculator = new Entropy(debug, inputFormat);
|
||||
bool separatedTracks = settings.SeparatedTracks;
|
||||
bool wholeDisc = settings.WholeDisc;
|
||||
|
||||
var entropyCalculator = new Entropy(settings.Debug, inputFormat);
|
||||
|
||||
AnsiConsole.Progress()
|
||||
.AutoClear(true)
|
||||
@@ -204,7 +183,7 @@ sealed class EntropyCommand : Command
|
||||
_progressTask2 = null;
|
||||
};
|
||||
|
||||
if(wholeDisc && inputFormat is IOpticalMediaImage opticalFormat)
|
||||
if(settings.WholeDisc && inputFormat is IOpticalMediaImage opticalFormat)
|
||||
{
|
||||
if(opticalFormat.Sessions?.Count > 1)
|
||||
{
|
||||
@@ -221,7 +200,7 @@ sealed class EntropyCommand : Command
|
||||
if(separatedTracks)
|
||||
{
|
||||
EntropyResults[] tracksEntropy =
|
||||
entropyCalculator.CalculateTracksEntropy(duplicatedSectors);
|
||||
entropyCalculator.CalculateTracksEntropy(settings.DuplicatedSectors);
|
||||
|
||||
foreach(EntropyResults trackEntropy in tracksEntropy)
|
||||
{
|
||||
@@ -243,7 +222,8 @@ sealed class EntropyCommand : Command
|
||||
|
||||
EntropyResults entropy = inputFormat.Info.MetadataMediaType == MetadataMediaType.LinearMedia
|
||||
? entropyCalculator.CalculateLinearMediaEntropy()
|
||||
: entropyCalculator.CalculateMediaEntropy(duplicatedSectors);
|
||||
: entropyCalculator.CalculateMediaEntropy(settings
|
||||
.DuplicatedSectors);
|
||||
|
||||
AaruConsole.WriteLine(UI.Entropy_for_disk_is_0, entropy.Entropy);
|
||||
|
||||
@@ -257,4 +237,27 @@ sealed class EntropyCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[Description("Calculates how many sectors are duplicated (have same exact data in user area).")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-p|--duplicated-sectors")]
|
||||
public bool DuplicatedSectors { get; init; }
|
||||
[Description("Calculates entropy for each track separately.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-t|--separated-tracks")]
|
||||
public bool SeparatedTracks { get; init; }
|
||||
[Description("Calculates entropy for the whole disc.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-w|--whole-disc")]
|
||||
public bool WholeDisc { get; init; }
|
||||
[Description("Media image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,26 +30,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.CommandLine;
|
||||
using Aaru.Localization;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class ImageFamily : Command
|
||||
{
|
||||
public ImageFamily() : base("image", UI.Image_Command_Family_Description)
|
||||
{
|
||||
AddAlias("i");
|
||||
|
||||
AddCommand(new ChecksumCommand());
|
||||
AddCommand(new CompareCommand());
|
||||
AddCommand(new ConvertImageCommand());
|
||||
AddCommand(new CreateSidecarCommand());
|
||||
AddCommand(new DecodeCommand());
|
||||
AddCommand(new EntropyCommand());
|
||||
AddCommand(new ImageInfoCommand());
|
||||
AddCommand(new ListOptionsCommand());
|
||||
AddCommand(new PrintHexCommand());
|
||||
AddCommand(new VerifyCommand());
|
||||
}
|
||||
}
|
||||
class ImageFamily : BaseSettings {}
|
||||
@@ -31,8 +31,7 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
@@ -40,30 +39,19 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class ImageInfoCommand : Command
|
||||
sealed class ImageInfoCommand : Command<ImageInfoCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Image-info command";
|
||||
|
||||
public ImageInfoCommand() : base("info", UI.Image_Info_Command_Description)
|
||||
{
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Media_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string imagePath)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -81,7 +69,7 @@ sealed class ImageInfoCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -94,16 +82,16 @@ sealed class ImageInfoCommand : Command
|
||||
|
||||
Statistics.AddCommand("image-info");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -176,4 +164,15 @@ sealed class ImageInfoCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[Description("Media image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -31,8 +31,6 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -42,21 +40,20 @@ using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using JetBrains.Annotations;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class ListOptionsCommand : Command
|
||||
sealed class ListOptionsCommand : Command<ListOptionsCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "List-Options command";
|
||||
|
||||
public ListOptionsCommand() : base("options", UI.Image_Options_Command_Description) =>
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
|
||||
public static int Invoke(bool debug, bool verbose)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -74,7 +71,7 @@ sealed class ListOptionsCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -85,8 +82,8 @@ sealed class ListOptionsCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
Statistics.AddCommand("list-options");
|
||||
|
||||
PluginRegister plugins = PluginRegister.Singleton;
|
||||
@@ -144,4 +141,10 @@ sealed class ListOptionsCommand : Command
|
||||
|
||||
return type == typeof(string) ? UI.TypeToString_string : type.ToString();
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily {}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -31,8 +31,7 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
@@ -41,39 +40,20 @@ using Aaru.Core;
|
||||
using Aaru.Helpers;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class PrintHexCommand : Command
|
||||
sealed class PrintHexCommand : Command<PrintHexCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "PrintHex command";
|
||||
|
||||
public PrintHexCommand() : base("print", UI.Image_Print_Command_Description)
|
||||
{
|
||||
Add(new Option<ulong>(["--length", "-l"], () => 1, UI.How_many_sectors_to_print));
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
|
||||
Add(new Option<bool>(["--long-sectors", "-r"], () => false, UI.Print_sectors_with_tags_included));
|
||||
|
||||
Add(new Option<ulong>(["--start", "-s"], UI.Starting_sector));
|
||||
|
||||
Add(new Option<ushort>(["--width", "-w"], () => 32, UI.How_many_bytes_to_print_per_line));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Media_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string imagePath, ulong length, bool longSectors, ulong start,
|
||||
ushort width)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -91,7 +71,7 @@ sealed class PrintHexCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -104,20 +84,20 @@ sealed class PrintHexCommand : Command
|
||||
|
||||
Statistics.AddCommand("print-hex");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--length={0}", length);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--long-sectors={0}", longSectors);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--start={0}", start);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--width={0}", width);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--length={0}", settings.Length);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--long-sectors={0}", settings.LongSectors);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--start={0}", settings.Start);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--width={0}", settings.Width);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -129,6 +109,8 @@ sealed class PrintHexCommand : Command
|
||||
|
||||
IBaseImage inputFormat = null;
|
||||
|
||||
bool longSectors = settings.LongSectors;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_image_format).IsIndeterminate();
|
||||
@@ -162,36 +144,40 @@ sealed class PrintHexCommand : Command
|
||||
{
|
||||
var byteAddressableImage = inputFormat as IByteAddressableImage;
|
||||
|
||||
AaruConsole.WriteLine($"[bold][italic]{string.Format(UI.Start_0_as_in_sector_start, start)}[/][/]");
|
||||
AaruConsole.WriteLine($"[bold][italic]{string.Format(UI.Start_0_as_in_sector_start, settings.Start)}[/][/]");
|
||||
|
||||
var data = new byte[length];
|
||||
byte[] data = new byte[settings.Length];
|
||||
ErrorNumber errno = ErrorNumber.NoError;
|
||||
var bytesRead = 0;
|
||||
int bytesRead = 0;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Reading_data).IsIndeterminate();
|
||||
|
||||
errno = byteAddressableImage?.ReadBytesAt((long)start, data, 0, (int)length, out bytesRead) ??
|
||||
errno = byteAddressableImage?.ReadBytesAt((long)settings.Start,
|
||||
data,
|
||||
0,
|
||||
(int)settings.Length,
|
||||
out bytesRead) ??
|
||||
ErrorNumber.InvalidArgument;
|
||||
});
|
||||
|
||||
// TODO: Span
|
||||
if(bytesRead != (int)length)
|
||||
if(bytesRead != (int)settings.Length)
|
||||
{
|
||||
var tmp = new byte[bytesRead];
|
||||
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)));
|
||||
AaruConsole.WriteLine(Markup.Escape(PrintHex.ByteArrayToHexArrayString(data, settings.Width, true)));
|
||||
else
|
||||
AaruConsole.ErrorWriteLine(string.Format(UI.Error_0_reading_data_from_1, errno, start));
|
||||
AaruConsole.ErrorWriteLine(string.Format(UI.Error_0_reading_data_from_1, errno, settings.Start));
|
||||
}
|
||||
else
|
||||
{
|
||||
for(ulong i = 0; i < length; i++)
|
||||
for(ulong i = 0; i < settings.Length; i++)
|
||||
{
|
||||
if(inputFormat is not IMediaImage blockImage)
|
||||
{
|
||||
@@ -200,8 +186,9 @@ sealed class PrintHexCommand : Command
|
||||
break;
|
||||
}
|
||||
|
||||
AaruConsole.WriteLine($"[bold][italic]{string.Format(UI.Sector_0_as_in_sector_number, start)}[/][/]" +
|
||||
i);
|
||||
AaruConsole
|
||||
.WriteLine($"[bold][italic]{string.Format(UI.Sector_0_as_in_sector_number, settings.Start)}[/][/]" +
|
||||
i);
|
||||
|
||||
if(blockImage.Info.ReadableSectorTags == null)
|
||||
{
|
||||
@@ -227,17 +214,46 @@ sealed class PrintHexCommand : Command
|
||||
ctx.AddTask(UI.Reading_sector).IsIndeterminate();
|
||||
|
||||
errno = longSectors
|
||||
? blockImage.ReadSectorLong(start + i, out sector)
|
||||
: blockImage.ReadSector(start + i, out sector);
|
||||
? blockImage.ReadSectorLong(settings.Start + i, out sector)
|
||||
: blockImage.ReadSector(settings.Start + i, out sector);
|
||||
});
|
||||
|
||||
if(errno == ErrorNumber.NoError)
|
||||
AaruConsole.WriteLine(Markup.Escape(PrintHex.ByteArrayToHexArrayString(sector, width, true)));
|
||||
AaruConsole.WriteLine(Markup.Escape(PrintHex.ByteArrayToHexArrayString(sector,
|
||||
settings.Width,
|
||||
true)));
|
||||
else
|
||||
AaruConsole.ErrorWriteLine(string.Format(UI.Error_0_reading_sector_1, errno, start + i));
|
||||
AaruConsole.ErrorWriteLine(string.Format(UI.Error_0_reading_sector_1, errno, settings.Start + i));
|
||||
}
|
||||
}
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[Description("How many sectors to print.")]
|
||||
[DefaultValue(1)]
|
||||
[CommandOption("-l|--length")]
|
||||
public ulong Length { get; init; }
|
||||
[Description("Print sectors with tags included.")]
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("-r|--long-sectors")]
|
||||
public bool LongSectors { get; init; }
|
||||
[Description("Starting sector.")]
|
||||
[DefaultValue(0)]
|
||||
[CommandOption("-s|--start")]
|
||||
public ulong Start { get; init; }
|
||||
[Description("How many bytes to print per line.")]
|
||||
[DefaultValue(32)]
|
||||
[CommandOption("-w|--width")]
|
||||
public ushort Width { get; init; }
|
||||
[Description("Media image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,10 +30,8 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Aaru.CommonTypes;
|
||||
@@ -47,39 +45,19 @@ using Aaru.Localization;
|
||||
using Humanizer;
|
||||
using Humanizer.Localisation;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Image;
|
||||
|
||||
sealed class VerifyCommand : Command
|
||||
sealed class VerifyCommand : Command<VerifyCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Verify command";
|
||||
|
||||
public VerifyCommand() : base("verify", UI.Image_Verify_Command_Description)
|
||||
{
|
||||
Add(new Option<bool>(["--verify-disc", "-w"], () => true, UI.Verify_media_image_if_supported));
|
||||
|
||||
Add(new Option<bool>(["--verify-sectors", "-s"], () => true, UI.Verify_all_sectors_if_supported));
|
||||
|
||||
Add(new Option<bool>(["--create-graph", "-g"], () => true, UI.Create_graph_of_verified_disc));
|
||||
|
||||
Add(new Option<uint>(["--dimensions"], () => 1080, UI.Verify_dimensions_paramater_help));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Disc_image_path,
|
||||
Name = "image-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string imagePath, bool verifyDisc, bool verifySectors,
|
||||
bool createGraph, uint dimensions)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -97,7 +75,7 @@ sealed class VerifyCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -110,20 +88,20 @@ sealed class VerifyCommand : Command
|
||||
|
||||
Statistics.AddCommand("verify");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(imagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verify-disc={0}", verifyDisc);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verify-sectors={0}", verifySectors);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--create-graph={0}", createGraph);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--dimensions={0}", dimensions);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--input={0}", Markup.Escape(settings.ImagePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verify-disc={0}", settings.VerifyDisc);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verify-sectors={0}", settings.VerifySectors);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--create-graph={0}", settings.CreateGraph);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--dimensions={0}", settings.Dimensions);
|
||||
|
||||
IFilter inputFilter = null;
|
||||
|
||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||
{
|
||||
ctx.AddTask(UI.Identifying_file_filter).IsIndeterminate();
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(imagePath);
|
||||
inputFilter = PluginRegister.Singleton.GetFilter(settings.ImagePath);
|
||||
});
|
||||
|
||||
if(inputFilter == null)
|
||||
@@ -183,7 +161,7 @@ sealed class VerifyCommand : Command
|
||||
|
||||
var chkWatch = new Stopwatch();
|
||||
|
||||
if(verifyDisc && verifiableImage != null)
|
||||
if(settings.VerifyDisc && verifiableImage != null)
|
||||
{
|
||||
bool? discCheckStatus = null;
|
||||
|
||||
@@ -218,7 +196,7 @@ sealed class VerifyCommand : Command
|
||||
chkWatch.Elapsed.Humanize(minUnit: TimeUnit.Second));
|
||||
}
|
||||
|
||||
if(!verifySectors)
|
||||
if(!settings.VerifySectors)
|
||||
{
|
||||
return correctImage switch
|
||||
{
|
||||
@@ -237,17 +215,20 @@ sealed class VerifyCommand : Command
|
||||
{
|
||||
Spiral.DiscParameters spiralParameters = null;
|
||||
|
||||
if(createGraph) spiralParameters = Spiral.DiscParametersFromMediaType(opticalMediaImage.Info.MediaType);
|
||||
if(settings.CreateGraph)
|
||||
spiralParameters = Spiral.DiscParametersFromMediaType(opticalMediaImage.Info.MediaType);
|
||||
|
||||
if(spiralParameters is not null)
|
||||
{
|
||||
mediaGraph = new Spiral((int)dimensions,
|
||||
(int)dimensions,
|
||||
mediaGraph = new Spiral((int)settings.Dimensions,
|
||||
(int)settings.Dimensions,
|
||||
spiralParameters,
|
||||
opticalMediaImage.Info.Sectors);
|
||||
}
|
||||
else if(createGraph)
|
||||
mediaGraph = new BlockMap((int)dimensions, (int)dimensions, opticalMediaImage.Info.Sectors);
|
||||
else if(settings.CreateGraph)
|
||||
mediaGraph = new BlockMap((int)settings.Dimensions,
|
||||
(int)settings.Dimensions,
|
||||
opticalMediaImage.Info.Sectors);
|
||||
|
||||
List<Track> inputTracks = opticalMediaImage.Tracks;
|
||||
ulong currentSectorAll = 0;
|
||||
@@ -439,23 +420,25 @@ sealed class VerifyCommand : Command
|
||||
AaruConsole.VerboseWriteLine(UI.Checking_sector_checksums_took_0,
|
||||
stopwatch.Elapsed.Humanize(minUnit: TimeUnit.Second));
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.VerboseWriteLine($"[red]{UI.LBAs_with_error}[/]");
|
||||
|
||||
if(failingLbas.Count == (int)inputFormat.Info.Sectors)
|
||||
AaruConsole.VerboseWriteLine($"\t[red]{UI.all_sectors}[/]");
|
||||
else
|
||||
foreach(ulong t in failingLbas)
|
||||
AaruConsole.VerboseWriteLine("\t{0}", t);
|
||||
{
|
||||
foreach(ulong t in failingLbas) AaruConsole.VerboseWriteLine("\t{0}", t);
|
||||
}
|
||||
|
||||
AaruConsole.WriteLine($"[yellow3_1]{UI.LBAs_without_checksum}[/]");
|
||||
|
||||
if(unknownLbas.Count == (int)inputFormat.Info.Sectors)
|
||||
AaruConsole.VerboseWriteLine($"\t[yellow3_1]{UI.all_sectors}[/]");
|
||||
else
|
||||
foreach(ulong t in unknownLbas)
|
||||
AaruConsole.VerboseWriteLine("\t{0}", t);
|
||||
{
|
||||
foreach(ulong t in unknownLbas) AaruConsole.VerboseWriteLine("\t{0}", t);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Convert to table
|
||||
@@ -483,4 +466,31 @@ sealed class VerifyCommand : Command
|
||||
true => (int)ErrorNumber.NoError
|
||||
};
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : ImageFamily
|
||||
{
|
||||
[Description("Verify media image if supported.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-w|--verify-disc")]
|
||||
public bool VerifyDisc { get; init; }
|
||||
[Description("Verify all sectors if supported.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-s|--verify-sectors")]
|
||||
public bool VerifySectors { get; init; }
|
||||
[Description("Create graph of verified disc (currently only implemented for optical discs).")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("-g|--create-graph")]
|
||||
public bool CreateGraph { get; init; }
|
||||
[Description("Dimensions, as a square, in pixels, for the graph of verified media.")]
|
||||
[DefaultValue(1080)]
|
||||
[CommandOption("-d|--dimensions")]
|
||||
public uint Dimensions { get; init; }
|
||||
[Description("Disc image path")]
|
||||
[CommandArgument(0, "<image-path>")]
|
||||
public string ImagePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,9 +30,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -40,21 +37,20 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands;
|
||||
|
||||
sealed class ListEncodingsCommand : Command
|
||||
sealed class ListEncodingsCommand : Command<ListEncodingsCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "List-Encodings command";
|
||||
|
||||
public ListEncodingsCommand() : base("list-encodings", UI.List_Encodings_Command_Description) =>
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
|
||||
public static int Invoke(bool debug, bool verbose)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -72,7 +68,7 @@ sealed class ListEncodingsCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -85,8 +81,8 @@ sealed class ListEncodingsCommand : Command
|
||||
|
||||
Statistics.AddCommand("list-encodings");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
|
||||
var encodings = Encoding.GetEncodings()
|
||||
.Select(info => new CommonEncodingInfo
|
||||
@@ -123,5 +119,11 @@ sealed class ListEncodingsCommand : Command
|
||||
public string DisplayName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : BaseSettings {}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,10 +30,7 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -42,21 +39,19 @@ using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands;
|
||||
|
||||
sealed class ListNamespacesCommand : Command
|
||||
sealed class ListNamespacesCommand : Command<ListNamespacesCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "List-Namespaces command";
|
||||
|
||||
public ListNamespacesCommand() : base("list-namespaces", UI.List_Namespaces_Command_Description) =>
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
|
||||
public static int Invoke(bool debug, bool verbose)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -74,7 +69,7 @@ sealed class ListNamespacesCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -85,8 +80,8 @@ sealed class ListNamespacesCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
Statistics.AddCommand("list-namespaces");
|
||||
|
||||
PluginRegister plugins = PluginRegister.Singleton;
|
||||
@@ -112,4 +107,10 @@ sealed class ListNamespacesCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : BaseSettings {}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -33,8 +33,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -56,121 +55,24 @@ using Aaru.Core.Logging;
|
||||
using Aaru.Localization;
|
||||
using Schemas;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using Dump = Aaru.Core.Devices.Dumping.Dump;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Aaru.Commands.Media;
|
||||
|
||||
// TODO: Add raw dumping
|
||||
sealed class DumpMediaCommand : Command
|
||||
sealed class DumpMediaCommand : Command<DumpMediaCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Dump-Media command";
|
||||
static ProgressTask _progressTask1;
|
||||
static ProgressTask _progressTask2;
|
||||
|
||||
public DumpMediaCommand() : base("dump", UI.Media_Dump_Command_Description)
|
||||
{
|
||||
Add(new Option<string>(["--cicm-xml", "-x"], () => null, UI.Take_metadata_from_existing_CICM_XML_sidecar));
|
||||
|
||||
Add(new Option<string>(["--encoding", "-e"], () => null, UI.Name_of_character_encoding_to_use));
|
||||
|
||||
Add(new Option<bool>("--first-pregap", () => false, UI.Try_to_read_first_track_pregap));
|
||||
|
||||
Add(new Option<bool>("--fix-offset", () => true, UI.Fix_audio_tracks_offset));
|
||||
|
||||
Add(new Option<bool>(["--force", "-f"], () => false, UI.Continue_dumping_whatever_happens));
|
||||
|
||||
Add(new Option<string>(["--format", "-t"],
|
||||
() => null,
|
||||
UI.Format_of_the_output_image_as_plugin_name_or_plugin_id));
|
||||
|
||||
Add(new Option<bool>("--metadata", () => true, UI.Enables_creating_Aaru_Metadata_sidecar));
|
||||
|
||||
Add(new Option<bool>("--trim", () => true, UI.Enables_trimming_errored_from_skipped_sectors));
|
||||
|
||||
Add(new Option<string>(["--options", "-O"], () => null, UI.Comma_separated_name_value_pairs_of_image_options));
|
||||
|
||||
Add(new Option<bool>("--persistent", () => false, UI.Try_to_recover_partial_or_incorrect_data));
|
||||
|
||||
Add(new Option<bool>(["--resume", "-r"], () => true, UI.Create_or_use_resume_mapfile));
|
||||
|
||||
Add(new Option<ushort>(["--retry-passes", "-p"], () => 5, UI.How_many_retry_passes_to_do));
|
||||
|
||||
Add(new Option<uint>(["--skip", "-k"],
|
||||
() => 512,
|
||||
UI.When_an_unreadable_sector_is_found_skip_this_many_sectors));
|
||||
|
||||
Add(new Option<bool>(["--stop-on-error", "-s"], () => false, UI.Stop_media_dump_on_first_error));
|
||||
|
||||
Add(new Option<string>("--subchannel", () => UI.Subchannel_name_any, UI.Subchannel_to_dump_help));
|
||||
|
||||
Add(new Option<byte>("--speed", () => 0, UI.Speed_to_dump));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Device_path,
|
||||
Name = "device-path"
|
||||
});
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Output_image_path_Dump_help,
|
||||
Name = "output-path"
|
||||
});
|
||||
|
||||
Add(new Option<bool>(["--private"], () => false, UI.Do_not_store_paths_and_serial_numbers_in_log_or_metadata));
|
||||
|
||||
Add(new Option<bool>(["--fix-subchannel-position"], () => true, UI.Fix_subchannel_position_help));
|
||||
|
||||
Add(new Option<bool>(["--retry-subchannel"], () => true, UI.Retry_subchannel_help));
|
||||
|
||||
Add(new Option<bool>(["--fix-subchannel"], () => false, UI.Fix_subchannel_help));
|
||||
|
||||
Add(new Option<bool>(["--fix-subchannel-crc"], () => false, UI.Fix_subchannel_crc_help));
|
||||
|
||||
Add(new Option<bool>(["--generate-subchannels"], () => false, UI.Generate_subchannels_dump_help));
|
||||
|
||||
Add(new Option<bool>(["--skip-cdiready-hole"], () => true, UI.Skip_CDi_Ready_hole_help));
|
||||
|
||||
Add(new Option<bool>(["--eject"], () => false, UI.Eject_media_after_dump_finishes));
|
||||
|
||||
Add(new Option<uint>(["--max-blocks"], () => 64, UI.Maximum_number_of_blocks_to_read_at_once));
|
||||
|
||||
Add(new Option<bool>(["--use-buffered-reads"], () => true, UI.OS_buffered_reads_help));
|
||||
|
||||
Add(new Option<bool>(["--store-encrypted"], () => true, UI.Store_encrypted_data_as_is));
|
||||
|
||||
Add(new Option<bool>(["--title-keys"], () => true, UI.Try_to_read_the_title_keys_from_CSS_DVDs));
|
||||
|
||||
Add(new Option<uint>(["--ignore-cdr-runouts"],
|
||||
() => 10,
|
||||
UI.How_many_CDRW_run_out_sectors_to_ignore_and_regenerate));
|
||||
|
||||
Add(new Option<bool>(["--create-graph", "-g"], () => true, UI.Create_graph_of_dumped_media));
|
||||
|
||||
Add(new Option<uint>(["--dimensions"], () => 1080, UI.Dump_graph_dimensions_argument_help));
|
||||
|
||||
Add(new Option<string>(["--aaru-metadata", "-m"],
|
||||
() => null,
|
||||
"Take metadata from existing Aaru Metadata sidecar."));
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string cicmXml, string devicePath, bool resume, string encoding,
|
||||
bool firstPregap, bool fixOffset, bool force, bool metadata, bool trim, string outputPath,
|
||||
string options, bool persistent, ushort retryPasses, uint skip, byte speed,
|
||||
bool stopOnError, string format, string subchannel, bool @private,
|
||||
bool fixSubchannelPosition, bool retrySubchannel, bool fixSubchannel,
|
||||
bool fixSubchannelCrc, bool generateSubchannels, bool skipCdiReadyHole, bool eject,
|
||||
uint maxBlocks, bool useBufferedReads, bool storeEncrypted, bool titleKeys,
|
||||
uint ignoreCdrRunOuts, bool createGraph, uint dimensions, string aaruMetadata)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -188,7 +90,7 @@ sealed class DumpMediaCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -199,53 +101,60 @@ sealed class DumpMediaCommand : Command
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
bool fixSubchannel = settings.FixSubchannel;
|
||||
bool fixSubchannelCrc = settings.FixSubchannelCrc;
|
||||
bool fixSubchannelPosition = settings.FixSubchannelPosition;
|
||||
uint maxBlocks = settings.MaxBlocks;
|
||||
bool eject = settings.Eject;
|
||||
|
||||
fixSubchannel |= fixSubchannelCrc;
|
||||
fixSubchannelPosition |= retrySubchannel || fixSubchannel;
|
||||
fixSubchannelPosition |= settings.RetrySubchannel || fixSubchannel;
|
||||
|
||||
if(maxBlocks == 0) maxBlocks = 64;
|
||||
|
||||
Statistics.AddCommand("dump-media");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--cicm-xml={0}", Markup.Escape(cicmXml ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--device={0}", Markup.Escape(devicePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--first-pregap={0}", firstPregap);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-offset={0}", fixOffset);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--force={0}", force);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--format={0}", Markup.Escape(format ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--metadata={0}", metadata);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--options={0}", Markup.Escape(options ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output={0}", Markup.Escape(outputPath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--persistent={0}", persistent);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--resume={0}", resume);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--retry-passes={0}", retryPasses);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--skip={0}", skip);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--stop-on-error={0}", stopOnError);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--trim={0}", trim);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--subchannel={0}", Markup.Escape(subchannel ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "----private={0}", @private);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel-position={0}", fixSubchannelPosition);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--retry-subchannel={0}", retrySubchannel);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel={0}", fixSubchannel);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel-crc={0}", fixSubchannelCrc);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--generate-subchannels={0}", generateSubchannels);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--skip-cdiready-hole={0}", skipCdiReadyHole);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--eject={0}", eject);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--max-blocks={0}", maxBlocks);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--use-buffered-reads={0}", useBufferedReads);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--store-encrypted={0}", storeEncrypted);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--title-keys={0}", titleKeys);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--ignore-cdr-runouts={0}", ignoreCdrRunOuts);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--create-graph={0}", createGraph);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--dimensions={0}", dimensions);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--aaru-metadata={0}", Markup.Escape(aaruMetadata ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--cicm-xml={0}", Markup.Escape(settings.CicmXml ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--device={0}", Markup.Escape(settings.DevicePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--encoding={0}", Markup.Escape(settings.Encoding ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--first-pregap={0}", settings.FirstPregap);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-offset={0}", settings.FixOffset);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--force={0}", settings.Force);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--format={0}", Markup.Escape(settings.Format ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--metadata={0}", settings.Metadata);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--options={0}", Markup.Escape(settings.Options ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--output={0}", Markup.Escape(settings.OutputPath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--persistent={0}", settings.Persistent);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--resume={0}", settings.Resume);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--retry-passes={0}", settings.RetryPasses);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--skip={0}", settings.Skip);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--stop-on-error={0}", settings.StopOnError);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--trim={0}", settings.Trim);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--subchannel={0}", Markup.Escape(settings.Subchannel ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "----private={0}", settings.Private);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel-position={0}", settings.FixSubchannelPosition);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--retry-subchannel={0}", settings.RetrySubchannel);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel={0}", fixSubchannel);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--fix-subchannel-crc={0}", fixSubchannelCrc);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--generate-subchannels={0}", settings.GenerateSubchannels);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--skip-cdiready-hole={0}", settings.SkipCdiReadyHole);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--eject={0}", eject);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--max-blocks={0}", maxBlocks);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--use-buffered-reads={0}", settings.UseBufferedReads);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--store-encrypted={0}", settings.StoreEncrypted);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--title-keys={0}", settings.TitleKeys);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--ignore-cdr-runouts={0}", settings.IgnoreCdrRunOuts);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--create-graph={0}", settings.CreateGraph);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--dimensions={0}", settings.Dimensions);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--aaru-metadata={0}", Markup.Escape(settings.AaruMetadata ?? ""));
|
||||
|
||||
// TODO: Disabled temporarily
|
||||
//AaruConsole.DebugWriteLine(MODULE_NAME, "--raw={0}", Markup.Escape(raw ?? ""));
|
||||
|
||||
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
|
||||
Dictionary<string, string> parsedOptions = Options.Parse(settings.Options);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, UI.Parsed_options);
|
||||
|
||||
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
|
||||
@@ -253,13 +162,13 @@ sealed class DumpMediaCommand : Command
|
||||
|
||||
Encoding encodingClass = null;
|
||||
|
||||
if(encoding != null)
|
||||
if(settings.Encoding != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(settings.Encoding);
|
||||
|
||||
if(verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
if(settings.Verbose) AaruConsole.VerboseWriteLine(UI.encoding_for_0, encodingClass.EncodingName);
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
@@ -271,43 +180,44 @@ sealed class DumpMediaCommand : Command
|
||||
|
||||
DumpSubchannel wantedSubchannel = DumpSubchannel.Any;
|
||||
|
||||
if(subchannel?.ToLower(CultureInfo.CurrentUICulture) == UI.Subchannel_name_any || subchannel is null)
|
||||
if(settings.Subchannel?.ToLower(CultureInfo.CurrentUICulture) == UI.Subchannel_name_any ||
|
||||
settings.Subchannel is null)
|
||||
wantedSubchannel = DumpSubchannel.Any;
|
||||
else if(subchannel?.ToLowerInvariant() == UI.Subchannel_name_rw)
|
||||
else if(settings.Subchannel?.ToLowerInvariant() == UI.Subchannel_name_rw)
|
||||
wantedSubchannel = DumpSubchannel.Rw;
|
||||
else if(subchannel?.ToLowerInvariant() == UI.Subchannel_name_rw_or_pq)
|
||||
else if(settings.Subchannel?.ToLowerInvariant() == UI.Subchannel_name_rw_or_pq)
|
||||
wantedSubchannel = DumpSubchannel.RwOrPq;
|
||||
else if(subchannel?.ToLowerInvariant() == UI.Subchannel_name_pq)
|
||||
else if(settings.Subchannel?.ToLowerInvariant() == UI.Subchannel_name_pq)
|
||||
wantedSubchannel = DumpSubchannel.Pq;
|
||||
else if(subchannel?.ToLowerInvariant() == UI.Subchannel_name_none)
|
||||
else if(settings.Subchannel?.ToLowerInvariant() == UI.Subchannel_name_none)
|
||||
wantedSubchannel = DumpSubchannel.None;
|
||||
else
|
||||
AaruConsole.WriteLine(UI.Incorrect_subchannel_type_0_requested, subchannel);
|
||||
AaruConsole.WriteLine(UI.Incorrect_subchannel_type_0_requested, settings.Subchannel);
|
||||
|
||||
string filename = Path.GetFileNameWithoutExtension(outputPath);
|
||||
string filename = Path.GetFileNameWithoutExtension(settings.OutputPath);
|
||||
|
||||
bool isResponse = filename.StartsWith("#", StringComparison.OrdinalIgnoreCase) &&
|
||||
File.Exists(Path.Combine(Path.GetDirectoryName(outputPath),
|
||||
Path.GetFileNameWithoutExtension(outputPath)));
|
||||
File.Exists(Path.Combine(Path.GetDirectoryName(settings.OutputPath),
|
||||
Path.GetFileNameWithoutExtension(settings.OutputPath)));
|
||||
|
||||
TextReader resReader;
|
||||
|
||||
if(isResponse)
|
||||
{
|
||||
resReader = new StreamReader(Path.Combine(Path.GetDirectoryName(outputPath),
|
||||
Path.GetFileNameWithoutExtension(outputPath)));
|
||||
resReader = new StreamReader(Path.Combine(Path.GetDirectoryName(settings.OutputPath),
|
||||
Path.GetFileNameWithoutExtension(settings.OutputPath)));
|
||||
}
|
||||
else
|
||||
resReader = new StringReader(Path.GetFileNameWithoutExtension(outputPath));
|
||||
resReader = new StringReader(Path.GetFileNameWithoutExtension(settings.OutputPath));
|
||||
|
||||
if(isResponse) eject = true;
|
||||
|
||||
PluginRegister plugins = PluginRegister.Singleton;
|
||||
List<IBaseWritableImage> candidates = [];
|
||||
string extension = Path.GetExtension(outputPath);
|
||||
string extension = Path.GetExtension(settings.OutputPath);
|
||||
|
||||
// Try extension
|
||||
if(string.IsNullOrEmpty(format))
|
||||
if(string.IsNullOrEmpty(settings.Format))
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
@@ -316,7 +226,7 @@ sealed class DumpMediaCommand : Command
|
||||
}
|
||||
|
||||
// Try Id
|
||||
else if(Guid.TryParse(format, out Guid outId))
|
||||
else if(Guid.TryParse(settings.Format, out Guid outId))
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
@@ -329,7 +239,7 @@ sealed class DumpMediaCommand : Command
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
where plugin.Name.Equals(format, StringComparison.InvariantCultureIgnoreCase)
|
||||
where plugin.Name.Equals(settings.Format, StringComparison.InvariantCultureIgnoreCase)
|
||||
select plugin);
|
||||
}
|
||||
|
||||
@@ -381,6 +291,8 @@ sealed class DumpMediaCommand : Command
|
||||
.Replace('*', '*');
|
||||
}
|
||||
|
||||
string devicePath = settings.DevicePath;
|
||||
|
||||
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
|
||||
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
|
||||
|
||||
@@ -424,11 +336,11 @@ sealed class DumpMediaCommand : Command
|
||||
|
||||
Statistics.AddDevice(dev);
|
||||
|
||||
string outputPrefix = Path.Combine(Path.GetDirectoryName(outputPath), responseLine);
|
||||
string outputPrefix = Path.Combine(Path.GetDirectoryName(settings.OutputPath), responseLine);
|
||||
|
||||
Resume resumeClass = null;
|
||||
|
||||
if(resume)
|
||||
if(settings.Resume)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -445,7 +357,7 @@ sealed class DumpMediaCommand : Command
|
||||
}
|
||||
|
||||
// DEPRECATED: To be removed in Aaru 7
|
||||
else if(File.Exists(outputPrefix + ".resume.xml") && resume)
|
||||
else if(File.Exists(outputPrefix + ".resume.xml") && settings.Resume)
|
||||
{
|
||||
// Should be covered by virtue of being the same exact class as the JSON above
|
||||
#pragma warning disable IL2026
|
||||
@@ -488,13 +400,13 @@ sealed class DumpMediaCommand : Command
|
||||
|
||||
Metadata sidecar = null;
|
||||
|
||||
if(aaruMetadata != null)
|
||||
if(settings.AaruMetadata != null)
|
||||
{
|
||||
if(File.Exists(aaruMetadata))
|
||||
if(File.Exists(settings.AaruMetadata))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fs = new FileStream(aaruMetadata, FileMode.Open);
|
||||
var fs = new FileStream(settings.AaruMetadata, FileMode.Open);
|
||||
|
||||
sidecar =
|
||||
(JsonSerializer.Deserialize(fs, typeof(MetadataJson), MetadataJsonContext.Default) as
|
||||
@@ -520,13 +432,13 @@ sealed class DumpMediaCommand : Command
|
||||
return (int)ErrorNumber.NoSuchFile;
|
||||
}
|
||||
}
|
||||
else if(cicmXml != null)
|
||||
else if(settings.CicmXml != null)
|
||||
{
|
||||
if(File.Exists(cicmXml))
|
||||
if(File.Exists(settings.CicmXml))
|
||||
{
|
||||
try
|
||||
{
|
||||
var sr = new StreamReader(cicmXml);
|
||||
var sr = new StreamReader(settings.CicmXml);
|
||||
|
||||
// Bypassed by JSON source generator used above
|
||||
#pragma warning disable IL2026
|
||||
@@ -563,16 +475,16 @@ sealed class DumpMediaCommand : Command
|
||||
candidates = [];
|
||||
|
||||
// Try extension
|
||||
if(string.IsNullOrEmpty(format))
|
||||
if(string.IsNullOrEmpty(settings.Format))
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
where plugin.KnownExtensions.Contains(Path.GetExtension(outputPath))
|
||||
where plugin.KnownExtensions.Contains(Path.GetExtension(settings.OutputPath))
|
||||
select plugin);
|
||||
}
|
||||
|
||||
// Try Id
|
||||
else if(Guid.TryParse(format, out Guid outId))
|
||||
else if(Guid.TryParse(settings.Format, out Guid outId))
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
@@ -585,15 +497,16 @@ sealed class DumpMediaCommand : Command
|
||||
{
|
||||
candidates.AddRange(from plugin in plugins.WritableImages.Values
|
||||
where plugin is not null
|
||||
where plugin.Name.Equals(format, StringComparison.InvariantCultureIgnoreCase)
|
||||
where plugin.Name.Equals(settings.Format,
|
||||
StringComparison.InvariantCultureIgnoreCase)
|
||||
select plugin);
|
||||
}
|
||||
|
||||
IBaseWritableImage outputFormat = candidates[0];
|
||||
|
||||
var dumpLog = new DumpLog(outputPrefix + ".log", dev, @private);
|
||||
var dumpLog = new DumpLog(outputPrefix + ".log", dev, settings.Private);
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
dumpLog.WriteLine(UI.Output_image_format_0_1, outputFormat.Name, outputFormat.Id);
|
||||
AaruConsole.VerboseWriteLine(UI.Output_image_format_0_1, outputFormat.Name, outputFormat.Id);
|
||||
@@ -606,15 +519,15 @@ sealed class DumpMediaCommand : Command
|
||||
|
||||
var errorLog = new ErrorLog(outputPrefix + ".error.log");
|
||||
|
||||
var dumper = new Dump(resume,
|
||||
var dumper = new Dump(settings.Resume,
|
||||
dev,
|
||||
devicePath,
|
||||
outputFormat,
|
||||
retryPasses,
|
||||
force,
|
||||
settings.RetryPasses,
|
||||
settings.Force,
|
||||
false,
|
||||
persistent,
|
||||
stopOnError,
|
||||
settings.Persistent,
|
||||
settings.StopOnError,
|
||||
resumeClass,
|
||||
dumpLog,
|
||||
encodingClass,
|
||||
@@ -622,29 +535,29 @@ sealed class DumpMediaCommand : Command
|
||||
outputPrefix + extension,
|
||||
parsedOptions,
|
||||
sidecar,
|
||||
skip,
|
||||
metadata,
|
||||
trim,
|
||||
firstPregap,
|
||||
fixOffset,
|
||||
debug,
|
||||
settings.Skip,
|
||||
settings.Metadata,
|
||||
settings.Trim,
|
||||
settings.FirstPregap,
|
||||
settings.FixOffset,
|
||||
settings.Debug,
|
||||
wantedSubchannel,
|
||||
speed,
|
||||
@private,
|
||||
settings.Speed,
|
||||
settings.Private,
|
||||
fixSubchannelPosition,
|
||||
retrySubchannel,
|
||||
settings.RetrySubchannel,
|
||||
fixSubchannel,
|
||||
fixSubchannelCrc,
|
||||
skipCdiReadyHole,
|
||||
settings.SkipCdiReadyHole,
|
||||
errorLog,
|
||||
generateSubchannels,
|
||||
settings.GenerateSubchannels,
|
||||
maxBlocks,
|
||||
useBufferedReads,
|
||||
storeEncrypted,
|
||||
titleKeys,
|
||||
ignoreCdrRunOuts,
|
||||
createGraph,
|
||||
dimensions);
|
||||
settings.UseBufferedReads,
|
||||
settings.StoreEncrypted,
|
||||
settings.TitleKeys,
|
||||
settings.IgnoreCdrRunOuts,
|
||||
settings.CreateGraph,
|
||||
settings.Dimensions);
|
||||
|
||||
AnsiConsole.Progress()
|
||||
.AutoClear(true)
|
||||
@@ -765,4 +678,146 @@ sealed class DumpMediaCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : MediaFamily
|
||||
{
|
||||
[Description("Take metadata from existing CICM XML sidecar.")]
|
||||
[CommandOption("-x|--cicm-xml")]
|
||||
[DefaultValue(null)]
|
||||
public string CicmXml { get; init; }
|
||||
[Description("Name of character encoding to use.")]
|
||||
[CommandOption("-e|--encoding")]
|
||||
[DefaultValue(null)]
|
||||
public string Encoding { get; init; }
|
||||
[Description("Try to read first track pregap. Only applicable to CD/DDCD/GD.")]
|
||||
[CommandOption("--first-pregap")]
|
||||
[DefaultValue(false)]
|
||||
public bool FirstPregap { get; init; }
|
||||
[Description("Fix audio tracks offset. Only applicable to CD/GD.")]
|
||||
[CommandOption("--fix-offset")]
|
||||
[DefaultValue(true)]
|
||||
public bool FixOffset { get; init; }
|
||||
[Description("Continue dumping whatever happens.")]
|
||||
[CommandOption("-f|--force")]
|
||||
[DefaultValue(false)]
|
||||
public bool Force { get; init; }
|
||||
[Description("Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.")]
|
||||
[CommandOption("-t|--format")]
|
||||
[DefaultValue(null)]
|
||||
public string Format { get; init; }
|
||||
[Description("Enables creating Aaru Metadata sidecar.")]
|
||||
[CommandOption("--metadata")]
|
||||
[DefaultValue(true)]
|
||||
public bool Metadata { get; init; }
|
||||
[Description("Enables trimming errored from skipped sectors.")]
|
||||
[CommandOption("--trim")]
|
||||
[DefaultValue(true)]
|
||||
public bool Trim { get; init; }
|
||||
[Description("Comma separated name=value pairs of options to pass to output image plugin.")]
|
||||
[CommandOption("-O|--options")]
|
||||
[DefaultValue(null)]
|
||||
public string Options { get; init; }
|
||||
[Description("Try to recover partial or incorrect data.")]
|
||||
[CommandOption("--persistent")]
|
||||
[DefaultValue(false)]
|
||||
public bool Persistent { get; init; }
|
||||
[Description("Create/use resume mapfile.")]
|
||||
[CommandOption("-r|--resume")]
|
||||
[DefaultValue(true)]
|
||||
public bool Resume { get; init; }
|
||||
[Description("How many retry passes to do.")]
|
||||
[CommandOption("-p|--retry-passes")]
|
||||
[DefaultValue(5)]
|
||||
public ushort RetryPasses { get; init; }
|
||||
[Description("When an unreadable sector is found skip this many sectors.")]
|
||||
[CommandOption("-k|--skip")]
|
||||
[DefaultValue(512)]
|
||||
public uint Skip { get; init; }
|
||||
[Description("Stop media dump on first error.")]
|
||||
[CommandOption("-s|--stop-on-error")]
|
||||
[DefaultValue(false)]
|
||||
public bool StopOnError { get; init; }
|
||||
[Description("Subchannel to dump. Only applicable to CD/GD. Values: any, rw, rw-or-pq, pq, none.")]
|
||||
[CommandOption("--subchannel")]
|
||||
[DefaultValue("any")]
|
||||
public string Subchannel { get; init; }
|
||||
[Description("Speed to dump. Only applicable to optical drives, 0 for maximum.")]
|
||||
[CommandOption("--speed")]
|
||||
[DefaultValue(0)]
|
||||
public byte Speed { get; init; }
|
||||
[Description("Do not store paths and serial numbers in log or metadata.")]
|
||||
[CommandOption("--private")]
|
||||
[DefaultValue(false)]
|
||||
public bool Private { get; init; }
|
||||
[Description("Store subchannel according to the sector they describe.")]
|
||||
[CommandOption("--fix-subchannel-position")]
|
||||
[DefaultValue(true)]
|
||||
public bool FixSubchannelPosition { get; init; }
|
||||
[Description("Retry subchannel. Implies fixing subchannel position.")]
|
||||
[CommandOption("--retry-subchannel")]
|
||||
[DefaultValue(true)]
|
||||
public bool RetrySubchannel { get; init; }
|
||||
[Description("Try to fix subchannel. Implies fixing subchannel position.")]
|
||||
[CommandOption("--fix-subchannel")]
|
||||
[DefaultValue(false)]
|
||||
public bool FixSubchannel { get; init; }
|
||||
[Description("If subchannel looks OK but CRC fails, rewrite it. Implies fixing subchannel.")]
|
||||
[CommandOption("--fix-subchannel-crc")]
|
||||
[DefaultValue(false)]
|
||||
public bool FixSubchannelCrc { get; init; }
|
||||
[Description("Generates missing subchannels (they don\'t count as dumped in resume file).")]
|
||||
[CommandOption("--generate-subchannels")]
|
||||
[DefaultValue(false)]
|
||||
public bool GenerateSubchannels { get; init; }
|
||||
[Description("Skip the hole between data and audio in a CD-i Ready disc.")]
|
||||
[CommandOption("--skip-cdiready-hole")]
|
||||
[DefaultValue(true)]
|
||||
public bool SkipCdiReadyHole { get; init; }
|
||||
[Description("Eject media after dump finishes.")]
|
||||
[CommandOption("--eject")]
|
||||
[DefaultValue(false)]
|
||||
public bool Eject { get; init; }
|
||||
[Description("Maximum number of blocks to read at once.")]
|
||||
[CommandOption("--max-blocks")]
|
||||
[DefaultValue(64)]
|
||||
public uint MaxBlocks { get; init; }
|
||||
[Description("Use OS buffered reads if CMD23 is not supported. Only applicable to MMC/SD.")]
|
||||
[CommandOption("--use-buffered-reads")]
|
||||
[DefaultValue(true)]
|
||||
public bool UseBufferedReads { get; init; }
|
||||
[Description("Store encrypted data as is.")]
|
||||
[CommandOption("--store-encrypted")]
|
||||
[DefaultValue(true)]
|
||||
public bool StoreEncrypted { get; init; }
|
||||
[Description("Try to read the title keys from CSS encrypted DVDs (very slow).")]
|
||||
[CommandOption("--title-keys")]
|
||||
[DefaultValue(true)]
|
||||
public bool TitleKeys { get; init; }
|
||||
[Description("How many CD-R(W) run-out sectors to ignore and regenerate (0 for none).")]
|
||||
[CommandOption("--ignore-cdr-runouts")]
|
||||
[DefaultValue(10)]
|
||||
public uint IgnoreCdrRunOuts { get; init; }
|
||||
[Description("Create graph of dumped media. Currently only supported for CD/DVD/BD/GD/UMD.")]
|
||||
[CommandOption("-g|--create-graph")]
|
||||
[DefaultValue(true)]
|
||||
public bool CreateGraph { get; init; }
|
||||
[Description("Dimensions in pixels of the square that will contain the graph of dumped media.")]
|
||||
[CommandOption("--dimensions")]
|
||||
[DefaultValue(1080)]
|
||||
public uint Dimensions { get; init; }
|
||||
[Description("Take metadata from existing Aaru Metadata sidecar.")]
|
||||
[CommandOption("--aaru-metadata")]
|
||||
[DefaultValue(null)]
|
||||
public string AaruMetadata { get; init; }
|
||||
[Description("Device path")]
|
||||
[CommandArgument(0, "<device-path>")]
|
||||
public string DevicePath { get; init; }
|
||||
[Description("Output image path. If filename starts with # and exists, it will be read as a list of output images, its extension will be used to detect the image output format, each media will be ejected and confirmation for the next one will be asked.")]
|
||||
[CommandArgument(1, "<output-path>")]
|
||||
public string OutputPath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
@@ -53,9 +52,9 @@ using Aaru.Decoders.Xbox;
|
||||
using Aaru.Localization;
|
||||
using Humanizer.Bytes;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using BCA = Aaru.Decoders.Bluray.BCA;
|
||||
using Cartridge = Aaru.Decoders.DVD.Cartridge;
|
||||
using Command = System.CommandLine.Command;
|
||||
using DDS = Aaru.Decoders.DVD.DDS;
|
||||
using DMI = Aaru.Decoders.Xbox.DMI;
|
||||
using Session = Aaru.Decoders.CD.Session;
|
||||
@@ -63,29 +62,16 @@ using Spare = Aaru.Decoders.DVD.Spare;
|
||||
|
||||
namespace Aaru.Commands.Media;
|
||||
|
||||
sealed class MediaInfoCommand : Command
|
||||
sealed class MediaInfoCommand : Command<MediaInfoCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Media-Info command";
|
||||
|
||||
public MediaInfoCommand() : base("info", UI.Media_Info_Command_Description)
|
||||
{
|
||||
Add(new Option<string>(["--output-prefix", "-w"], () => null, UI.Prefix_for_saving_binary_information));
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Device_path,
|
||||
Name = "device-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string devicePath, string outputPrefix)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -103,7 +89,7 @@ sealed class MediaInfoCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -116,10 +102,12 @@ sealed class MediaInfoCommand : Command
|
||||
|
||||
Statistics.AddCommand("media-info");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "device={0}", Markup.Escape(devicePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "output-prefix={0}", Markup.Escape(outputPrefix ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "device={0}", Markup.Escape(settings.DevicePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "output-prefix={0}", Markup.Escape(settings.OutputPrefix ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "verbose={0}", settings.Verbose);
|
||||
|
||||
string devicePath = settings.DevicePath;
|
||||
|
||||
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
|
||||
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
|
||||
@@ -170,12 +158,12 @@ sealed class MediaInfoCommand : Command
|
||||
|
||||
break;
|
||||
case DeviceType.NVMe:
|
||||
DoNvmeMediaInfo(outputPrefix, dev);
|
||||
DoNvmeMediaInfo(settings.OutputPrefix, dev);
|
||||
|
||||
break;
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
DoScsiMediaInfo(debug, outputPrefix, dev);
|
||||
DoScsiMediaInfo(settings.Debug, settings.OutputPrefix, dev);
|
||||
|
||||
break;
|
||||
default:
|
||||
@@ -827,7 +815,7 @@ sealed class MediaInfoCommand : Command
|
||||
|
||||
AaruConsole.Write($"[bold]{Localization.Core.Media_Serial_Number}:[/] ");
|
||||
|
||||
for(var i = 4; i < scsiInfo.MediaSerialNumber.Length; i++)
|
||||
for(int i = 4; i < scsiInfo.MediaSerialNumber.Length; i++)
|
||||
AaruConsole.Write("{0:X2}", scsiInfo.MediaSerialNumber[i]);
|
||||
|
||||
AaruConsole.WriteLine();
|
||||
@@ -843,13 +831,13 @@ sealed class MediaInfoCommand : Command
|
||||
|
||||
if(tracks != null)
|
||||
{
|
||||
var firstLba = (uint)tracks.Min(t => t.StartSector);
|
||||
uint firstLba = (uint)tracks.Min(t => t.StartSector);
|
||||
|
||||
bool supportsPqSubchannel = Dump.SupportsPqSubchannel(dev, null, null, firstLba);
|
||||
bool supportsRwSubchannel = Dump.SupportsRwSubchannel(dev, null, null, firstLba);
|
||||
|
||||
// Open main database
|
||||
var ctx = AaruContext.Create(Settings.Settings.MainDbPath);
|
||||
var ctx = AaruContext.Create(Aaru.Settings.Settings.MainDbPath);
|
||||
|
||||
// Search for device in main database
|
||||
Aaru.Database.Models.Device dbDev =
|
||||
@@ -867,7 +855,7 @@ sealed class MediaInfoCommand : Command
|
||||
out bool inexactPositioning,
|
||||
false);
|
||||
|
||||
for(var t = 1; t < tracks.Length; t++) tracks[t - 1].EndSector = tracks[t].StartSector - 1;
|
||||
for(int t = 1; t < tracks.Length; t++) tracks[t - 1].EndSector = tracks[t].StartSector - 1;
|
||||
|
||||
tracks[^1].EndSector = (ulong)lastSector;
|
||||
|
||||
@@ -969,4 +957,19 @@ sealed class MediaInfoCommand : Command
|
||||
|
||||
dev.Close();
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : MediaFamily
|
||||
{
|
||||
[Description("Prefix for saving binary information from device.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-w|--output-prefix")]
|
||||
public string OutputPrefix { get; init; }
|
||||
[Description("Device path")]
|
||||
[CommandArgument(0, "<device-path>")]
|
||||
public string DevicePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -30,19 +30,6 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.CommandLine;
|
||||
using Aaru.Localization;
|
||||
|
||||
namespace Aaru.Commands.Media;
|
||||
|
||||
sealed class MediaFamily : Command
|
||||
{
|
||||
public MediaFamily() : base("media", UI.Media_Command_Family_Description)
|
||||
{
|
||||
AddAlias("m");
|
||||
|
||||
AddCommand(new DumpMediaCommand());
|
||||
AddCommand(new MediaInfoCommand());
|
||||
AddCommand(new MediaScanCommand());
|
||||
}
|
||||
}
|
||||
class MediaFamily : BaseSettings {}
|
||||
@@ -30,9 +30,7 @@
|
||||
// Copyright © 2011-2025 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
@@ -42,42 +40,20 @@ using Humanizer;
|
||||
using Humanizer.Bytes;
|
||||
using Humanizer.Localisation;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Aaru.Commands.Media;
|
||||
|
||||
sealed class MediaScanCommand : Command
|
||||
sealed class MediaScanCommand : Command<MediaScanCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Media-Scan command";
|
||||
static ProgressTask _progressTask1;
|
||||
|
||||
public MediaScanCommand() : base("scan", UI.Media_Scan_Command_Description)
|
||||
{
|
||||
Add(new Option<string>(["--mhdd-log", "-m"],
|
||||
() => null,
|
||||
UI.Write_a_log_of_the_scan_in_the_format_used_by_MHDD));
|
||||
|
||||
Add(new Option<string>(["--ibg-log", "-b"],
|
||||
() => null,
|
||||
UI.Write_a_log_of_the_scan_in_the_format_used_by_ImgBurn));
|
||||
|
||||
Add(new Option<bool>(["--use-buffered-reads"], () => true, UI.OS_buffered_reads_help));
|
||||
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = UI.Device_path,
|
||||
Name = "device-path"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string devicePath, string ibgLog, string mhddLog,
|
||||
bool useBufferedReads)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -95,7 +71,7 @@ sealed class MediaScanCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -108,12 +84,14 @@ sealed class MediaScanCommand : Command
|
||||
|
||||
Statistics.AddCommand("media-scan");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--device={0}", Markup.Escape(devicePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--ibg-log={0}", Markup.Escape(ibgLog ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--mhdd-log={0}", Markup.Escape(mhddLog ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--use-buffered-reads={0}", useBufferedReads);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--device={0}", Markup.Escape(settings.DevicePath ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--ibg-log={0}", Markup.Escape(settings.IbgLog ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--mhdd-log={0}", Markup.Escape(settings.MhddLog ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--verbose={0}", settings.Verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "--use-buffered-reads={0}", settings.UseBufferedReads);
|
||||
|
||||
string devicePath = settings.DevicePath;
|
||||
|
||||
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
|
||||
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
|
||||
@@ -152,7 +130,7 @@ sealed class MediaScanCommand : Command
|
||||
|
||||
Statistics.AddDevice(dev);
|
||||
|
||||
var scanner = new MediaScan(mhddLog, ibgLog, devicePath, dev, useBufferedReads);
|
||||
var scanner = new MediaScan(settings.MhddLog, settings.IbgLog, devicePath, dev, settings.UseBufferedReads);
|
||||
ScanResults results = new();
|
||||
|
||||
AnsiConsole.Progress()
|
||||
@@ -254,4 +232,27 @@ sealed class MediaScanCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : MediaFamily
|
||||
{
|
||||
[Description("Write a log of the scan in the format used by MHDD.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-m|--mhdd-log")]
|
||||
public string MhddLog { get; init; }
|
||||
[Description("Write a log of the scan in the format used by ImgBurn.")]
|
||||
[DefaultValue(null)]
|
||||
[CommandOption("-b|--ibg-log")]
|
||||
public string IbgLog { get; init; }
|
||||
[Description("For MMC/SD, use OS buffered reads if CMD23 is not supported.")]
|
||||
[DefaultValue(true)]
|
||||
[CommandOption("--use-buffered-reads")]
|
||||
public bool UseBufferedReads { get; init; }
|
||||
[Description("Media device path")]
|
||||
[CommandArgument(0, "<device-path>")]
|
||||
public string DevicePath { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -33,38 +33,25 @@
|
||||
// TODO: Fix errors returned
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.NamingConventionBinder;
|
||||
using System.ComponentModel;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Localization;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using Remote = Aaru.Devices.Remote.Remote;
|
||||
|
||||
namespace Aaru.Commands;
|
||||
|
||||
sealed class RemoteCommand : Command
|
||||
sealed class RemoteCommand : Command<RemoteCommand.Settings>
|
||||
{
|
||||
const string MODULE_NAME = "Remote command";
|
||||
|
||||
public RemoteCommand() : base("remote", UI.Remote_Command_Description)
|
||||
{
|
||||
AddArgument(new Argument<string>
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
Description = "aaru host",
|
||||
Name = "host"
|
||||
});
|
||||
|
||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)) ?? throw new NullReferenceException());
|
||||
}
|
||||
|
||||
public static int Invoke(bool debug, bool verbose, string host)
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
MainClass.PrintCopyright();
|
||||
|
||||
if(debug)
|
||||
if(settings.Debug)
|
||||
{
|
||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
@@ -82,7 +69,7 @@ sealed class RemoteCommand : Command
|
||||
AaruConsole.WriteExceptionEvent += ex => { stderrConsole.WriteException(ex); };
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
if(settings.Verbose)
|
||||
{
|
||||
AaruConsole.WriteEvent += (format, objects) =>
|
||||
{
|
||||
@@ -95,13 +82,13 @@ sealed class RemoteCommand : Command
|
||||
|
||||
Statistics.AddCommand("remote");
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "debug={0}", debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "host={0}", Markup.Escape(host ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "verbose={0}", verbose);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "debug={0}", settings.Debug);
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "host={0}", Markup.Escape(settings.Host ?? ""));
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, "verbose={0}", settings.Verbose);
|
||||
|
||||
try
|
||||
{
|
||||
var remote = new Remote(new Uri(host));
|
||||
var remote = new Remote(new Uri(settings.Host));
|
||||
|
||||
Statistics.AddRemote(remote.ServerApplication,
|
||||
remote.ServerVersion,
|
||||
@@ -138,4 +125,15 @@ sealed class RemoteCommand : Command
|
||||
|
||||
return (int)ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
#region Nested type: Settings
|
||||
|
||||
public class Settings : BaseSettings
|
||||
{
|
||||
[CommandArgument(0, "<host>")]
|
||||
[Description("Aaru host")]
|
||||
public string Host { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
192
Aaru/Main.cs
192
Aaru/Main.cs
@@ -32,7 +32,6 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@@ -54,6 +53,8 @@ using Aaru.Settings;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
using ListOptionsCommand = Aaru.Commands.Filesystem.ListOptionsCommand;
|
||||
|
||||
namespace Aaru;
|
||||
|
||||
@@ -176,7 +177,7 @@ class MainClass
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
var mainDbUpdate = false;
|
||||
bool mainDbUpdate = false;
|
||||
|
||||
if(!File.Exists(Settings.Settings.MainDbPath))
|
||||
{
|
||||
@@ -222,40 +223,179 @@ class MainClass
|
||||
// There are too many places that depend on this being inited to be sure all are covered, so init it here.
|
||||
PluginBase.Init();
|
||||
|
||||
var rootCommand = new RootCommand();
|
||||
var app = new CommandApp();
|
||||
|
||||
rootCommand.AddGlobalOption(new Option<bool>(["--verbose", "-v"], () => false, UI.Shows_verbose_output));
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.UseAssemblyInformationalVersion();
|
||||
|
||||
rootCommand.AddGlobalOption(new Option<bool>(["--debug", "-d"],
|
||||
() => false,
|
||||
UI.Shows_debug_output_from_plugins));
|
||||
config.AddBranch<ArchiveFamily>("archive",
|
||||
archive =>
|
||||
{
|
||||
archive.SetDescription(UI.Archive_Command_Family_Description);
|
||||
|
||||
Option<bool> pauseOption = new(["--pause"], () => false, UI.Pauses_before_exiting);
|
||||
archive.AddCommand<ArchiveListCommand>("list")
|
||||
.WithAlias("l")
|
||||
.WithAlias("ls")
|
||||
.WithDescription(UI.Archive_List_Command_Description);
|
||||
|
||||
rootCommand.AddGlobalOption(pauseOption);
|
||||
archive.AddCommand<ArchiveExtractCommand>("extract")
|
||||
.WithAlias("x")
|
||||
.WithDescription(UI.Archive_Extract_Command_Description);
|
||||
|
||||
rootCommand.Description = $"{_assemblyTitle} {_assemblyVersion?.InformationalVersion}\n{_assemblyCopyright}";
|
||||
archive.AddCommand<ArchiveInfoCommand>("info")
|
||||
.WithAlias("i")
|
||||
.WithDescription(UI.Archive_Info_Command_Description);
|
||||
})
|
||||
.WithAlias("arc");
|
||||
|
||||
rootCommand.AddCommand(new DatabaseFamily(mainDbUpdate));
|
||||
rootCommand.AddCommand(new DeviceFamily());
|
||||
rootCommand.AddCommand(new FilesystemFamily());
|
||||
rootCommand.AddCommand(new ImageFamily());
|
||||
rootCommand.AddCommand(new MediaFamily());
|
||||
rootCommand.AddCommand(new ArchiveFamily());
|
||||
rootCommand.AddCommand(new ConfigureCommand());
|
||||
rootCommand.AddCommand(new FormatsCommand());
|
||||
rootCommand.AddCommand(new ListEncodingsCommand());
|
||||
rootCommand.AddCommand(new ListNamespacesCommand());
|
||||
rootCommand.AddCommand(new RemoteCommand());
|
||||
config.AddBranch<DeviceFamily>("device",
|
||||
device =>
|
||||
{
|
||||
device.SetDescription(UI.Device_Command_Family_Description);
|
||||
|
||||
int ret = await rootCommand.InvokeAsync(args);
|
||||
device.AddCommand<DeviceReportCommand>("report")
|
||||
.WithDescription(UI.Device_Report_Command_Description);
|
||||
|
||||
device.AddCommand<DeviceInfoCommand>("info")
|
||||
.WithAlias("i")
|
||||
.WithDescription(UI.Device_Info_Command_Description);
|
||||
|
||||
device.AddCommand<ListDevicesCommand>("list")
|
||||
.WithAlias("l")
|
||||
.WithAlias("ls")
|
||||
.WithDescription(UI.Device_List_Command_Description);
|
||||
})
|
||||
.WithAlias("dev");
|
||||
|
||||
config.AddBranch<FilesystemFamily>("filesystem",
|
||||
fs =>
|
||||
{
|
||||
fs.SetDescription(UI.Filesystem_Command_Family_Description);
|
||||
|
||||
fs.AddCommand<ExtractFilesCommand>("extract")
|
||||
.WithAlias("x")
|
||||
.WithDescription(UI.Filesystem_Extract_Command_Description);
|
||||
|
||||
fs.AddCommand<FilesystemInfoCommand>("info")
|
||||
.WithAlias("i")
|
||||
.WithDescription(UI.Filesystem_Info_Command_Description);
|
||||
|
||||
fs.AddCommand<LsCommand>("list")
|
||||
.WithAlias("ls")
|
||||
.WithDescription(UI.Filesystem_List_Command_Description);
|
||||
|
||||
fs.AddCommand<ListOptionsCommand>("options")
|
||||
.WithDescription(UI.Filesystem_Options_Command_Description);
|
||||
})
|
||||
.WithAlias("fs")
|
||||
.WithAlias("fi");
|
||||
|
||||
config.AddBranch<ImageFamily>("image",
|
||||
image =>
|
||||
{
|
||||
image.SetDescription(UI.Image_Command_Family_Description);
|
||||
|
||||
image.AddCommand<ChecksumCommand>("checksum")
|
||||
.WithAlias("chk")
|
||||
.WithDescription(UI.Image_Checksum_Command_Description);
|
||||
|
||||
image.AddCommand<CompareCommand>("compate")
|
||||
.WithAlias("cmp")
|
||||
.WithDescription(UI.Image_Compare_Command_Description);
|
||||
|
||||
image.AddCommand<ConvertImageCommand>("convert")
|
||||
.WithAlias("cvt")
|
||||
.WithDescription(UI.Image_Convert_Command_Description);
|
||||
|
||||
image.AddCommand<CreateSidecarCommand>("create-sidecar")
|
||||
.WithAlias("cs")
|
||||
.WithDescription(UI.Image_Create_Sidecar_Command_Description);
|
||||
|
||||
image.AddCommand<DecodeCommand>("decode")
|
||||
.WithDescription(UI.Image_Decode_Command_Description);
|
||||
|
||||
image.AddCommand<EntropyCommand>("entropy")
|
||||
.WithDescription(UI.Image_Entropy_Command_Description);
|
||||
|
||||
image.AddCommand<ImageInfoCommand>("info")
|
||||
.WithAlias("i")
|
||||
.WithDescription(UI.Image_Info_Command_Description);
|
||||
|
||||
image.AddCommand<Commands.Image.ListOptionsCommand>("options")
|
||||
.WithDescription(UI.Image_Options_Command_Description);
|
||||
|
||||
image.AddCommand<PrintHexCommand>("print-hex")
|
||||
.WithAlias("ph")
|
||||
.WithDescription(UI.Image_Print_Command_Description);
|
||||
|
||||
image.AddCommand<VerifyCommand>("verify")
|
||||
.WithAlias("v")
|
||||
.WithDescription(UI.Image_Verify_Command_Description);
|
||||
})
|
||||
.WithAlias("i")
|
||||
.WithAlias("img");
|
||||
|
||||
config.AddBranch<MediaFamily>("media",
|
||||
media =>
|
||||
{
|
||||
media.SetDescription(UI.Media_Command_Family_Description);
|
||||
|
||||
media.AddCommand<MediaInfoCommand>("info")
|
||||
.WithAlias("i")
|
||||
.WithDescription(UI.Media_Info_Command_Description);
|
||||
|
||||
media.AddCommand<MediaScanCommand>("scan")
|
||||
.WithAlias("s")
|
||||
.WithDescription(UI.Media_Scan_Command_Description);
|
||||
|
||||
media.AddCommand<DumpMediaCommand>("dump")
|
||||
.WithAlias("d")
|
||||
.WithDescription(UI.Media_Dump_Command_Description);
|
||||
})
|
||||
.WithAlias("m");
|
||||
|
||||
config.AddBranch<DatabaseFamily>("database",
|
||||
db =>
|
||||
{
|
||||
db.SetDescription(UI.Database_Command_Family_Description);
|
||||
|
||||
db.AddCommand<StatisticsCommand>("stats")
|
||||
.WithDescription(UI.Database_Stats_Command_Description);
|
||||
|
||||
db.AddCommand<UpdateCommand>("update")
|
||||
.WithDescription(UI.Database_Update_Command_Description);
|
||||
})
|
||||
.WithAlias("db");
|
||||
|
||||
config.AddCommand<ConfigureCommand>("configure")
|
||||
.WithAlias("cfg")
|
||||
.WithDescription(UI.Configure_Command_Description);
|
||||
|
||||
config.AddCommand<FormatsCommand>("formats")
|
||||
.WithAlias("fmt")
|
||||
.WithDescription(UI.List_Formats_Command_Description);
|
||||
|
||||
config.AddCommand<ListEncodingsCommand>("list-encodings")
|
||||
.WithAlias("le")
|
||||
.WithDescription(UI.List_Encodings_Command_Description);
|
||||
|
||||
config.AddCommand<ListNamespacesCommand>("list-namespaces")
|
||||
.WithAlias("ln")
|
||||
.WithDescription(UI.List_Namespaces_Command_Description);
|
||||
|
||||
config.AddCommand<RemoteCommand>("remote").WithAlias("rem").WithDescription(UI.Remote_Command_Description);
|
||||
});
|
||||
|
||||
PrintCopyright();
|
||||
|
||||
int ret = await app.RunAsync(args);
|
||||
|
||||
await Statistics.SaveStatsAsync();
|
||||
|
||||
if(!rootCommand.Parse(args).RootCommandResult.GetValueForOption(pauseOption)) return ret;
|
||||
|
||||
AaruConsole.WriteLine(UI.Press_any_key_to_exit);
|
||||
System.Console.ReadKey();
|
||||
// TODO: Return pause functionality
|
||||
// AaruConsole.WriteLine(UI.Press_any_key_to_exit);
|
||||
// System.Console.ReadKey();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,70 +1,69 @@
|
||||
<Project ToolsVersion="15.0">
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Aaru.Checksums.Native" Version="6.0.0-alpha9"/>
|
||||
<PackageVersion Include="Aaru.Compression.Native" Version="6.0.0-alpha.10"/>
|
||||
<PackageVersion Include="AsyncFixer" Version="1.6.0"/>
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.3"/>
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.3"/>
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.3"/>
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.3"/>
|
||||
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.3"/>
|
||||
<PackageVersion Include="Avalonia" Version="11.3.3"/>
|
||||
<PackageVersion Include="Claunia.Encoding" Version="1.9.2"/>
|
||||
<PackageVersion Include="Claunia.RsrcFork" Version="1.2.0"/>
|
||||
<PackageVersion Include="DotNetZip" Version="1.16.0"/>
|
||||
<PackageVersion Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2"/>
|
||||
<PackageVersion Include="ErrorProne.NET.Structs" Version="0.1.2"/>
|
||||
<PackageVersion Include="FluentAssertions.Analyzers" Version="0.34.1"/>
|
||||
<PackageVersion Include="FluentAssertions" Version="8.6.0"/>
|
||||
<PackageVersion Include="Humanizer.Core" Version="2.14.1"/>
|
||||
<PackageVersion Include="Humanizer" Version="2.14.1"/>
|
||||
<PackageVersion Include="JetBrains.Annotations" Version="2025.2.0"/>
|
||||
<PackageVersion Include="Macross.Json.Extensions" Version="3.0.0"/>
|
||||
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0"/>
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4"/>
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0"/>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
|
||||
<PackageVersion Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15"/>
|
||||
<PackageVersion Include="Microsoft.Win32.Registry" Version="6.0.0-preview.5.21301.5"/>
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3"/>
|
||||
<PackageVersion Include="NUnit.Analyzers" Version="4.10.0"/>
|
||||
<PackageVersion Include="nunit" Version="4.4.0"/>
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="5.1.0"/>
|
||||
<PackageVersion Include="Philips.CodeAnalysis.MaintainabilityAnalyzers" Version="1.8.0"/>
|
||||
<PackageVersion Include="plist-cil" Version="2.3.1"/>
|
||||
<PackageVersion Include="Roslynator.Analyzers" Version="4.14.0"/>
|
||||
<PackageVersion Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.0"/>
|
||||
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="4.14.0"/>
|
||||
<PackageVersion Include="SharpCompress" Version="0.40.0"/>
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.8"/>
|
||||
<PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31"/>
|
||||
<PackageVersion Include="Spectre.Console.Analyzer" Version="1.0.0"/>
|
||||
<PackageVersion Include="Spectre.Console" Version="0.50.0"/>
|
||||
<PackageVersion Include="System.Collections" Version="4.3.0"/>
|
||||
<PackageVersion Include="System.CommandLine.NamingConventionBinder" Version="2.0.0-beta4.22272.1"/>
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1"/>
|
||||
<PackageVersion Include="System.ComponentModel.Annotations" Version="6.0.0-preview.4.21253.7"/>
|
||||
<PackageVersion Include="System.Diagnostics.Debug" Version="4.3.0"/>
|
||||
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0"/>
|
||||
<PackageVersion Include="System.IO.FileSystem" Version="4.3.0"/>
|
||||
<PackageVersion Include="System.Management" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="System.Memory" Version="4.6.3"/>
|
||||
<PackageVersion Include="System.Net.Primitives" Version="4.3.1"/>
|
||||
<PackageVersion Include="System.Resources.Extensions" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="System.Runtime.Extensions" Version="4.3.1"/>
|
||||
<PackageVersion Include="System.Runtime.Handles" Version="4.3.0"/>
|
||||
<PackageVersion Include="System.Runtime.InteropServices" Version="4.3.0"/>
|
||||
<PackageVersion Include="System.Security.Principal.Windows" Version="6.0.0-preview.5.21301.5"/>
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.0-preview.7.25380.108"/>
|
||||
<PackageVersion Include="System.ValueTuple" Version="4.6.1"/>
|
||||
<PackageVersion Include="Text.Analyzers" Version="4.14.0"/>
|
||||
<PackageVersion Include="Unclassified.NetRevisionTask" Version="0.4.4"/>
|
||||
<PackageVersion Update="Packaging.Targets" Version="0.1.226"/>
|
||||
<PackageVersion Include="Aaru.Checksums.Native" Version="6.0.0-alpha9" />
|
||||
<PackageVersion Include="Aaru.Compression.Native" Version="6.0.0-alpha.10" />
|
||||
<PackageVersion Include="AsyncFixer" Version="1.6.0" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.3" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.3" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.3" />
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.3" />
|
||||
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.3" />
|
||||
<PackageVersion Include="Avalonia" Version="11.3.3" />
|
||||
<PackageVersion Include="Claunia.Encoding" Version="1.9.2" />
|
||||
<PackageVersion Include="Claunia.RsrcFork" Version="1.2.0" />
|
||||
<PackageVersion Include="DotNetZip" Version="1.16.0" />
|
||||
<PackageVersion Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2" />
|
||||
<PackageVersion Include="ErrorProne.NET.Structs" Version="0.1.2" />
|
||||
<PackageVersion Include="FluentAssertions.Analyzers" Version="0.34.1" />
|
||||
<PackageVersion Include="FluentAssertions" Version="8.6.0" />
|
||||
<PackageVersion Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
||||
<PackageVersion Include="JetBrains.Annotations" Version="2025.2.0" />
|
||||
<PackageVersion Include="Macross.Json.Extensions" Version="3.0.0" />
|
||||
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageVersion Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" />
|
||||
<PackageVersion Include="Microsoft.Win32.Registry" Version="6.0.0-preview.5.21301.5" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageVersion Include="NUnit.Analyzers" Version="4.10.0" />
|
||||
<PackageVersion Include="nunit" Version="4.4.0" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="5.1.0" />
|
||||
<PackageVersion Include="Philips.CodeAnalysis.MaintainabilityAnalyzers" Version="1.8.0" />
|
||||
<PackageVersion Include="plist-cil" Version="2.3.1" />
|
||||
<PackageVersion Include="Roslynator.Analyzers" Version="4.14.0" />
|
||||
<PackageVersion Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.0" />
|
||||
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="4.14.0" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.40.0" />
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.8" />
|
||||
<PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" />
|
||||
<PackageVersion Include="Spectre.Console.Analyzer" Version="1.0.0" />
|
||||
<PackageVersion Include="Spectre.Console" Version="0.50.0" />
|
||||
<PackageVersion Include="Spectre.Console.Cli" Version="0.50.0" />
|
||||
<PackageVersion Include="System.Collections" Version="4.3.0" />
|
||||
<PackageVersion Include="System.ComponentModel.Annotations" Version="6.0.0-preview.4.21253.7" />
|
||||
<PackageVersion Include="System.Diagnostics.Debug" Version="4.3.0" />
|
||||
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||
<PackageVersion Include="System.IO.FileSystem" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Management" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="System.Memory" Version="4.6.3" />
|
||||
<PackageVersion Include="System.Net.Primitives" Version="4.3.1" />
|
||||
<PackageVersion Include="System.Resources.Extensions" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="System.Runtime.Extensions" Version="4.3.1" />
|
||||
<PackageVersion Include="System.Runtime.Handles" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Runtime.InteropServices" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Security.Principal.Windows" Version="6.0.0-preview.5.21301.5" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.0-preview.7.25380.108" />
|
||||
<PackageVersion Include="System.ValueTuple" Version="4.6.1" />
|
||||
<PackageVersion Include="Text.Analyzers" Version="4.14.0" />
|
||||
<PackageVersion Include="Unclassified.NetRevisionTask" Version="0.4.4" />
|
||||
<PackageVersion Update="Packaging.Targets" Version="0.1.226" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user