mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Add support for byte addressable images to detection.
This commit is contained in:
@@ -636,7 +636,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
UpdateStatus?.Invoke("Creating sidecar.");
|
UpdateStatus?.Invoke("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(_outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter) as IMediaImage;
|
||||||
ErrorNumber opened = inputPlugin.Open(filter);
|
ErrorNumber opened = inputPlugin.Open(filter);
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
if(opened != ErrorNumber.NoError)
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
_dumpLog.WriteLine("Creating sidecar.");
|
_dumpLog.WriteLine("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(_outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter) as IMediaImage;
|
||||||
totalChkDuration = 0;
|
totalChkDuration = 0;
|
||||||
ErrorNumber opened = inputPlugin.Open(filter);
|
ErrorNumber opened = inputPlugin.Open(filter);
|
||||||
|
|
||||||
|
|||||||
@@ -693,7 +693,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
_dumpLog.WriteLine("Creating sidecar.");
|
_dumpLog.WriteLine("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(_outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter) as IMediaImage;
|
||||||
ErrorNumber opened = inputPlugin.Open(filter);
|
ErrorNumber opened = inputPlugin.Open(filter);
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
if(opened != ErrorNumber.NoError)
|
||||||
|
|||||||
@@ -561,7 +561,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
_dumpLog.WriteLine("Creating sidecar.");
|
_dumpLog.WriteLine("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(_outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter) as IMediaImage;
|
||||||
ErrorNumber opened = inputPlugin.Open(filter);
|
ErrorNumber opened = inputPlugin.Open(filter);
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
if(opened != ErrorNumber.NoError)
|
||||||
|
|||||||
@@ -1314,7 +1314,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
_dumpLog.WriteLine("Creating sidecar.");
|
_dumpLog.WriteLine("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(_outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter) as IMediaImage;
|
||||||
ErrorNumber opened = inputPlugin.Open(filter);
|
ErrorNumber opened = inputPlugin.Open(filter);
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
if(opened != ErrorNumber.NoError)
|
||||||
|
|||||||
@@ -985,7 +985,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
_dumpLog.WriteLine("Creating sidecar.");
|
_dumpLog.WriteLine("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(_outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter) as IMediaImage;
|
||||||
ErrorNumber opened = inputPlugin.Open(filter);
|
ErrorNumber opened = inputPlugin.Open(filter);
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
if(opened != ErrorNumber.NoError)
|
||||||
|
|||||||
@@ -782,7 +782,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
_dumpLog.WriteLine("Creating sidecar.");
|
_dumpLog.WriteLine("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(_outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter) as IMediaImage;
|
||||||
ErrorNumber opened = inputPlugin.Open(filter);
|
ErrorNumber opened = inputPlugin.Open(filter);
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
if(opened != ErrorNumber.NoError)
|
||||||
|
|||||||
@@ -36,72 +36,94 @@ using Aaru.CommonTypes;
|
|||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Interfaces;
|
||||||
using Aaru.Console;
|
using Aaru.Console;
|
||||||
|
|
||||||
namespace Aaru.Core
|
namespace Aaru.Core;
|
||||||
|
|
||||||
|
/// <summary>Core media image format operations</summary>
|
||||||
|
public static class ImageFormat
|
||||||
{
|
{
|
||||||
/// <summary>Core media image format operations</summary>
|
/// <summary>Detects the image plugin that recognizes the data inside a filter</summary>
|
||||||
public static class ImageFormat
|
/// <param name="imageFilter">Filter</param>
|
||||||
|
/// <returns>Detected image plugin</returns>
|
||||||
|
public static IBaseImage Detect(IFilter imageFilter)
|
||||||
{
|
{
|
||||||
/// <summary>Detects the image plugin that recognizes the data inside a filter</summary>
|
try
|
||||||
/// <param name="imageFilter">Filter</param>
|
|
||||||
/// <returns>Detected image plugin</returns>
|
|
||||||
public static IMediaImage Detect(IFilter imageFilter)
|
|
||||||
{
|
{
|
||||||
try
|
PluginBase plugins = GetPluginBase.Instance;
|
||||||
{
|
|
||||||
PluginBase plugins = GetPluginBase.Instance;
|
|
||||||
|
|
||||||
IMediaImage imageFormat = null;
|
IBaseImage imageFormat = null;
|
||||||
|
|
||||||
// Check all but RAW plugin
|
// Check all but RAW plugin
|
||||||
foreach(IMediaImage imagePlugin in plugins.ImagePluginsList.Values.Where(imagePlugin =>
|
foreach(IMediaImage imagePlugin in plugins.ImagePluginsList.Values.Where(imagePlugin =>
|
||||||
imagePlugin.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000")))
|
imagePlugin.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000")))
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AaruConsole.DebugWriteLine("Format detection", "Trying plugin {0}", imagePlugin.Name);
|
AaruConsole.DebugWriteLine("Format detection", "Trying plugin {0}", imagePlugin.Name);
|
||||||
|
|
||||||
if(!imagePlugin.Identify(imageFilter))
|
if(!imagePlugin.Identify(imageFilter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
imageFormat = imagePlugin;
|
imageFormat = imagePlugin;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
if(imageFormat != null)
|
if(imageFormat != null)
|
||||||
return imageFormat;
|
|
||||||
|
|
||||||
// Check only RAW plugin
|
|
||||||
foreach(IMediaImage imagePlugin in plugins.ImagePluginsList.Values.Where(imagePlugin =>
|
|
||||||
imagePlugin.Id == new Guid("12345678-AAAA-BBBB-CCCC-123456789000")))
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AaruConsole.DebugWriteLine("Format detection", "Trying plugin {0}", imagePlugin.Name);
|
|
||||||
|
|
||||||
if(!imagePlugin.Identify(imageFilter))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
imageFormat = imagePlugin;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
// Still not recognized
|
|
||||||
return imageFormat;
|
return imageFormat;
|
||||||
}
|
|
||||||
catch
|
// Check all but RAW plugin
|
||||||
{
|
foreach(IByteAddressableImage imagePlugin in plugins.ByteAddressableImages.Values.Where(imagePlugin =>
|
||||||
return null;
|
imagePlugin.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000")))
|
||||||
}
|
try
|
||||||
|
{
|
||||||
|
AaruConsole.DebugWriteLine("Format detection", "Trying plugin {0}", imagePlugin.Name);
|
||||||
|
|
||||||
|
if(!imagePlugin.Identify(imageFilter))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
imageFormat = imagePlugin;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
if(imageFormat != null)
|
||||||
|
return imageFormat;
|
||||||
|
|
||||||
|
// Check only RAW plugin
|
||||||
|
foreach(IMediaImage imagePlugin in plugins.ImagePluginsList.Values.Where(imagePlugin =>
|
||||||
|
imagePlugin.Id == new Guid("12345678-AAAA-BBBB-CCCC-123456789000")))
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AaruConsole.DebugWriteLine("Format detection", "Trying plugin {0}", imagePlugin.Name);
|
||||||
|
|
||||||
|
if(!imagePlugin.Identify(imageFilter))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
imageFormat = imagePlugin;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
// Still not recognized
|
||||||
|
return imageFormat;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,7 +523,7 @@ namespace Aaru.Gui.ViewModels.Windows
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IMediaImage imageFormat = ImageFormat.Detect(inputFilter);
|
IMediaImage imageFormat = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
if(imageFormat == null)
|
if(imageFormat == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace Aaru.Tests.Filesystems
|
|||||||
|
|
||||||
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
||||||
|
|
||||||
IMediaImage image = ImageFormat.Detect(inputFilter);
|
IMediaImage image = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.IsNotNull(image, $"Image format: {testFile}");
|
Assert.IsNotNull(image, $"Image format: {testFile}");
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ namespace Aaru.Tests.Filesystems
|
|||||||
|
|
||||||
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
||||||
|
|
||||||
IMediaImage image = ImageFormat.Detect(inputFilter);
|
IMediaImage image = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.IsNotNull(image, $"Image format: {testFile}");
|
Assert.IsNotNull(image, $"Image format: {testFile}");
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ namespace Aaru.Tests.Filesystems
|
|||||||
|
|
||||||
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
||||||
|
|
||||||
IMediaImage image = ImageFormat.Detect(inputFilter);
|
IMediaImage image = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.IsNotNull(image, $"Image format: {testFile}");
|
Assert.IsNotNull(image, $"Image format: {testFile}");
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Aaru.Tests.Filesystems
|
|||||||
|
|
||||||
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
||||||
|
|
||||||
IMediaImage image = ImageFormat.Detect(inputFilter);
|
IMediaImage image = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.IsNotNull(image, $"Image format: {testFile}");
|
Assert.IsNotNull(image, $"Image format: {testFile}");
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ namespace Aaru.Tests.Filesystems
|
|||||||
|
|
||||||
var filtersList = new FiltersList();
|
var filtersList = new FiltersList();
|
||||||
IFilter inputFilter = filtersList.GetFilter(testFile);
|
IFilter inputFilter = filtersList.GetFilter(testFile);
|
||||||
IMediaImage image = ImageFormat.Detect(inputFilter);
|
IMediaImage image = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
ErrorNumber opened = image.Open(inputFilter);
|
ErrorNumber opened = image.Open(inputFilter);
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
if(opened != ErrorNumber.NoError)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Aaru.Tests.Issues
|
|||||||
|
|
||||||
PluginBase plugins = GetPluginBase.Instance;
|
PluginBase plugins = GetPluginBase.Instance;
|
||||||
|
|
||||||
IMediaImage imageFormat = ImageFormat.Detect(inputFilter);
|
IMediaImage imageFormat = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.NotNull(imageFormat, "Image format not identified, not proceeding with analysis.");
|
Assert.NotNull(imageFormat, "Image format not identified, not proceeding with analysis.");
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace Aaru.Tests.Issues
|
|||||||
|
|
||||||
PluginBase plugins = GetPluginBase.Instance;
|
PluginBase plugins = GetPluginBase.Instance;
|
||||||
|
|
||||||
IMediaImage imageFormat = ImageFormat.Detect(inputFilter);
|
IMediaImage imageFormat = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.NotNull(imageFormat, "Image format not identified, not proceeding with analysis.");
|
Assert.NotNull(imageFormat, "Image format not identified, not proceeding with analysis.");
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Aaru.Tests.Issues
|
|||||||
|
|
||||||
Assert.IsNotNull(inputFilter, "Filter for test file is not detected");
|
Assert.IsNotNull(inputFilter, "Filter for test file is not detected");
|
||||||
|
|
||||||
IMediaImage image = ImageFormat.Detect(inputFilter);
|
IMediaImage image = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.IsNotNull(image, "Image format for test file is not detected");
|
Assert.IsNotNull(image, "Image format for test file is not detected");
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace Aaru.Tests.Issues
|
|||||||
|
|
||||||
Assert.IsFalse(File.Exists(outputPath), "Output file already exists, not continuing.");
|
Assert.IsFalse(File.Exists(outputPath), "Output file already exists, not continuing.");
|
||||||
|
|
||||||
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
|
IMediaImage inputFormat = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.IsNotNull(inputFormat, "Input image format not identified, not proceeding with conversion.");
|
Assert.IsNotNull(inputFormat, "Input image format not identified, not proceeding with conversion.");
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace Aaru.Tests.Issues
|
|||||||
|
|
||||||
Assert.IsNotNull(inputFilter, "Filter for test file is not detected");
|
Assert.IsNotNull(inputFilter, "Filter for test file is not detected");
|
||||||
|
|
||||||
IMediaImage image = ImageFormat.Detect(inputFilter);
|
IMediaImage image = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.IsNotNull(image, "Image format for test file is not detected");
|
Assert.IsNotNull(image, "Image format for test file is not detected");
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace Aaru.Tests.Partitions
|
|||||||
|
|
||||||
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
Assert.IsNotNull(inputFilter, $"Filter: {testFile}");
|
||||||
|
|
||||||
IMediaImage image = ImageFormat.Detect(inputFilter);
|
IMediaImage image = ImageFormat.Detect(inputFilter) as IMediaImage;
|
||||||
|
|
||||||
Assert.IsNotNull(image, $"Image format: {testFile}");
|
Assert.IsNotNull(image, $"Image format: {testFile}");
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -42,339 +42,345 @@ using Aaru.Console;
|
|||||||
using Aaru.Core;
|
using Aaru.Core;
|
||||||
using Spectre.Console;
|
using Spectre.Console;
|
||||||
|
|
||||||
namespace Aaru.Commands.Filesystem
|
namespace Aaru.Commands.Filesystem;
|
||||||
|
|
||||||
|
internal sealed class FilesystemInfoCommand : Command
|
||||||
{
|
{
|
||||||
internal sealed class FilesystemInfoCommand : Command
|
public FilesystemInfoCommand() : base("info",
|
||||||
|
"Opens a disc image and prints info on the found partitions and/or filesystems.")
|
||||||
{
|
{
|
||||||
public FilesystemInfoCommand() : base("info",
|
Add(new Option(new[]
|
||||||
"Opens a disc image and prints info on the found partitions and/or filesystems.")
|
|
||||||
{
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--encoding", "-e"
|
|
||||||
}, "Name of character encoding to use.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<string>(() => null),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--filesystems", "-f"
|
|
||||||
}, "Searches and prints information about filesystems.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<bool>(() => true),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--partitions", "-p"
|
|
||||||
}, "Searches and interprets partitions.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<bool>(() => true),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
AddArgument(new Argument<string>
|
|
||||||
{
|
{
|
||||||
Arity = ArgumentArity.ExactlyOne,
|
"--encoding", "-e"
|
||||||
Description = "Media image path",
|
}, "Name of character encoding to use.")
|
||||||
Name = "image-path"
|
{
|
||||||
|
Argument = new Argument<string>(() => null),
|
||||||
|
Required = false
|
||||||
});
|
});
|
||||||
|
|
||||||
Handler = CommandHandler.Create(typeof(FilesystemInfoCommand).GetMethod(nameof(Invoke)));
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--filesystems", "-f"
|
||||||
|
}, "Searches and prints information about filesystems.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<bool>(() => true),
|
||||||
|
Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--partitions", "-p"
|
||||||
|
}, "Searches and interprets partitions.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<bool>(() => true),
|
||||||
|
Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
AddArgument(new Argument<string>
|
||||||
|
{
|
||||||
|
Arity = ArgumentArity.ExactlyOne,
|
||||||
|
Description = "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)
|
||||||
|
{
|
||||||
|
MainClass.PrintCopyright();
|
||||||
|
|
||||||
|
if(debug)
|
||||||
|
{
|
||||||
|
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||||
|
{
|
||||||
|
Out = new AnsiConsoleOutput(System.Console.Error)
|
||||||
|
});
|
||||||
|
|
||||||
|
AaruConsole.DebugWriteLineEvent += (format, objects) =>
|
||||||
|
{
|
||||||
|
if(objects is null)
|
||||||
|
stderrConsole.MarkupLine(format);
|
||||||
|
else
|
||||||
|
stderrConsole.MarkupLine(format, objects);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Invoke(bool verbose, bool debug, string encoding, bool filesystems, bool partitions,
|
if(verbose)
|
||||||
string imagePath)
|
AaruConsole.WriteEvent += (format, objects) =>
|
||||||
{
|
|
||||||
MainClass.PrintCopyright();
|
|
||||||
|
|
||||||
if(debug)
|
|
||||||
{
|
{
|
||||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
if(objects is null)
|
||||||
{
|
AnsiConsole.Markup(format);
|
||||||
Out = new AnsiConsoleOutput(System.Console.Error)
|
else
|
||||||
});
|
AnsiConsole.Markup(format, objects);
|
||||||
|
};
|
||||||
|
|
||||||
AaruConsole.DebugWriteLineEvent += (format, objects) =>
|
Statistics.AddCommand("fs-info");
|
||||||
{
|
|
||||||
if(objects is null)
|
AaruConsole.DebugWriteLine("Fs-info command", "--debug={0}", debug);
|
||||||
stderrConsole.MarkupLine(format);
|
AaruConsole.DebugWriteLine("Fs-info command", "--encoding={0}", encoding);
|
||||||
else
|
AaruConsole.DebugWriteLine("Fs-info command", "--filesystems={0}", filesystems);
|
||||||
stderrConsole.MarkupLine(format, objects);
|
AaruConsole.DebugWriteLine("Fs-info command", "--input={0}", imagePath);
|
||||||
};
|
AaruConsole.DebugWriteLine("Fs-info command", "--partitions={0}", partitions);
|
||||||
|
AaruConsole.DebugWriteLine("Fs-info command", "--verbose={0}", verbose);
|
||||||
|
|
||||||
|
var filtersList = new FiltersList();
|
||||||
|
IFilter inputFilter = null;
|
||||||
|
|
||||||
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddTask("Identifying file filter...").IsIndeterminate();
|
||||||
|
inputFilter = filtersList.GetFilter(imagePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(inputFilter == null)
|
||||||
|
{
|
||||||
|
AaruConsole.ErrorWriteLine("Cannot open specified file.");
|
||||||
|
|
||||||
|
return (int)ErrorNumber.CannotOpenFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
Encoding encodingClass = null;
|
||||||
|
|
||||||
|
if(encoding != null)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||||
|
|
||||||
|
if(verbose)
|
||||||
|
AaruConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
|
||||||
|
}
|
||||||
|
catch(ArgumentException)
|
||||||
|
{
|
||||||
|
AaruConsole.ErrorWriteLine("Specified encoding is not supported.");
|
||||||
|
|
||||||
|
return (int)ErrorNumber.EncodingUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose)
|
PluginBase plugins = GetPluginBase.Instance;
|
||||||
AaruConsole.WriteEvent += (format, objects) =>
|
|
||||||
{
|
|
||||||
if(objects is null)
|
|
||||||
AnsiConsole.Markup(format);
|
|
||||||
else
|
|
||||||
AnsiConsole.Markup(format, objects);
|
|
||||||
};
|
|
||||||
|
|
||||||
Statistics.AddCommand("fs-info");
|
bool checkRaw = false;
|
||||||
|
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", "--debug={0}", debug);
|
try
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", "--encoding={0}", encoding);
|
{
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", "--filesystems={0}", filesystems);
|
IMediaImage imageFormat = null;
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", "--input={0}", imagePath);
|
IBaseImage baseImage = null;
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", "--partitions={0}", partitions);
|
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", "--verbose={0}", verbose);
|
|
||||||
|
|
||||||
var filtersList = new FiltersList();
|
|
||||||
IFilter inputFilter = null;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
{
|
{
|
||||||
ctx.AddTask("Identifying file filter...").IsIndeterminate();
|
ctx.AddTask("Identifying image format...").IsIndeterminate();
|
||||||
inputFilter = filtersList.GetFilter(imagePath);
|
baseImage = ImageFormat.Detect(inputFilter);
|
||||||
|
imageFormat = baseImage as IMediaImage;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(inputFilter == null)
|
if(baseImage == null)
|
||||||
{
|
{
|
||||||
AaruConsole.ErrorWriteLine("Cannot open specified file.");
|
AaruConsole.WriteLine("Image format not identified, not proceeding with analysis.");
|
||||||
|
|
||||||
return (int)ErrorNumber.CannotOpenFile;
|
return (int)ErrorNumber.UnrecognizedFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
Encoding encodingClass = null;
|
if(imageFormat == null)
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("Command not supported for this image type.");
|
||||||
|
|
||||||
if(encoding != null)
|
return (int)ErrorNumber.InvalidArgument;
|
||||||
try
|
}
|
||||||
{
|
|
||||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
|
||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
AaruConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
|
AaruConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id);
|
||||||
}
|
else
|
||||||
catch(ArgumentException)
|
AaruConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
|
||||||
{
|
|
||||||
AaruConsole.ErrorWriteLine("Specified encoding is not supported.");
|
|
||||||
|
|
||||||
return (int)ErrorNumber.EncodingUnknown;
|
AaruConsole.WriteLine();
|
||||||
}
|
|
||||||
|
|
||||||
PluginBase plugins = GetPluginBase.Instance;
|
|
||||||
|
|
||||||
bool checkRaw = false;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IMediaImage imageFormat = null;
|
ErrorNumber opened = ErrorNumber.NoData;
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
{
|
{
|
||||||
ctx.AddTask("Identifying image format...").IsIndeterminate();
|
ctx.AddTask("Opening image file...").IsIndeterminate();
|
||||||
imageFormat = ImageFormat.Detect(inputFilter);
|
opened = imageFormat.Open(inputFilter);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(imageFormat == null)
|
if(opened != ErrorNumber.NoError)
|
||||||
{
|
{
|
||||||
AaruConsole.WriteLine("Image format not identified, not proceeding with analysis.");
|
AaruConsole.WriteLine("Unable to open image format");
|
||||||
|
AaruConsole.WriteLine("Error {0}", opened);
|
||||||
|
|
||||||
return (int)ErrorNumber.UnrecognizedFormat;
|
return (int)opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
AaruConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
|
{
|
||||||
imageFormat.Id);
|
ImageInfo.PrintImageInfo(imageFormat);
|
||||||
|
AaruConsole.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
Statistics.AddMediaFormat(imageFormat.Format);
|
||||||
|
Statistics.AddMedia(imageFormat.Info.MediaType, false);
|
||||||
|
Statistics.AddFilter(inputFilter.Name);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
AaruConsole.ErrorWriteLine("Unable to open image format");
|
||||||
|
AaruConsole.ErrorWriteLine("Error: {0}", ex.Message);
|
||||||
|
AaruConsole.DebugWriteLine("Fs-info command", "Stack trace: {0}", ex.StackTrace);
|
||||||
|
|
||||||
|
return (int)ErrorNumber.CannotOpenFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> idPlugins = null;
|
||||||
|
IFilesystem plugin;
|
||||||
|
string information;
|
||||||
|
|
||||||
|
if(partitions)
|
||||||
|
{
|
||||||
|
List<Partition> partitionsList = null;
|
||||||
|
|
||||||
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddTask("Enumerating partitions...").IsIndeterminate();
|
||||||
|
partitionsList = Core.Partitions.GetAll(imageFormat);
|
||||||
|
});
|
||||||
|
|
||||||
|
Core.Partitions.AddSchemesToStats(partitionsList);
|
||||||
|
|
||||||
|
if(partitionsList.Count == 0)
|
||||||
|
{
|
||||||
|
AaruConsole.DebugWriteLine("Fs-info command", "No partitions found");
|
||||||
|
|
||||||
|
if(!filesystems)
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("No partitions founds, not searching for filesystems");
|
||||||
|
|
||||||
|
return (int)ErrorNumber.NothingFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkRaw = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
AaruConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
|
|
||||||
|
|
||||||
AaruConsole.WriteLine();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
ErrorNumber opened = ErrorNumber.NoData;
|
AaruConsole.WriteLine("{0} partitions found.", partitionsList.Count);
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
for(int i = 0; i < partitionsList.Count; i++)
|
||||||
{
|
{
|
||||||
ctx.AddTask("Opening image file...").IsIndeterminate();
|
Table table = new();
|
||||||
opened = imageFormat.Open(inputFilter);
|
table.Title = new TableTitle($"Partition {partitionsList[i].Sequence}:");
|
||||||
});
|
table.AddColumn("");
|
||||||
|
table.AddColumn("");
|
||||||
|
table.HideHeaders();
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
table.AddRow("Name", Markup.Escape(partitionsList[i].Name ?? ""));
|
||||||
{
|
table.AddRow("Type", Markup.Escape(partitionsList[i].Type ?? ""));
|
||||||
AaruConsole.WriteLine("Unable to open image format");
|
table.AddRow("Start", $"sector {partitionsList[i].Start}, byte {partitionsList[i].Offset}");
|
||||||
AaruConsole.WriteLine("Error {0}", opened);
|
|
||||||
|
|
||||||
return (int)opened;
|
table.AddRow("Length", $"{partitionsList[i].Length} sectors, {partitionsList[i].Size} bytes");
|
||||||
}
|
|
||||||
|
|
||||||
if(verbose)
|
table.AddRow("Scheme", Markup.Escape(partitionsList[i].Scheme ?? ""));
|
||||||
{
|
table.AddRow("Description", Markup.Escape(partitionsList[i].Description ?? ""));
|
||||||
ImageInfo.PrintImageInfo(imageFormat);
|
|
||||||
AaruConsole.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
Statistics.AddMediaFormat(imageFormat.Format);
|
AnsiConsole.Render(table);
|
||||||
Statistics.AddMedia(imageFormat.Info.MediaType, false);
|
|
||||||
Statistics.AddFilter(inputFilter.Name);
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
AaruConsole.ErrorWriteLine("Unable to open image format");
|
|
||||||
AaruConsole.ErrorWriteLine("Error: {0}", ex.Message);
|
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", "Stack trace: {0}", ex.StackTrace);
|
|
||||||
|
|
||||||
return (int)ErrorNumber.CannotOpenFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<string> idPlugins = null;
|
|
||||||
IFilesystem plugin;
|
|
||||||
string information;
|
|
||||||
|
|
||||||
if(partitions)
|
|
||||||
{
|
|
||||||
List<Partition> partitionsList = null;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
|
||||||
{
|
|
||||||
ctx.AddTask("Enumerating partitions...").IsIndeterminate();
|
|
||||||
partitionsList = Core.Partitions.GetAll(imageFormat);
|
|
||||||
});
|
|
||||||
|
|
||||||
Core.Partitions.AddSchemesToStats(partitionsList);
|
|
||||||
|
|
||||||
if(partitionsList.Count == 0)
|
|
||||||
{
|
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", "No partitions found");
|
|
||||||
|
|
||||||
if(!filesystems)
|
if(!filesystems)
|
||||||
{
|
continue;
|
||||||
AaruConsole.WriteLine("No partitions founds, not searching for filesystems");
|
|
||||||
|
|
||||||
return (int)ErrorNumber.NothingFound;
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddTask("Identifying filesystems on partition...").IsIndeterminate();
|
||||||
|
Core.Filesystems.Identify(imageFormat, out idPlugins, partitionsList[i]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(idPlugins.Count == 0)
|
||||||
|
AaruConsole.WriteLine("[bold]Filesystem not identified[/]");
|
||||||
|
else if(idPlugins.Count > 1)
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
||||||
|
|
||||||
|
foreach(string pluginName in idPlugins)
|
||||||
|
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
||||||
|
|
||||||
|
plugin.GetInformation(imageFormat, partitionsList[i], out information,
|
||||||
|
encodingClass);
|
||||||
|
|
||||||
|
AaruConsole.Write(information);
|
||||||
|
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
checkRaw = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("{0} partitions found.", partitionsList.Count);
|
|
||||||
|
|
||||||
for(int i = 0; i < partitionsList.Count; i++)
|
|
||||||
{
|
{
|
||||||
Table table = new();
|
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
|
||||||
table.Title = new TableTitle($"Partition {partitionsList[i].Sequence}:");
|
|
||||||
table.AddColumn("");
|
|
||||||
table.AddColumn("");
|
|
||||||
table.HideHeaders();
|
|
||||||
|
|
||||||
table.AddRow("Name", Markup.Escape(partitionsList[i].Name ?? ""));
|
if(plugin == null)
|
||||||
table.AddRow("Type", Markup.Escape(partitionsList[i].Type ?? ""));
|
|
||||||
table.AddRow("Start", $"sector {partitionsList[i].Start}, byte {partitionsList[i].Offset}");
|
|
||||||
|
|
||||||
table.AddRow("Length",
|
|
||||||
$"{partitionsList[i].Length} sectors, {partitionsList[i].Size} bytes");
|
|
||||||
|
|
||||||
table.AddRow("Scheme", Markup.Escape(partitionsList[i].Scheme ?? ""));
|
|
||||||
table.AddRow("Description", Markup.Escape(partitionsList[i].Description ?? ""));
|
|
||||||
|
|
||||||
AnsiConsole.Render(table);
|
|
||||||
|
|
||||||
if(!filesystems)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
||||||
{
|
plugin.GetInformation(imageFormat, partitionsList[i], out information, encodingClass);
|
||||||
ctx.AddTask("Identifying filesystems on partition...").IsIndeterminate();
|
AaruConsole.Write("{0}", information);
|
||||||
Core.Filesystems.Identify(imageFormat, out idPlugins, partitionsList[i]);
|
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||||
});
|
|
||||||
|
|
||||||
if(idPlugins.Count == 0)
|
|
||||||
AaruConsole.WriteLine("[bold]Filesystem not identified[/]");
|
|
||||||
else if(idPlugins.Count > 1)
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
|
||||||
|
|
||||||
foreach(string pluginName in idPlugins)
|
|
||||||
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
|
||||||
|
|
||||||
plugin.GetInformation(imageFormat, partitionsList[i], out information,
|
|
||||||
encodingClass);
|
|
||||||
|
|
||||||
AaruConsole.Write(information);
|
|
||||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
|
|
||||||
|
|
||||||
if(plugin == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
|
||||||
plugin.GetInformation(imageFormat, partitionsList[i], out information, encodingClass);
|
|
||||||
AaruConsole.Write("{0}", information);
|
|
||||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
AaruConsole.WriteLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AaruConsole.WriteLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(checkRaw)
|
if(checkRaw)
|
||||||
|
{
|
||||||
|
var wholePart = new Partition
|
||||||
{
|
{
|
||||||
var wholePart = new Partition
|
Name = "Whole device",
|
||||||
{
|
Length = imageFormat.Info.Sectors,
|
||||||
Name = "Whole device",
|
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
|
||||||
Length = imageFormat.Info.Sectors,
|
};
|
||||||
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
|
|
||||||
};
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
{
|
{
|
||||||
ctx.AddTask("Identifying filesystems...").IsIndeterminate();
|
ctx.AddTask("Identifying filesystems...").IsIndeterminate();
|
||||||
Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
|
Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(idPlugins.Count == 0)
|
if(idPlugins.Count == 0)
|
||||||
AaruConsole.WriteLine("[bold]Filesystem not identified[/]");
|
AaruConsole.WriteLine("[bold]Filesystem not identified[/]");
|
||||||
else if(idPlugins.Count > 1)
|
else if(idPlugins.Count > 1)
|
||||||
{
|
{
|
||||||
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
||||||
|
|
||||||
foreach(string pluginName in idPlugins)
|
foreach(string pluginName in idPlugins)
|
||||||
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
||||||
{
|
|
||||||
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
|
||||||
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
|
|
||||||
AaruConsole.Write(information);
|
|
||||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
|
|
||||||
|
|
||||||
if(plugin != null)
|
|
||||||
{
|
{
|
||||||
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
||||||
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
|
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
|
||||||
AaruConsole.Write(information);
|
AaruConsole.Write(information);
|
||||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
|
||||||
|
|
||||||
|
if(plugin != null)
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
||||||
|
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
|
||||||
|
AaruConsole.Write(information);
|
||||||
|
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
AaruConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
|
|
||||||
AaruConsole.DebugWriteLine("Fs-info command", ex.StackTrace);
|
|
||||||
|
|
||||||
return (int)ErrorNumber.UnexpectedException;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int)ErrorNumber.NoError;
|
|
||||||
}
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
AaruConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
|
||||||
|
AaruConsole.DebugWriteLine("Fs-info command", ex.StackTrace);
|
||||||
|
|
||||||
|
return (int)ErrorNumber.UnexpectedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)ErrorNumber.NoError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,414 +45,418 @@ using Aaru.Core;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Spectre.Console;
|
using Spectre.Console;
|
||||||
|
|
||||||
namespace Aaru.Commands.Filesystem
|
namespace Aaru.Commands.Filesystem;
|
||||||
|
|
||||||
|
internal sealed class LsCommand : Command
|
||||||
{
|
{
|
||||||
internal sealed class LsCommand : Command
|
public LsCommand() : base("list", "Lists files in disc image.")
|
||||||
{
|
{
|
||||||
public LsCommand() : base("list", "Lists files in disc image.")
|
AddAlias("ls");
|
||||||
{
|
|
||||||
AddAlias("ls");
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
Add(new Option(new[]
|
||||||
{
|
|
||||||
"--encoding", "-e"
|
|
||||||
}, "Name of character encoding to use.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<string>(() => null),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--long-format", "-l"
|
|
||||||
}, "Uses long format.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<bool>(() => true),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--options", "-O"
|
|
||||||
}, "Comma separated name=value pairs of options to pass to filesystem plugin.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<string>(() => null),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--namespace", "-n"
|
|
||||||
}, "Namespace to use for filenames.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<string>(() => null),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
AddArgument(new Argument<string>
|
|
||||||
{
|
{
|
||||||
Arity = ArgumentArity.ExactlyOne,
|
"--encoding", "-e"
|
||||||
Description = "Media image path",
|
}, "Name of character encoding to use.")
|
||||||
Name = "image-path"
|
{
|
||||||
|
Argument = new Argument<string>(() => null),
|
||||||
|
Required = false
|
||||||
});
|
});
|
||||||
|
|
||||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--long-format", "-l"
|
||||||
|
}, "Uses long format.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<bool>(() => true),
|
||||||
|
Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--options", "-O"
|
||||||
|
}, "Comma separated name=value pairs of options to pass to filesystem plugin.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<string>(() => null),
|
||||||
|
Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--namespace", "-n"
|
||||||
|
}, "Namespace to use for filenames.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<string>(() => null),
|
||||||
|
Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
AddArgument(new Argument<string>
|
||||||
|
{
|
||||||
|
Arity = ArgumentArity.ExactlyOne,
|
||||||
|
Description = "Media image path",
|
||||||
|
Name = "image-path"
|
||||||
|
});
|
||||||
|
|
||||||
|
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Invoke(bool debug, bool verbose, string encoding, string imagePath, bool longFormat,
|
||||||
|
string @namespace, string options)
|
||||||
|
{
|
||||||
|
MainClass.PrintCopyright();
|
||||||
|
|
||||||
|
if(debug)
|
||||||
|
{
|
||||||
|
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||||
|
{
|
||||||
|
Out = new AnsiConsoleOutput(System.Console.Error)
|
||||||
|
});
|
||||||
|
|
||||||
|
AaruConsole.DebugWriteLineEvent += (format, objects) =>
|
||||||
|
{
|
||||||
|
if(objects is null)
|
||||||
|
stderrConsole.MarkupLine(format);
|
||||||
|
else
|
||||||
|
stderrConsole.MarkupLine(format, objects);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Invoke(bool debug, bool verbose, string encoding, string imagePath, bool longFormat,
|
if(verbose)
|
||||||
string @namespace, string options)
|
AaruConsole.WriteEvent += (format, objects) =>
|
||||||
{
|
|
||||||
MainClass.PrintCopyright();
|
|
||||||
|
|
||||||
if(debug)
|
|
||||||
{
|
{
|
||||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
if(objects is null)
|
||||||
{
|
AnsiConsole.Markup(format);
|
||||||
Out = new AnsiConsoleOutput(System.Console.Error)
|
else
|
||||||
});
|
AnsiConsole.Markup(format, objects);
|
||||||
|
};
|
||||||
|
|
||||||
AaruConsole.DebugWriteLineEvent += (format, objects) =>
|
AaruConsole.DebugWriteLine("Ls command", "--debug={0}", debug);
|
||||||
{
|
AaruConsole.DebugWriteLine("Ls command", "--encoding={0}", encoding);
|
||||||
if(objects is null)
|
AaruConsole.DebugWriteLine("Ls command", "--input={0}", imagePath);
|
||||||
stderrConsole.MarkupLine(format);
|
AaruConsole.DebugWriteLine("Ls command", "--options={0}", options);
|
||||||
else
|
AaruConsole.DebugWriteLine("Ls command", "--verbose={0}", verbose);
|
||||||
stderrConsole.MarkupLine(format, objects);
|
Statistics.AddCommand("ls");
|
||||||
};
|
|
||||||
|
var filtersList = new FiltersList();
|
||||||
|
IFilter inputFilter = null;
|
||||||
|
|
||||||
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddTask("Identifying file filter...").IsIndeterminate();
|
||||||
|
inputFilter = filtersList.GetFilter(imagePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
|
||||||
|
AaruConsole.DebugWriteLine("Ls command", "Parsed options:");
|
||||||
|
|
||||||
|
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
|
||||||
|
AaruConsole.DebugWriteLine("Ls command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
|
||||||
|
|
||||||
|
parsedOptions.Add("debug", debug.ToString());
|
||||||
|
|
||||||
|
if(inputFilter == null)
|
||||||
|
{
|
||||||
|
AaruConsole.ErrorWriteLine("Cannot open specified file.");
|
||||||
|
|
||||||
|
return (int)ErrorNumber.CannotOpenFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
Encoding encodingClass = null;
|
||||||
|
|
||||||
|
if(encoding != null)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
||||||
|
|
||||||
|
if(verbose)
|
||||||
|
AaruConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
|
||||||
|
}
|
||||||
|
catch(ArgumentException)
|
||||||
|
{
|
||||||
|
AaruConsole.ErrorWriteLine("Specified encoding is not supported.");
|
||||||
|
|
||||||
|
return (int)ErrorNumber.EncodingUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginBase plugins = GetPluginBase.Instance;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IMediaImage imageFormat = null;
|
||||||
|
IBaseImage baseImage = null;
|
||||||
|
|
||||||
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddTask("Identifying image format...").IsIndeterminate();
|
||||||
|
baseImage = ImageFormat.Detect(inputFilter);
|
||||||
|
imageFormat = baseImage as IMediaImage;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(baseImage == null)
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("Image format not identified, not proceeding with analysis.");
|
||||||
|
|
||||||
|
return (int)ErrorNumber.UnrecognizedFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(imageFormat == null)
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("Command not supported for this image type.");
|
||||||
|
|
||||||
|
return (int)ErrorNumber.InvalidArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
AaruConsole.WriteEvent += (format, objects) =>
|
AaruConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id);
|
||||||
{
|
else
|
||||||
if(objects is null)
|
AaruConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
|
||||||
AnsiConsole.Markup(format);
|
|
||||||
else
|
|
||||||
AnsiConsole.Markup(format, objects);
|
|
||||||
};
|
|
||||||
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "--debug={0}", debug);
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "--encoding={0}", encoding);
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "--input={0}", imagePath);
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "--options={0}", options);
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "--verbose={0}", verbose);
|
|
||||||
Statistics.AddCommand("ls");
|
|
||||||
|
|
||||||
var filtersList = new FiltersList();
|
|
||||||
IFilter inputFilter = null;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
|
||||||
{
|
|
||||||
ctx.AddTask("Identifying file filter...").IsIndeterminate();
|
|
||||||
inputFilter = filtersList.GetFilter(imagePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "Parsed options:");
|
|
||||||
|
|
||||||
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
|
|
||||||
|
|
||||||
parsedOptions.Add("debug", debug.ToString());
|
|
||||||
|
|
||||||
if(inputFilter == null)
|
|
||||||
{
|
|
||||||
AaruConsole.ErrorWriteLine("Cannot open specified file.");
|
|
||||||
|
|
||||||
return (int)ErrorNumber.CannotOpenFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
Encoding encodingClass = null;
|
|
||||||
|
|
||||||
if(encoding != null)
|
|
||||||
try
|
|
||||||
{
|
|
||||||
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
|
|
||||||
|
|
||||||
if(verbose)
|
|
||||||
AaruConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
|
|
||||||
}
|
|
||||||
catch(ArgumentException)
|
|
||||||
{
|
|
||||||
AaruConsole.ErrorWriteLine("Specified encoding is not supported.");
|
|
||||||
|
|
||||||
return (int)ErrorNumber.EncodingUnknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginBase plugins = GetPluginBase.Instance;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IMediaImage imageFormat = null;
|
ErrorNumber opened = ErrorNumber.NoData;
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
{
|
{
|
||||||
ctx.AddTask("Identifying image format...").IsIndeterminate();
|
ctx.AddTask("Opening image file...").IsIndeterminate();
|
||||||
imageFormat = ImageFormat.Detect(inputFilter);
|
opened = imageFormat.Open(inputFilter);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(imageFormat == null)
|
if(opened != ErrorNumber.NoError)
|
||||||
{
|
{
|
||||||
AaruConsole.WriteLine("Image format not identified, not proceeding with analysis.");
|
AaruConsole.WriteLine("Unable to open image format");
|
||||||
|
AaruConsole.WriteLine("Error {0}", opened);
|
||||||
|
|
||||||
return (int)ErrorNumber.UnrecognizedFormat;
|
return (int)opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose)
|
AaruConsole.DebugWriteLine("Ls command", "Correctly opened image file.");
|
||||||
AaruConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
|
|
||||||
imageFormat.Id);
|
|
||||||
else
|
|
||||||
AaruConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
|
|
||||||
|
|
||||||
try
|
AaruConsole.DebugWriteLine("Ls command", "Image without headers is {0} bytes.",
|
||||||
{
|
imageFormat.Info.ImageSize);
|
||||||
ErrorNumber opened = ErrorNumber.NoData;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
AaruConsole.DebugWriteLine("Ls command", "Image has {0} sectors.", imageFormat.Info.Sectors);
|
||||||
{
|
|
||||||
ctx.AddTask("Opening image file...").IsIndeterminate();
|
|
||||||
opened = imageFormat.Open(inputFilter);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
AaruConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.",
|
||||||
{
|
imageFormat.Info.MediaType);
|
||||||
AaruConsole.WriteLine("Unable to open image format");
|
|
||||||
AaruConsole.WriteLine("Error {0}", opened);
|
|
||||||
|
|
||||||
return (int)opened;
|
Statistics.AddMediaFormat(imageFormat.Format);
|
||||||
}
|
Statistics.AddMedia(imageFormat.Info.MediaType, false);
|
||||||
|
Statistics.AddFilter(inputFilter.Name);
|
||||||
AaruConsole.DebugWriteLine("Ls command", "Correctly opened image file.");
|
|
||||||
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "Image without headers is {0} bytes.",
|
|
||||||
imageFormat.Info.ImageSize);
|
|
||||||
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "Image has {0} sectors.", imageFormat.Info.Sectors);
|
|
||||||
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.",
|
|
||||||
imageFormat.Info.MediaType);
|
|
||||||
|
|
||||||
Statistics.AddMediaFormat(imageFormat.Format);
|
|
||||||
Statistics.AddMedia(imageFormat.Info.MediaType, false);
|
|
||||||
Statistics.AddFilter(inputFilter.Name);
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
AaruConsole.ErrorWriteLine("Unable to open image format");
|
|
||||||
AaruConsole.ErrorWriteLine("Error: {0}", ex.Message);
|
|
||||||
|
|
||||||
return (int)ErrorNumber.CannotOpenFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Partition> partitions = null;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
|
||||||
{
|
|
||||||
ctx.AddTask("Enumerating partitions...").IsIndeterminate();
|
|
||||||
partitions = Core.Partitions.GetAll(imageFormat);
|
|
||||||
});
|
|
||||||
|
|
||||||
Core.Partitions.AddSchemesToStats(partitions);
|
|
||||||
|
|
||||||
if(partitions.Count == 0)
|
|
||||||
{
|
|
||||||
AaruConsole.DebugWriteLine("Ls command", "No partitions found");
|
|
||||||
|
|
||||||
partitions.Add(new Partition
|
|
||||||
{
|
|
||||||
Description = "Whole device",
|
|
||||||
Length = imageFormat.Info.Sectors,
|
|
||||||
Offset = 0,
|
|
||||||
Size = imageFormat.Info.SectorSize * imageFormat.Info.Sectors,
|
|
||||||
Sequence = 1,
|
|
||||||
Start = 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
AaruConsole.WriteLine("{0} partitions found.", partitions.Count);
|
|
||||||
|
|
||||||
for(int i = 0; i < partitions.Count; i++)
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine();
|
|
||||||
AaruConsole.WriteLine("[bold]Partition {0}:[/]", partitions[i].Sequence);
|
|
||||||
|
|
||||||
List<string> idPlugins = null;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
|
||||||
{
|
|
||||||
ctx.AddTask("Identifying filesystems on partition...").IsIndeterminate();
|
|
||||||
Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(idPlugins.Count == 0)
|
|
||||||
AaruConsole.WriteLine("Filesystem not identified");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IReadOnlyFilesystem plugin;
|
|
||||||
ErrorNumber error = ErrorNumber.InvalidArgument;
|
|
||||||
|
|
||||||
if(idPlugins.Count > 1)
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
|
||||||
|
|
||||||
foreach(string pluginName in idPlugins)
|
|
||||||
if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
|
||||||
|
|
||||||
var fs = (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.
|
|
||||||
Invoke(new object[]
|
|
||||||
{});
|
|
||||||
|
|
||||||
if(fs == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
|
||||||
{
|
|
||||||
ctx.AddTask("Mounting filesystem...").IsIndeterminate();
|
|
||||||
|
|
||||||
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions,
|
|
||||||
@namespace);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(error == ErrorNumber.NoError)
|
|
||||||
{
|
|
||||||
ListFilesInDir("/", fs, longFormat);
|
|
||||||
|
|
||||||
Statistics.AddFilesystem(fs.XmlFsType.Type);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AaruConsole.ErrorWriteLine("Unable to mount device, error {0}",
|
|
||||||
error.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
|
|
||||||
|
|
||||||
if(plugin == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
|
||||||
|
|
||||||
var fs = (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.
|
|
||||||
Invoke(new object[]
|
|
||||||
{});
|
|
||||||
|
|
||||||
if(fs == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
|
||||||
{
|
|
||||||
ctx.AddTask("Mounting filesystem...").IsIndeterminate();
|
|
||||||
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(error == ErrorNumber.NoError)
|
|
||||||
{
|
|
||||||
ListFilesInDir("/", fs, longFormat);
|
|
||||||
|
|
||||||
Statistics.AddFilesystem(fs.XmlFsType.Type);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AaruConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch(Exception ex)
|
||||||
{
|
{
|
||||||
AaruConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
|
AaruConsole.ErrorWriteLine("Unable to open image format");
|
||||||
AaruConsole.DebugWriteLine("Ls command", ex.StackTrace);
|
AaruConsole.ErrorWriteLine("Error: {0}", ex.Message);
|
||||||
|
|
||||||
return (int)ErrorNumber.UnexpectedException;
|
return (int)ErrorNumber.CannotOpenFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)ErrorNumber.NoError;
|
List<Partition> partitions = null;
|
||||||
}
|
|
||||||
|
|
||||||
static void ListFilesInDir(string path, [NotNull] IReadOnlyFilesystem fs, bool longFormat)
|
|
||||||
{
|
|
||||||
ErrorNumber error = ErrorNumber.InvalidArgument;
|
|
||||||
List<string> directory = new();
|
|
||||||
|
|
||||||
if(path.StartsWith('/'))
|
|
||||||
path = path.Substring(1);
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(string.IsNullOrEmpty(path) ? "Root directory" : $"Directory: {Markup.Escape(path)}");
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
{
|
{
|
||||||
ctx.AddTask("Reading directory...").IsIndeterminate();
|
ctx.AddTask("Enumerating partitions...").IsIndeterminate();
|
||||||
error = fs.ReadDir(path, out directory);
|
partitions = Core.Partitions.GetAll(imageFormat);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(error != ErrorNumber.NoError)
|
Core.Partitions.AddSchemesToStats(partitions);
|
||||||
{
|
|
||||||
AaruConsole.ErrorWriteLine("Error {0} reading root directory {1}", error.ToString(), path);
|
|
||||||
|
|
||||||
return;
|
if(partitions.Count == 0)
|
||||||
|
{
|
||||||
|
AaruConsole.DebugWriteLine("Ls command", "No partitions found");
|
||||||
|
|
||||||
|
partitions.Add(new Partition
|
||||||
|
{
|
||||||
|
Description = "Whole device",
|
||||||
|
Length = imageFormat.Info.Sectors,
|
||||||
|
Offset = 0,
|
||||||
|
Size = imageFormat.Info.SectorSize * imageFormat.Info.Sectors,
|
||||||
|
Sequence = 1,
|
||||||
|
Start = 0
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<string, FileEntryInfo> stats = new();
|
AaruConsole.WriteLine("{0} partitions found.", partitions.Count);
|
||||||
|
|
||||||
AnsiConsole.Progress().AutoClear(true).HideCompleted(true).
|
for(int i = 0; i < partitions.Count; i++)
|
||||||
Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn()).
|
{
|
||||||
Start(ctx =>
|
AaruConsole.WriteLine();
|
||||||
{
|
AaruConsole.WriteLine("[bold]Partition {0}:[/]", partitions[i].Sequence);
|
||||||
ProgressTask task = ctx.AddTask("Retrieving file information...");
|
|
||||||
task.MaxValue = directory.Count;
|
|
||||||
|
|
||||||
foreach(string entry in directory)
|
List<string> idPlugins = null;
|
||||||
{
|
|
||||||
task.Increment(1);
|
|
||||||
fs.Stat(path + "/" + entry, out FileEntryInfo stat);
|
|
||||||
|
|
||||||
stats.Add(entry, stat);
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach(KeyValuePair<string, FileEntryInfo> entry in
|
|
||||||
stats.OrderBy(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == false))
|
|
||||||
if(longFormat)
|
|
||||||
{
|
{
|
||||||
if(entry.Value != null)
|
ctx.AddTask("Identifying filesystems on partition...").IsIndeterminate();
|
||||||
{
|
Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]);
|
||||||
if(entry.Value.Attributes.HasFlag(FileAttributes.Directory))
|
});
|
||||||
AaruConsole.WriteLine("{0, 10:d} {0, 12:T} {1, -20} {2}", entry.Value.CreationTimeUtc,
|
|
||||||
"<DIR>", Markup.Escape(entry.Key));
|
|
||||||
else
|
|
||||||
AaruConsole.WriteLine("{0, 10:d} {0, 12:T} {1, 6}{2, 14:N0} {3}",
|
|
||||||
entry.Value.CreationTimeUtc, entry.Value.Inode, entry.Value.Length,
|
|
||||||
Markup.Escape(entry.Key));
|
|
||||||
|
|
||||||
error = fs.ListXAttr(path + "/" + entry.Key, out List<string> xattrs);
|
if(idPlugins.Count == 0)
|
||||||
|
AaruConsole.WriteLine("Filesystem not identified");
|
||||||
if(error != ErrorNumber.NoError)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach(string xattr in xattrs)
|
|
||||||
{
|
|
||||||
byte[] xattrBuf = Array.Empty<byte>();
|
|
||||||
error = fs.GetXattr(path + "/" + entry.Key, xattr, ref xattrBuf);
|
|
||||||
|
|
||||||
if(error == ErrorNumber.NoError)
|
|
||||||
AaruConsole.WriteLine("\t\t{0}\t{1:##,#}", Markup.Escape(xattr), xattrBuf.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AaruConsole.WriteLine("{0, 47}{1}", string.Empty, Markup.Escape(entry.Key));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AaruConsole.
|
IReadOnlyFilesystem plugin;
|
||||||
WriteLine(entry.Value?.Attributes.HasFlag(FileAttributes.Directory) == true ? "{0}/" : "{0}",
|
ErrorNumber error = ErrorNumber.InvalidArgument;
|
||||||
entry.Key);
|
|
||||||
|
if(idPlugins.Count > 1)
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
||||||
|
|
||||||
|
foreach(string pluginName in idPlugins)
|
||||||
|
if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
||||||
|
|
||||||
|
var fs = (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.
|
||||||
|
Invoke(new object[]
|
||||||
|
{});
|
||||||
|
|
||||||
|
if(fs == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddTask("Mounting filesystem...").IsIndeterminate();
|
||||||
|
|
||||||
|
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions,
|
||||||
|
@namespace);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(error == ErrorNumber.NoError)
|
||||||
|
{
|
||||||
|
ListFilesInDir("/", fs, longFormat);
|
||||||
|
|
||||||
|
Statistics.AddFilesystem(fs.XmlFsType.Type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AaruConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
|
||||||
|
|
||||||
|
if(plugin == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
||||||
|
|
||||||
|
var fs = (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.
|
||||||
|
Invoke(new object[]
|
||||||
|
{});
|
||||||
|
|
||||||
|
if(fs == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddTask("Mounting filesystem...").IsIndeterminate();
|
||||||
|
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(error == ErrorNumber.NoError)
|
||||||
|
{
|
||||||
|
ListFilesInDir("/", fs, longFormat);
|
||||||
|
|
||||||
|
Statistics.AddFilesystem(fs.XmlFsType.Type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AaruConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
AaruConsole.WriteLine();
|
|
||||||
|
|
||||||
foreach(KeyValuePair<string, FileEntryInfo> subdirectory in
|
|
||||||
stats.Where(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == true))
|
|
||||||
ListFilesInDir(path + "/" + subdirectory.Key, fs, longFormat);
|
|
||||||
}
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
AaruConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
|
||||||
|
AaruConsole.DebugWriteLine("Ls command", ex.StackTrace);
|
||||||
|
|
||||||
|
return (int)ErrorNumber.UnexpectedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)ErrorNumber.NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ListFilesInDir(string path, [NotNull] IReadOnlyFilesystem fs, bool longFormat)
|
||||||
|
{
|
||||||
|
ErrorNumber error = ErrorNumber.InvalidArgument;
|
||||||
|
List<string> directory = new();
|
||||||
|
|
||||||
|
if(path.StartsWith('/'))
|
||||||
|
path = path.Substring(1);
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(string.IsNullOrEmpty(path) ? "Root directory" : $"Directory: {Markup.Escape(path)}");
|
||||||
|
|
||||||
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddTask("Reading directory...").IsIndeterminate();
|
||||||
|
error = fs.ReadDir(path, out directory);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(error != ErrorNumber.NoError)
|
||||||
|
{
|
||||||
|
AaruConsole.ErrorWriteLine("Error {0} reading root directory {1}", error.ToString(), path);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, FileEntryInfo> stats = new();
|
||||||
|
|
||||||
|
AnsiConsole.Progress().AutoClear(true).HideCompleted(true).
|
||||||
|
Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn()).Start(ctx =>
|
||||||
|
{
|
||||||
|
ProgressTask task = ctx.AddTask("Retrieving file information...");
|
||||||
|
task.MaxValue = directory.Count;
|
||||||
|
|
||||||
|
foreach(string entry in directory)
|
||||||
|
{
|
||||||
|
task.Increment(1);
|
||||||
|
fs.Stat(path + "/" + entry, out FileEntryInfo stat);
|
||||||
|
|
||||||
|
stats.Add(entry, stat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach(KeyValuePair<string, FileEntryInfo> entry in
|
||||||
|
stats.OrderBy(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == false))
|
||||||
|
if(longFormat)
|
||||||
|
{
|
||||||
|
if(entry.Value != null)
|
||||||
|
{
|
||||||
|
if(entry.Value.Attributes.HasFlag(FileAttributes.Directory))
|
||||||
|
AaruConsole.WriteLine("{0, 10:d} {0, 12:T} {1, -20} {2}", entry.Value.CreationTimeUtc,
|
||||||
|
"<DIR>", Markup.Escape(entry.Key));
|
||||||
|
else
|
||||||
|
AaruConsole.WriteLine("{0, 10:d} {0, 12:T} {1, 6}{2, 14:N0} {3}", entry.Value.CreationTimeUtc,
|
||||||
|
entry.Value.Inode, entry.Value.Length, Markup.Escape(entry.Key));
|
||||||
|
|
||||||
|
error = fs.ListXAttr(path + "/" + entry.Key, out List<string> xattrs);
|
||||||
|
|
||||||
|
if(error != ErrorNumber.NoError)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach(string xattr in xattrs)
|
||||||
|
{
|
||||||
|
byte[] xattrBuf = Array.Empty<byte>();
|
||||||
|
error = fs.GetXattr(path + "/" + entry.Key, xattr, ref xattrBuf);
|
||||||
|
|
||||||
|
if(error == ErrorNumber.NoError)
|
||||||
|
AaruConsole.WriteLine("\t\t{0}\t{1:##,#}", Markup.Escape(xattr), xattrBuf.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AaruConsole.WriteLine("{0, 47}{1}", string.Empty, Markup.Escape(entry.Key));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine(entry.Value?.Attributes.HasFlag(FileAttributes.Directory) == true ? "{0}/" : "{0}",
|
||||||
|
entry.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
AaruConsole.WriteLine();
|
||||||
|
|
||||||
|
foreach(KeyValuePair<string, FileEntryInfo> subdirectory in
|
||||||
|
stats.Where(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == true))
|
||||||
|
ListFilesInDir(path + "/" + subdirectory.Key, fs, longFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -42,389 +42,393 @@ using Aaru.Decoders.CD;
|
|||||||
using Aaru.Decoders.SCSI;
|
using Aaru.Decoders.SCSI;
|
||||||
using Spectre.Console;
|
using Spectre.Console;
|
||||||
|
|
||||||
namespace Aaru.Commands.Image
|
namespace Aaru.Commands.Image;
|
||||||
|
|
||||||
|
internal sealed class DecodeCommand : Command
|
||||||
{
|
{
|
||||||
internal sealed class DecodeCommand : Command
|
public DecodeCommand() : base("decode", "Decodes and pretty prints disk and/or sector tags.")
|
||||||
{
|
{
|
||||||
public DecodeCommand() : base("decode", "Decodes and pretty prints disk and/or sector tags.")
|
Add(new Option(new[]
|
||||||
{
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--disk-tags", "-f"
|
|
||||||
}, "Decode disk tags.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<bool>(() => true),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--length", "-l"
|
|
||||||
}, "How many sectors to decode, or \"all\".")
|
|
||||||
{
|
|
||||||
Argument = new Argument<string>(() => "all"),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--sector-tags", "-p"
|
|
||||||
}, "Decode sector tags.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<bool>(() => true),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new Option(new[]
|
|
||||||
{
|
|
||||||
"--start", "-s"
|
|
||||||
}, "Sector to start decoding from.")
|
|
||||||
{
|
|
||||||
Argument = new Argument<ulong>(() => 0),
|
|
||||||
Required = false
|
|
||||||
});
|
|
||||||
|
|
||||||
AddArgument(new Argument<string>
|
|
||||||
{
|
{
|
||||||
Arity = ArgumentArity.ExactlyOne,
|
"--disk-tags", "-f"
|
||||||
Description = "Media image path",
|
}, "Decode disk tags.")
|
||||||
Name = "image-path"
|
{
|
||||||
|
Argument = new Argument<bool>(() => true),
|
||||||
|
Required = false
|
||||||
});
|
});
|
||||||
|
|
||||||
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--length", "-l"
|
||||||
|
}, "How many sectors to decode, or \"all\".")
|
||||||
|
{
|
||||||
|
Argument = new Argument<string>(() => "all"),
|
||||||
|
Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--sector-tags", "-p"
|
||||||
|
}, "Decode sector tags.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<bool>(() => true),
|
||||||
|
Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--start", "-s"
|
||||||
|
}, "Sector to start decoding from.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<ulong>(() => 0),
|
||||||
|
Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
AddArgument(new Argument<string>
|
||||||
|
{
|
||||||
|
Arity = ArgumentArity.ExactlyOne,
|
||||||
|
Description = "Media image path",
|
||||||
|
Name = "image-path"
|
||||||
|
});
|
||||||
|
|
||||||
|
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Invoke(bool verbose, bool debug, bool diskTags, string imagePath, string length, bool sectorTags,
|
||||||
|
ulong startSector)
|
||||||
|
{
|
||||||
|
MainClass.PrintCopyright();
|
||||||
|
|
||||||
|
if(debug)
|
||||||
|
{
|
||||||
|
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
||||||
|
{
|
||||||
|
Out = new AnsiConsoleOutput(System.Console.Error)
|
||||||
|
});
|
||||||
|
|
||||||
|
AaruConsole.DebugWriteLineEvent += (format, objects) =>
|
||||||
|
{
|
||||||
|
if(objects is null)
|
||||||
|
stderrConsole.MarkupLine(format);
|
||||||
|
else
|
||||||
|
stderrConsole.MarkupLine(format, objects);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Invoke(bool verbose, bool debug, bool diskTags, string imagePath, string length,
|
if(verbose)
|
||||||
bool sectorTags, ulong startSector)
|
AaruConsole.WriteEvent += (format, objects) =>
|
||||||
|
{
|
||||||
|
if(objects is null)
|
||||||
|
AnsiConsole.Markup(format);
|
||||||
|
else
|
||||||
|
AnsiConsole.Markup(format, objects);
|
||||||
|
};
|
||||||
|
|
||||||
|
Statistics.AddCommand("decode");
|
||||||
|
|
||||||
|
AaruConsole.DebugWriteLine("Decode command", "--debug={0}", debug);
|
||||||
|
AaruConsole.DebugWriteLine("Decode command", "--disk-tags={0}", diskTags);
|
||||||
|
AaruConsole.DebugWriteLine("Decode command", "--input={0}", imagePath);
|
||||||
|
AaruConsole.DebugWriteLine("Decode command", "--length={0}", length);
|
||||||
|
AaruConsole.DebugWriteLine("Decode command", "--sector-tags={0}", sectorTags);
|
||||||
|
AaruConsole.DebugWriteLine("Decode command", "--start={0}", startSector);
|
||||||
|
AaruConsole.DebugWriteLine("Decode command", "--verbose={0}", verbose);
|
||||||
|
|
||||||
|
var filtersList = new FiltersList();
|
||||||
|
IFilter inputFilter = null;
|
||||||
|
|
||||||
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
{
|
{
|
||||||
MainClass.PrintCopyright();
|
ctx.AddTask("Identifying file filter...").IsIndeterminate();
|
||||||
|
inputFilter = filtersList.GetFilter(imagePath);
|
||||||
if(debug)
|
});
|
||||||
{
|
|
||||||
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
if(inputFilter == null)
|
||||||
{
|
{
|
||||||
Out = new AnsiConsoleOutput(System.Console.Error)
|
AaruConsole.ErrorWriteLine("Cannot open specified file.");
|
||||||
});
|
|
||||||
|
return (int)ErrorNumber.CannotOpenFile;
|
||||||
AaruConsole.DebugWriteLineEvent += (format, objects) =>
|
}
|
||||||
{
|
|
||||||
if(objects is null)
|
IMediaImage inputFormat = null;
|
||||||
stderrConsole.MarkupLine(format);
|
IBaseImage baseImage = null;
|
||||||
else
|
|
||||||
stderrConsole.MarkupLine(format, objects);
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
};
|
{
|
||||||
}
|
ctx.AddTask("Identifying image format...").IsIndeterminate();
|
||||||
|
baseImage = ImageFormat.Detect(inputFilter);
|
||||||
if(verbose)
|
inputFormat = baseImage as IMediaImage;
|
||||||
AaruConsole.WriteEvent += (format, objects) =>
|
});
|
||||||
{
|
|
||||||
if(objects is null)
|
if(baseImage == null)
|
||||||
AnsiConsole.Markup(format);
|
{
|
||||||
else
|
AaruConsole.ErrorWriteLine("Unable to recognize image format, not decoding");
|
||||||
AnsiConsole.Markup(format, objects);
|
|
||||||
};
|
return (int)ErrorNumber.UnrecognizedFormat;
|
||||||
|
}
|
||||||
Statistics.AddCommand("decode");
|
|
||||||
|
if(inputFormat == null)
|
||||||
AaruConsole.DebugWriteLine("Decode command", "--debug={0}", debug);
|
{
|
||||||
AaruConsole.DebugWriteLine("Decode command", "--disk-tags={0}", diskTags);
|
AaruConsole.WriteLine("Command not supported for this image type.");
|
||||||
AaruConsole.DebugWriteLine("Decode command", "--input={0}", imagePath);
|
|
||||||
AaruConsole.DebugWriteLine("Decode command", "--length={0}", length);
|
return (int)ErrorNumber.InvalidArgument;
|
||||||
AaruConsole.DebugWriteLine("Decode command", "--sector-tags={0}", sectorTags);
|
}
|
||||||
AaruConsole.DebugWriteLine("Decode command", "--start={0}", startSector);
|
|
||||||
AaruConsole.DebugWriteLine("Decode command", "--verbose={0}", verbose);
|
ErrorNumber opened = ErrorNumber.NoData;
|
||||||
|
|
||||||
var filtersList = new FiltersList();
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
||||||
IFilter inputFilter = null;
|
{
|
||||||
|
ctx.AddTask("Opening image file...").IsIndeterminate();
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
opened = inputFormat.Open(inputFilter);
|
||||||
{
|
});
|
||||||
ctx.AddTask("Identifying file filter...").IsIndeterminate();
|
|
||||||
inputFilter = filtersList.GetFilter(imagePath);
|
if(opened != ErrorNumber.NoError)
|
||||||
});
|
{
|
||||||
|
AaruConsole.WriteLine("Error {opened} opening image format");
|
||||||
if(inputFilter == null)
|
|
||||||
{
|
return (int)opened;
|
||||||
AaruConsole.ErrorWriteLine("Cannot open specified file.");
|
}
|
||||||
|
|
||||||
return (int)ErrorNumber.CannotOpenFile;
|
Statistics.AddMediaFormat(inputFormat.Format);
|
||||||
}
|
Statistics.AddMedia(inputFormat.Info.MediaType, false);
|
||||||
|
Statistics.AddFilter(inputFilter.Name);
|
||||||
IMediaImage inputFormat = null;
|
ErrorNumber errno;
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
if(diskTags)
|
||||||
{
|
if(inputFormat.Info.ReadableMediaTags.Count == 0)
|
||||||
ctx.AddTask("Identifying image format...").IsIndeterminate();
|
AaruConsole.WriteLine("There are no disk tags in chosen disc image.");
|
||||||
inputFormat = ImageFormat.Detect(inputFilter);
|
else
|
||||||
});
|
foreach(MediaTagType tag in inputFormat.Info.ReadableMediaTags)
|
||||||
|
switch(tag)
|
||||||
if(inputFormat == null)
|
|
||||||
{
|
|
||||||
AaruConsole.ErrorWriteLine("Unable to recognize image format, not decoding");
|
|
||||||
|
|
||||||
return (int)ErrorNumber.UnrecognizedFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorNumber opened = ErrorNumber.NoData;
|
|
||||||
|
|
||||||
Core.Spectre.ProgressSingleSpinner(ctx =>
|
|
||||||
{
|
|
||||||
ctx.AddTask("Opening image file...").IsIndeterminate();
|
|
||||||
opened = inputFormat.Open(inputFilter);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(opened != ErrorNumber.NoError)
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("Error {opened} opening image format");
|
|
||||||
|
|
||||||
return (int)opened;
|
|
||||||
}
|
|
||||||
|
|
||||||
Statistics.AddMediaFormat(inputFormat.Format);
|
|
||||||
Statistics.AddMedia(inputFormat.Info.MediaType, false);
|
|
||||||
Statistics.AddFilter(inputFilter.Name);
|
|
||||||
ErrorNumber errno;
|
|
||||||
|
|
||||||
if(diskTags)
|
|
||||||
if(inputFormat.Info.ReadableMediaTags.Count == 0)
|
|
||||||
AaruConsole.WriteLine("There are no disk tags in chosen disc image.");
|
|
||||||
else
|
|
||||||
foreach(MediaTagType tag in inputFormat.Info.ReadableMediaTags)
|
|
||||||
switch(tag)
|
|
||||||
{
|
|
||||||
case MediaTagType.SCSI_INQUIRY:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.SCSI_INQUIRY, out byte[] inquiry);
|
|
||||||
|
|
||||||
if(inquiry == null)
|
|
||||||
AaruConsole.WriteLine("Error {0} reading SCSI INQUIRY response from disc image",
|
|
||||||
errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]SCSI INQUIRY command response:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(Inquiry.Prettify(inquiry));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MediaTagType.ATA_IDENTIFY:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.ATA_IDENTIFY, out byte[] identify);
|
|
||||||
|
|
||||||
if(errno != ErrorNumber.NoError)
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("Error {0} reading ATA IDENTIFY DEVICE response from disc image",
|
|
||||||
errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]ATA IDENTIFY DEVICE command response:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(Identify.Prettify(identify));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MediaTagType.ATAPI_IDENTIFY:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.ATAPI_IDENTIFY, out byte[] identify);
|
|
||||||
|
|
||||||
if(identify == null)
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("Error {0} reading ATA IDENTIFY PACKET DEVICE response from disc image",
|
|
||||||
errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]ATA IDENTIFY PACKET DEVICE command response:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(Identify.Prettify(identify));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MediaTagType.CD_ATIP:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.CD_ATIP, out byte[] atip);
|
|
||||||
|
|
||||||
if(errno != ErrorNumber.NoError)
|
|
||||||
AaruConsole.WriteLine("Error {0} reading CD ATIP from disc image", errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]CD ATIP:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(ATIP.Prettify(atip));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MediaTagType.CD_FullTOC:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.CD_FullTOC, out byte[] fullToc);
|
|
||||||
|
|
||||||
if(errno != ErrorNumber.NoError)
|
|
||||||
AaruConsole.WriteLine("Error {0} reading CD full TOC from disc image", errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]CD full TOC:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(FullTOC.Prettify(fullToc));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MediaTagType.CD_PMA:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.CD_PMA, out byte[] pma);
|
|
||||||
|
|
||||||
if(errno != ErrorNumber.NoError)
|
|
||||||
AaruConsole.WriteLine("Error {0} reading CD PMA from disc image", errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]CD PMA:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(PMA.Prettify(pma));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MediaTagType.CD_SessionInfo:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.CD_SessionInfo, out byte[] sessionInfo);
|
|
||||||
|
|
||||||
if(errno != ErrorNumber.NoError)
|
|
||||||
AaruConsole.WriteLine("Error {0} reading CD session information from disc image",
|
|
||||||
errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]CD session information:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(Session.Prettify(sessionInfo));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MediaTagType.CD_TEXT:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.CD_TEXT, out byte[] cdText);
|
|
||||||
|
|
||||||
if(errno != ErrorNumber.NoError)
|
|
||||||
AaruConsole.WriteLine("Error reading CD-TEXT from disc image");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]CD-TEXT:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(CDTextOnLeadIn.Prettify(cdText));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MediaTagType.CD_TOC:
|
|
||||||
{
|
|
||||||
errno = inputFormat.ReadMediaTag(MediaTagType.CD_TOC, out byte[] toc);
|
|
||||||
|
|
||||||
if(toc == null)
|
|
||||||
AaruConsole.WriteLine("Error reading CD TOC from disc image");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AaruConsole.WriteLine("[bold]CD TOC:[/]");
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
|
|
||||||
AaruConsole.WriteLine(TOC.Prettify(toc));
|
|
||||||
|
|
||||||
AaruConsole.
|
|
||||||
WriteLine("================================================================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
AaruConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.",
|
|
||||||
tag);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sectorTags)
|
|
||||||
{
|
|
||||||
if(length.ToLowerInvariant() == "all") {}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!ulong.TryParse(length, out ulong _))
|
|
||||||
{
|
{
|
||||||
AaruConsole.WriteLine("Value \"{0}\" is not a valid number for length.", length);
|
case MediaTagType.SCSI_INQUIRY:
|
||||||
AaruConsole.WriteLine("Not decoding sectors tags");
|
|
||||||
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(inputFormat.Info.ReadableSectorTags.Count == 0)
|
|
||||||
AaruConsole.WriteLine("There are no sector tags in chosen disc image.");
|
|
||||||
else
|
|
||||||
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags)
|
|
||||||
switch(tag)
|
|
||||||
{
|
{
|
||||||
default:
|
errno = inputFormat.ReadMediaTag(MediaTagType.SCSI_INQUIRY, out byte[] inquiry);
|
||||||
AaruConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.",
|
|
||||||
tag);
|
|
||||||
|
|
||||||
break;
|
if(inquiry == null)
|
||||||
|
AaruConsole.WriteLine("Error {0} reading SCSI INQUIRY response from disc image", errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]SCSI INQUIRY command response:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(Inquiry.Prettify(inquiry));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case MediaTagType.ATA_IDENTIFY:
|
||||||
|
{
|
||||||
|
errno = inputFormat.ReadMediaTag(MediaTagType.ATA_IDENTIFY, out byte[] identify);
|
||||||
|
|
||||||
// TODO: Not implemented
|
if(errno != ErrorNumber.NoError)
|
||||||
|
AaruConsole.WriteLine("Error {0} reading ATA IDENTIFY DEVICE response from disc image",
|
||||||
|
errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]ATA IDENTIFY DEVICE command response:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(Identify.Prettify(identify));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MediaTagType.ATAPI_IDENTIFY:
|
||||||
|
{
|
||||||
|
errno = inputFormat.ReadMediaTag(MediaTagType.ATAPI_IDENTIFY, out byte[] identify);
|
||||||
|
|
||||||
|
if(identify == null)
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("Error {0} reading ATA IDENTIFY PACKET DEVICE response from disc image",
|
||||||
|
errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]ATA IDENTIFY PACKET DEVICE command response:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(Identify.Prettify(identify));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MediaTagType.CD_ATIP:
|
||||||
|
{
|
||||||
|
errno = inputFormat.ReadMediaTag(MediaTagType.CD_ATIP, out byte[] atip);
|
||||||
|
|
||||||
|
if(errno != ErrorNumber.NoError)
|
||||||
|
AaruConsole.WriteLine("Error {0} reading CD ATIP from disc image", errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]CD ATIP:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(ATIP.Prettify(atip));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MediaTagType.CD_FullTOC:
|
||||||
|
{
|
||||||
|
errno = inputFormat.ReadMediaTag(MediaTagType.CD_FullTOC, out byte[] fullToc);
|
||||||
|
|
||||||
|
if(errno != ErrorNumber.NoError)
|
||||||
|
AaruConsole.WriteLine("Error {0} reading CD full TOC from disc image", errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]CD full TOC:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(FullTOC.Prettify(fullToc));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MediaTagType.CD_PMA:
|
||||||
|
{
|
||||||
|
errno = inputFormat.ReadMediaTag(MediaTagType.CD_PMA, out byte[] pma);
|
||||||
|
|
||||||
|
if(errno != ErrorNumber.NoError)
|
||||||
|
AaruConsole.WriteLine("Error {0} reading CD PMA from disc image", errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]CD PMA:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(PMA.Prettify(pma));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MediaTagType.CD_SessionInfo:
|
||||||
|
{
|
||||||
|
errno = inputFormat.ReadMediaTag(MediaTagType.CD_SessionInfo, out byte[] sessionInfo);
|
||||||
|
|
||||||
|
if(errno != ErrorNumber.NoError)
|
||||||
|
AaruConsole.WriteLine("Error {0} reading CD session information from disc image",
|
||||||
|
errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]CD session information:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(Session.Prettify(sessionInfo));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MediaTagType.CD_TEXT:
|
||||||
|
{
|
||||||
|
errno = inputFormat.ReadMediaTag(MediaTagType.CD_TEXT, out byte[] cdText);
|
||||||
|
|
||||||
|
if(errno != ErrorNumber.NoError)
|
||||||
|
AaruConsole.WriteLine("Error reading CD-TEXT from disc image");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]CD-TEXT:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(CDTextOnLeadIn.Prettify(cdText));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MediaTagType.CD_TOC:
|
||||||
|
{
|
||||||
|
errno = inputFormat.ReadMediaTag(MediaTagType.CD_TOC, out byte[] toc);
|
||||||
|
|
||||||
|
if(toc == null)
|
||||||
|
AaruConsole.WriteLine("Error reading CD TOC from disc image");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("[bold]CD TOC:[/]");
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
|
||||||
|
AaruConsole.WriteLine(TOC.Prettify(toc));
|
||||||
|
|
||||||
|
AaruConsole.
|
||||||
|
WriteLine("================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
AaruConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.", tag);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sectorTags)
|
||||||
|
{
|
||||||
|
if(length.ToLowerInvariant() == "all") {}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!ulong.TryParse(length, out ulong _))
|
||||||
|
{
|
||||||
|
AaruConsole.WriteLine("Value \"{0}\" is not a valid number for length.", length);
|
||||||
|
AaruConsole.WriteLine("Not decoding sectors tags");
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)ErrorNumber.NoError;
|
if(inputFormat.Info.ReadableSectorTags.Count == 0)
|
||||||
|
AaruConsole.WriteLine("There are no sector tags in chosen disc image.");
|
||||||
|
else
|
||||||
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags)
|
||||||
|
switch(tag)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
AaruConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.", tag);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Not implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (int)ErrorNumber.NoError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user