Replace Mono.Options with System.CommandLine

This commit is contained in:
2020-01-02 04:09:39 +00:00
parent 4a74de5843
commit 758d4dd364
30 changed files with 2389 additions and 2147 deletions

View File

@@ -186,8 +186,11 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=ATAPI/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ATIP/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BANDAI/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bitsetting/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bluray/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=cartstatus/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=CDDA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=cdtext/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=CDTV/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=cdrom/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=certance/@EntryIndexedValue">True</s:Boolean>
@@ -196,20 +199,39 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=cicm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Claunia/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=DDCD/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dicremote/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Drive_0027s/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dvdr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dvdram/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ecsd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=eeprom/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=EVPD/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=formatlayers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=getconfiguration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hddvd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hddvdr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Hldtst/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=iomega/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=isrc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kreon/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lastrmd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lastsequence/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=layercap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Lbas/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=leadout/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=manuallj/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mapfile/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mediaid/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mediaserialnumber/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mhdd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mhddlog/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=milcd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=MINIX/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=modesense/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NTFS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NTSC/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nuon/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nvme/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=opticals/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCMCIA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Plextor/@EntryIndexedValue">True</s:Boolean>
@@ -219,18 +241,34 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Plextor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pmin/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Portillo/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Powe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pregap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pregaps/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=printhex/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=psec/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rawtoc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=readblocklimits/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=readcapacity/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=readcd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=readdiscinformation/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=readdiscstructure/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Recordables/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reiser/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=remapanchor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=reportdensitysupport/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SDHCI/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Secu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=spamsum/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=subchannels/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=subpages/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=subchannel/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=subchannels/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=umounting/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=undecoded/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Vari/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=writeprotection/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Wxripper/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xattr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xattrs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xeto/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xtreme/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -32,104 +32,103 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class AnalyzeCommand : Command
internal class AnalyzeCommand : Command
{
string encodingName;
string inputFile;
bool searchForFilesystems = true;
bool searchForPartitions = true;
bool showHelp;
public AnalyzeCommand() : base("analyze",
"Analyzes a disc image and searches for partitions and/or filesystems.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--encoding", "-e"
}, "Name of character encoding to use.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option(new[]
{
"--filesystems", "-f"
}, "Searches and analyzes 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>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
{"filesystems|f", "Searches and analyzes filesystems.", b => searchForFilesystems = b != null},
{"partitions|p", "Searches and interprets partitions.", b => searchForPartitions = b != null},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "Disc image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
int Invoke(bool verbose, bool debug, string encoding, bool filesystems, bool partitions, string imagePath)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("analyze");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Analyze command", "--encoding={0}", encoding);
DicConsole.DebugWriteLine("Analyze command", "--filesystems={0}", filesystems);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Analyze command", "--partitions={0}", partitions);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose);
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Analyze command", "--encoding={0}", encodingName);
DicConsole.DebugWriteLine("Analyze command", "--filesystems={0}", searchForFilesystems);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Analyze command", "--partitions={0}", searchForPartitions);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose);
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
Encoding encoding = null;
Encoding encodingClass = null;
if(encodingName != null)
if(encoding != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
if(verbose)
DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
}
catch(ArgumentException)
{
DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return (int)ErrorNumber.EncodingUnknown;
return(int)ErrorNumber.EncodingUnknown;
}
PluginBase plugins = GetPluginBase.Instance;
bool checkraw = false;
bool checkRaw = false;
try
{
@@ -138,13 +137,16 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
imageFormat.Id);
else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
else
DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
DicConsole.WriteLine();
try
@@ -153,10 +155,11 @@ namespace DiscImageChef.Commands
{
DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given");
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
if(MainClass.Verbose)
if(verbose)
{
ImageInfo.PrintImageInfo(imageFormat);
DicConsole.WriteLine();
@@ -171,52 +174,62 @@ namespace DiscImageChef.Commands
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
DicConsole.DebugWriteLine("Analyze command", "Stack trace: {0}", ex.StackTrace);
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
List<string> idPlugins;
IFilesystem plugin;
string information;
if(searchForPartitions)
{
List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
Core.Partitions.AddSchemesToStats(partitions);
if(partitions.Count == 0)
if(partitions)
{
List<Partition> partitionsList = Core.Partitions.GetAll(imageFormat);
Core.Partitions.AddSchemesToStats(partitionsList);
if(partitionsList.Count == 0)
{
DicConsole.DebugWriteLine("Analyze command", "No partitions found");
if(!searchForFilesystems)
if(!filesystems)
{
DicConsole.WriteLine("No partitions founds, not searching for filesystems");
return (int)ErrorNumber.NothingFound;
return(int)ErrorNumber.NothingFound;
}
checkraw = true;
checkRaw = true;
}
else
{
DicConsole.WriteLine("{0} partitions found.", partitions.Count);
DicConsole.WriteLine("{0} partitions found.", partitionsList.Count);
for(int i = 0; i < partitions.Count; i++)
for(int i = 0; i < partitionsList.Count; i++)
{
DicConsole.WriteLine();
DicConsole.WriteLine("Partition {0}:", partitions[i].Sequence);
DicConsole.WriteLine("Partition name: {0}", partitions[i].Name);
DicConsole.WriteLine("Partition type: {0}", partitions[i].Type);
DicConsole.WriteLine("Partition start: sector {0}, byte {1}", partitions[i].Start,
partitions[i].Offset);
DicConsole.WriteLine("Partition length: {0} sectors, {1} bytes", partitions[i].Length,
partitions[i].Size);
DicConsole.WriteLine("Partition scheme: {0}", partitions[i].Scheme);
DicConsole.WriteLine("Partition description:");
DicConsole.WriteLine(partitions[i].Description);
DicConsole.WriteLine("Partition {0}:", partitionsList[i].Sequence);
DicConsole.WriteLine("Partition name: {0}", partitionsList[i].Name);
DicConsole.WriteLine("Partition type: {0}", partitionsList[i].Type);
if(!searchForFilesystems) continue;
DicConsole.WriteLine("Partition start: sector {0}, byte {1}", partitionsList[i].Start,
partitionsList[i].Offset);
DicConsole.WriteLine("Partition length: {0} sectors, {1} bytes", partitionsList[i].Length,
partitionsList[i].Size);
DicConsole.WriteLine("Partition scheme: {0}", partitionsList[i].Scheme);
DicConsole.WriteLine("Partition description:");
DicConsole.WriteLine(partitionsList[i].Description);
if(!filesystems)
continue;
DicConsole.WriteLine("Identifying filesystem on partition");
Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]);
if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified");
Core.Filesystems.Identify(imageFormat, out idPlugins, partitionsList[i]);
if(idPlugins.Count == 0)
DicConsole.WriteLine("Filesystem not identified");
else if(idPlugins.Count > 1)
{
DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");
@@ -225,7 +238,10 @@ namespace DiscImageChef.Commands
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
{
DicConsole.WriteLine($"As identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, partitions[i], out information, encoding);
plugin.GetInformation(imageFormat, partitionsList[i], out information,
encodingClass);
DicConsole.Write(information);
Statistics.AddFilesystem(plugin.XmlFsType.Type);
}
@@ -233,10 +249,12 @@ namespace DiscImageChef.Commands
else
{
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
if(plugin == null) continue;
if(plugin == null)
continue;
DicConsole.WriteLine($"Identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, partitions[i], out information, encoding);
plugin.GetInformation(imageFormat, partitionsList[i], out information, encodingClass);
DicConsole.Write("{0}", information);
Statistics.AddFilesystem(plugin.XmlFsType.Type);
}
@@ -244,17 +262,18 @@ namespace DiscImageChef.Commands
}
}
if(checkraw)
if(checkRaw)
{
Partition wholePart = new Partition
var wholePart = new Partition
{
Name = "Whole device",
Length = imageFormat.Info.Sectors,
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
Name = "Whole device", Length = imageFormat.Info.Sectors,
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
};
Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified");
if(idPlugins.Count == 0)
DicConsole.WriteLine("Filesystem not identified");
else if(idPlugins.Count > 1)
{
DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");
@@ -263,7 +282,7 @@ namespace DiscImageChef.Commands
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
{
DicConsole.WriteLine($"As identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, wholePart, out information, encoding);
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
DicConsole.Write(information);
Statistics.AddFilesystem(plugin.XmlFsType.Type);
}
@@ -271,10 +290,11 @@ namespace DiscImageChef.Commands
else
{
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
if(plugin != null)
{
DicConsole.WriteLine($"Identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, wholePart, out information, encoding);
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
DicConsole.Write(information);
Statistics.AddFilesystem(plugin.XmlFsType.Type);
}
@@ -285,10 +305,11 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
DicConsole.DebugWriteLine("Analyze command", ex.StackTrace);
return (int)ErrorNumber.UnexpectedException;
return(int)ErrorNumber.UnexpectedException;
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -31,58 +31,56 @@
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class BenchmarkCommand : Command
internal class BenchmarkCommand : Command
{
int blockSize = 512;
int bufferSize = 128;
bool showHelp;
public BenchmarkCommand() : base("benchmark", "Benchmarks hashing and entropy calculation.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--block-size", "-b"
}, "Block size.")
{
Argument = new Argument<int>(() => 512), Required = false
});
Add(new Option(new[]
{
"--buffer-size", "-s"
}, "Buffer size in mebibytes.")
{
Argument = new Argument<int>(() => 128), Required = false
});
AddArgument(new Argument<string>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS]",
"",
Help,
{"block-size|b=", "Block size.", (int i) => blockSize = i},
{"buffer-size|s=", "Buffer size in mebibytes.", (int i) => bufferSize = i},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "Disc image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, int blockSize, int bufferSize)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("benchmark");
if(extra.Count != 0)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
DicConsole.DebugWriteLine("Benchmark command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Benchmark command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Benchmark command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Benchmark command", "--verbose={0}", verbose);
Benchmark.InitProgressEvent += Progress.InitProgress;
Benchmark.UpdateProgressEvent += Progress.UpdateProgress;
@@ -92,8 +90,10 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Took {0} seconds to fill buffer, {1:F3} MiB/sec.", results.FillTime,
results.FillSpeed);
DicConsole.WriteLine("Took {0} seconds to read buffer, {1:F3} MiB/sec.", results.ReadTime,
results.ReadSpeed);
DicConsole.WriteLine("Took {0} seconds to entropy buffer, {1:F3} MiB/sec.", results.EntropyTime,
results.EntropySpeed);
@@ -103,6 +103,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Took {0} seconds to do all algorithms at the same time, {1:F3} MiB/sec.",
results.TotalTime, results.TotalSpeed);
DicConsole.WriteLine("Took {0} seconds to do all algorithms sequentially, {1:F3} MiB/sec.",
results.SeparateTime, results.SeparateSpeed);
@@ -110,7 +111,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Max memory used is {0} bytes", results.MaxMemory);
DicConsole.WriteLine("Min memory used is {0} bytes", results.MinMemory);
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -32,121 +32,167 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
using Schemas;
namespace DiscImageChef.Commands
{
class ChecksumCommand : Command
internal class ChecksumCommand : Command
{
// How many sectors to read at once
const uint SECTORS_TO_READ = 256;
bool doAdler32 = true;
bool doCrc16 = true;
bool doCrc32 = true;
bool doCrc64;
bool doFletcher16;
bool doFletcher32;
bool doMd5 = true;
bool doSha1 = true;
bool doSha256;
bool doSha384;
bool doSha512;
bool doSpamSum = true;
string inputFile;
bool separatedTracks = true;
bool showHelp;
bool wholeDisc = true;
public ChecksumCommand() : base("checksum", "Checksums an image.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--adler32", "-a"
}, "Calculates Adler32.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option("--crc16", "Calculates CRC16.")
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"adler32|a", "Calculates Adler-32.", b => doAdler32 = b != null},
{"crc16", "Calculates CRC16.", b => doCrc16 = b != null},
{"crc32|c", "Calculates CRC32.", b => doCrc32 = b != null},
{"crc64", "Calculates CRC64 (ECMA).", b => doCrc64 = b != null},
{"fletcher16", "Calculates Fletcher-16.", b => doFletcher16 = b != null},
{"fletcher32", "Calculates Fletcher-32.", b => doFletcher32 = b != null},
{"md5|m", "Calculates MD5.", b => doMd5 = b != null},
{"separated-tracks|t", "Checksums each track separately.", b => separatedTracks = b != null},
{"sha1|s", "Calculates SHA1.", b => doSha1 = b != null},
{"sha256", "Calculates SHA256.", b => doSha256 = b != null},
{"sha384", "Calculates SHA384.", b => doSha384 = b != null},
{"sha512", "Calculates SHA512.", b => doSha512 = b != null},
{"spamsum|f", "Calculates SpamSum fuzzy hash.", b => doSpamSum = b != null},
{"whole-disc|w", "Checksums the whole disc.", b => wholeDisc = b != null},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--crc32", "-c"
}, "Calculates CRC32.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option("--crc64", "Calculates CRC64.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option("--fletcher16", "Calculates Fletcher-16.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option("--fletcher32", "Calculates Fletcher-32.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--md5", "-m"
}, "Calculates MD5.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--separated-tracks", "-t"
}, "Checksums each track separately.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--sha1", "-s"
}, "Calculates SHA1.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--sha256", "-a"
}, "Calculates SHA256.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option("--sha384", "Calculates SHA384.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option("--sha512", "Calculates SHA512.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--spamsum", "-f"
}, "Calculates SpamSum fuzzy hash.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--whole-disc", "-w"
}, "Checksums the whole disc.")
{
Argument = new Argument<bool>(() => true), Required = false
});
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, bool adler32, bool crc16, bool crc32, bool crc64, bool fletcher16,
bool fletcher32, bool md5, bool sha1, bool sha256, bool sha384, bool sha512, bool spamSum,
string imagePath, bool separatedTracks, bool wholeDisc)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("checksum");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("Checksum command", "--adler32={0}", doAdler32);
DicConsole.DebugWriteLine("Checksum command", "--crc16={0}", doCrc16);
DicConsole.DebugWriteLine("Checksum command", "--crc32={0}", doCrc32);
DicConsole.DebugWriteLine("Checksum command", "--crc64={0}", doCrc64);
DicConsole.DebugWriteLine("Checksum command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Checksum command", "--fletcher16={0}", doFletcher16);
DicConsole.DebugWriteLine("Checksum command", "--fletcher32={0}", doFletcher32);
DicConsole.DebugWriteLine("Checksum command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Checksum command", "--md5={0}", doMd5);
DicConsole.DebugWriteLine("Checksum command", "--adler32={0}", adler32);
DicConsole.DebugWriteLine("Checksum command", "--crc16={0}", crc16);
DicConsole.DebugWriteLine("Checksum command", "--crc32={0}", crc32);
DicConsole.DebugWriteLine("Checksum command", "--crc64={0}", crc64);
DicConsole.DebugWriteLine("Checksum command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Checksum command", "--fletcher16={0}", fletcher16);
DicConsole.DebugWriteLine("Checksum command", "--fletcher32={0}", fletcher32);
DicConsole.DebugWriteLine("Checksum command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Checksum command", "--md5={0}", md5);
DicConsole.DebugWriteLine("Checksum command", "--separated-tracks={0}", separatedTracks);
DicConsole.DebugWriteLine("Checksum command", "--sha1={0}", doSha1);
DicConsole.DebugWriteLine("Checksum command", "--sha256={0}", doSha256);
DicConsole.DebugWriteLine("Checksum command", "--sha384={0}", doSha384);
DicConsole.DebugWriteLine("Checksum command", "--sha512={0}", doSha512);
DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", doSpamSum);
DicConsole.DebugWriteLine("Checksum command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Checksum command", "--whole-disc={0}", wholeDisc);
DicConsole.DebugWriteLine("Checksum command", "--sha1={0}", sha1);
DicConsole.DebugWriteLine("Checksum command", "--sha256={0}", sha256);
DicConsole.DebugWriteLine("Checksum command", "--sha384={0}", sha384);
DicConsole.DebugWriteLine("Checksum command", "--sha512={0}", sha512);
DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", spamSum);
DicConsole.DebugWriteLine("Checksum command", "--verbose={0}", verbose);
DicConsole.DebugWriteLine("Checksum command", "--whole-disc={0}", wholeDisc);
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -154,27 +200,51 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
inputFormat.Open(inputFilter);
Statistics.AddMediaFormat(inputFormat.Format);
Statistics.AddMedia(inputFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
EnableChecksum enabledChecksums = new EnableChecksum();
var enabledChecksums = new EnableChecksum();
if(doAdler32) enabledChecksums |= EnableChecksum.Adler32;
if(doCrc16) enabledChecksums |= EnableChecksum.Crc16;
if(doCrc32) enabledChecksums |= EnableChecksum.Crc32;
if(doCrc64) enabledChecksums |= EnableChecksum.Crc64;
if(doMd5) enabledChecksums |= EnableChecksum.Md5;
if(doSha1) enabledChecksums |= EnableChecksum.Sha1;
if(doSha256) enabledChecksums |= EnableChecksum.Sha256;
if(doSha384) enabledChecksums |= EnableChecksum.Sha384;
if(doSha512) enabledChecksums |= EnableChecksum.Sha512;
if(doSpamSum) enabledChecksums |= EnableChecksum.SpamSum;
if(doFletcher16) enabledChecksums |= EnableChecksum.Fletcher16;
if(doFletcher32) enabledChecksums |= EnableChecksum.Fletcher32;
if(adler32)
enabledChecksums |= EnableChecksum.Adler32;
if(crc16)
enabledChecksums |= EnableChecksum.Crc16;
if(crc32)
enabledChecksums |= EnableChecksum.Crc32;
if(crc64)
enabledChecksums |= EnableChecksum.Crc64;
if(md5)
enabledChecksums |= EnableChecksum.Md5;
if(sha1)
enabledChecksums |= EnableChecksum.Sha1;
if(sha256)
enabledChecksums |= EnableChecksum.Sha256;
if(sha384)
enabledChecksums |= EnableChecksum.Sha384;
if(sha512)
enabledChecksums |= EnableChecksum.Sha512;
if(spamSum)
enabledChecksums |= EnableChecksum.SpamSum;
if(fletcher16)
enabledChecksums |= EnableChecksum.Fletcher16;
if(fletcher32)
enabledChecksums |= EnableChecksum.Fletcher32;
Checksum mediaChecksum = null;
@@ -185,11 +255,13 @@ namespace DiscImageChef.Commands
{
Checksum trackChecksum = null;
if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums);
if(wholeDisc)
mediaChecksum = new Checksum(enabledChecksums);
ulong previousTrackEnd = 0;
List<Track> inputTracks = opticalInput.Tracks;
foreach(Track currentTrack in inputTracks)
{
if(currentTrack.TrackStartSector - previousTrackEnd != 0 && wholeDisc)
@@ -207,9 +279,10 @@ namespace DiscImageChef.Commands
currentTrack.TrackSequence, currentTrack.TrackStartSector,
currentTrack.TrackEndSector);
if(separatedTracks) trackChecksum = new Checksum(enabledChecksums);
if(separatedTracks)
trackChecksum = new Checksum(enabledChecksums);
ulong sectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector + 1;
ulong sectors = (currentTrack.TrackEndSector - currentTrack.TrackStartSector) + 1;
ulong doneSectors = 0;
DicConsole.WriteLine("Track {0} has {1} sectors", currentTrack.TrackSequence, sectors);
@@ -221,22 +294,28 @@ namespace DiscImageChef.Commands
{
sector = opticalInput.ReadSectors(doneSectors, SECTORS_TO_READ,
currentTrack.TrackSequence);
DicConsole.Write("\rHashings sectors {0} to {2} of track {1}", doneSectors,
DicConsole.Write("\rHashing sectors {0} to {2} of track {1}", doneSectors,
currentTrack.TrackSequence, doneSectors + SECTORS_TO_READ);
doneSectors += SECTORS_TO_READ;
}
else
{
sector = opticalInput.ReadSectors(doneSectors, (uint)(sectors - doneSectors),
currentTrack.TrackSequence);
DicConsole.Write("\rHashings sectors {0} to {2} of track {1}", doneSectors,
DicConsole.Write("\rHashing sectors {0} to {2} of track {1}", doneSectors,
currentTrack.TrackSequence, doneSectors + (sectors - doneSectors));
doneSectors += sectors - doneSectors;
}
if(wholeDisc) mediaChecksum?.Update(sector);
if(wholeDisc)
mediaChecksum?.Update(sector);
if(separatedTracks) trackChecksum?.Update(sector);
if(separatedTracks)
trackChecksum?.Update(sector);
}
DicConsole.WriteLine();
@@ -266,8 +345,10 @@ namespace DiscImageChef.Commands
}
catch(Exception ex)
{
if(MainClass.Debug) DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message);
else DicConsole.WriteLine("Unable to get separate tracks, not checksumming them");
if(debug)
DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message);
else
DicConsole.WriteLine("Unable to get separate tracks, not checksumming them");
}
break;
@@ -276,7 +357,8 @@ namespace DiscImageChef.Commands
{
Checksum trackChecksum = null;
if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums);
if(wholeDisc)
mediaChecksum = new Checksum(enabledChecksums);
ulong previousTrackEnd = 0;
@@ -296,9 +378,10 @@ namespace DiscImageChef.Commands
"Track {0} starts at sector {1} and ends at block {2}",
currentFile.File, currentFile.FirstBlock, currentFile.LastBlock);
if(separatedTracks) trackChecksum = new Checksum(enabledChecksums);
if(separatedTracks)
trackChecksum = new Checksum(enabledChecksums);
ulong sectors = currentFile.LastBlock - currentFile.FirstBlock + 1;
ulong sectors = (currentFile.LastBlock - currentFile.FirstBlock) + 1;
ulong doneSectors = 0;
DicConsole.WriteLine("File {0} has {1} sectors", currentFile.File, sectors);
@@ -309,22 +392,28 @@ namespace DiscImageChef.Commands
if(sectors - doneSectors >= SECTORS_TO_READ)
{
sector = tapeImage.ReadSectors(doneSectors + currentFile.FirstBlock, SECTORS_TO_READ);
DicConsole.Write("\rHashings blocks {0} to {2} of file {1}", doneSectors,
DicConsole.Write("\rHashing blocks {0} to {2} of file {1}", doneSectors,
currentFile.File, doneSectors + SECTORS_TO_READ);
doneSectors += SECTORS_TO_READ;
}
else
{
sector = tapeImage.ReadSectors(doneSectors + currentFile.FirstBlock,
(uint)(sectors - doneSectors));
DicConsole.Write("\rHashings blocks {0} to {2} of file {1}", doneSectors,
DicConsole.Write("\rHashing blocks {0} to {2} of file {1}", doneSectors,
currentFile.File, doneSectors + (sectors - doneSectors));
doneSectors += sectors - doneSectors;
}
if(wholeDisc) mediaChecksum?.Update(sector);
if(wholeDisc)
mediaChecksum?.Update(sector);
if(separatedTracks) trackChecksum?.Update(sector);
if(separatedTracks)
trackChecksum?.Update(sector);
}
DicConsole.WriteLine();
@@ -350,6 +439,7 @@ namespace DiscImageChef.Commands
if(mediaChecksum != null)
foreach(ChecksumType chk in mediaChecksum.End())
DicConsole.WriteLine("Tape's {0}: {1}", chk.type, chk.Value);
break;
}
@@ -368,15 +458,19 @@ namespace DiscImageChef.Commands
if(sectors - doneSectors >= SECTORS_TO_READ)
{
sector = inputFormat.ReadSectors(doneSectors, SECTORS_TO_READ);
DicConsole.Write("\rHashings sectors {0} to {1}", doneSectors,
DicConsole.Write("\rHashing sectors {0} to {1}", doneSectors,
doneSectors + SECTORS_TO_READ);
doneSectors += SECTORS_TO_READ;
}
else
{
sector = inputFormat.ReadSectors(doneSectors, (uint)(sectors - doneSectors));
DicConsole.Write("\rHashings sectors {0} to {1}", doneSectors,
DicConsole.Write("\rHashing sectors {0} to {1}", doneSectors,
doneSectors + (sectors - doneSectors));
doneSectors += sectors - doneSectors;
}
@@ -387,11 +481,12 @@ namespace DiscImageChef.Commands
foreach(ChecksumType chk in mediaChecksum.End())
DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value);
break;
}
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -32,6 +32,8 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
@@ -39,81 +41,61 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
using ImageInfo = DiscImageChef.CommonTypes.Structs.ImageInfo;
namespace DiscImageChef.Commands
{
class CompareCommand : Command
internal class CompareCommand : Command
{
string inputFile1;
string inputFile2;
bool showHelp;
public CompareCommand() : base("compare", "Compares two disc images.")
{
Options = new OptionSet
AddArgument(new Argument<string>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} imagefile1 imagefile2",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "First media image path", Name = "image-path1"
});
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne, Description = "Second media image path", Name = "image-path2"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, string imagePath1, string imagePath2)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("compare");
if(extra.Count > 2)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
DicConsole.DebugWriteLine("Compare command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Compare command", "--input1={0}", imagePath1);
DicConsole.DebugWriteLine("Compare command", "--input2={0}", imagePath2);
DicConsole.DebugWriteLine("Compare command", "--verbose={0}", verbose);
if(extra.Count <= 1)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile1 = extra[0];
inputFile2 = extra[1];
DicConsole.DebugWriteLine("Compare command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Compare command", "--input1={0}", inputFile1);
DicConsole.DebugWriteLine("Compare command", "--input2={0}", inputFile2);
DicConsole.DebugWriteLine("Compare command", "--verbose={0}", MainClass.Verbose);
FiltersList filtersList = new FiltersList();
IFilter inputFilter1 = filtersList.GetFilter(inputFile1);
var filtersList = new FiltersList();
IFilter inputFilter1 = filtersList.GetFilter(imagePath1);
filtersList = new FiltersList();
IFilter inputFilter2 = filtersList.GetFilter(inputFile2);
IFilter inputFilter2 = filtersList.GetFilter(imagePath2);
if(inputFilter1 == null)
{
DicConsole.ErrorWriteLine("Cannot open input file 1");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
if(inputFilter2 == null)
{
DicConsole.ErrorWriteLine("Cannot open input file 2");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
IMediaImage input1Format = ImageFormat.Detect(inputFilter1);
@@ -122,24 +104,28 @@ namespace DiscImageChef.Commands
if(input1Format == null)
{
DicConsole.ErrorWriteLine("Input file 1 format not identified, not proceeding with comparison.");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("Input file 1 format identified by {0} ({1}).", input1Format.Name,
input1Format.Id);
else DicConsole.WriteLine("Input file 1 format identified by {0}.", input1Format.Name);
else
DicConsole.WriteLine("Input file 1 format identified by {0}.", input1Format.Name);
if(input2Format == null)
{
DicConsole.ErrorWriteLine("Input file 2 format not identified, not proceeding with comparison.");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("Input file 2 format identified by {0} ({1}).", input2Format.Name,
input2Format.Id);
else DicConsole.WriteLine("Input file 2 format identified by {0}.", input2Format.Name);
else
DicConsole.WriteLine("Input file 2 format identified by {0}.", input2Format.Name);
input1Format.Open(inputFilter1);
input2Format.Open(inputFilter2);
@@ -151,19 +137,19 @@ namespace DiscImageChef.Commands
Statistics.AddFilter(inputFilter1.Name);
Statistics.AddFilter(inputFilter2.Name);
StringBuilder sb = new StringBuilder();
var sb = new StringBuilder();
if(MainClass.Verbose)
if(verbose)
{
sb.AppendLine("\tDisc image 1\tDisc image 2");
sb.AppendLine("================================");
sb.AppendFormat("File\t{0}\t{1}", inputFile1, inputFile2).AppendLine();
sb.AppendFormat("File\t{0}\t{1}", imagePath1, imagePath2).AppendLine();
sb.AppendFormat("Disc image format\t{0}\t{1}", input1Format.Name, input2Format.Name).AppendLine();
}
else
{
sb.AppendFormat("Disc image 1: {0}", inputFile1).AppendLine();
sb.AppendFormat("Disc image 2: {0}", inputFile2).AppendLine();
sb.AppendFormat("Disc image 1: {0}", imagePath1).AppendLine();
sb.AppendFormat("Disc image 2: {0}", imagePath2).AppendLine();
}
bool imagesDiffer = false;
@@ -205,47 +191,66 @@ namespace DiscImageChef.Commands
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
}
if(MainClass.Verbose)
if(verbose)
{
sb.AppendFormat("Has partitions?\t{0}\t{1}", image1Info.HasPartitions, image2Info.HasPartitions)
.AppendLine();
sb.AppendFormat("Has partitions?\t{0}\t{1}", image1Info.HasPartitions, image2Info.HasPartitions).
AppendLine();
sb.AppendFormat("Has sessions?\t{0}\t{1}", image1Info.HasSessions, image2Info.HasSessions).AppendLine();
sb.AppendFormat("Image size\t{0}\t{1}", image1Info.ImageSize, image2Info.ImageSize).AppendLine();
sb.AppendFormat("Sectors\t{0}\t{1}", image1Info.Sectors, image2Info.Sectors).AppendLine();
sb.AppendFormat("Sector size\t{0}\t{1}", image1Info.SectorSize, image2Info.SectorSize).AppendLine();
sb.AppendFormat("Creation time\t{0}\t{1}", image1Info.CreationTime, image2Info.CreationTime)
.AppendLine();
sb.AppendFormat("Creation time\t{0}\t{1}", image1Info.CreationTime, image2Info.CreationTime).
AppendLine();
sb.AppendFormat("Last modification time\t{0}\t{1}", image1Info.LastModificationTime,
image2Info.LastModificationTime).AppendLine();
sb.AppendFormat("Disk type\t{0}\t{1}", image1Info.MediaType, image2Info.MediaType).AppendLine();
sb.AppendFormat("Image version\t{0}\t{1}", image1Info.Version, image2Info.Version).AppendLine();
sb.AppendFormat("Image application\t{0}\t{1}", image1Info.Application, image2Info.Application)
.AppendLine();
sb.AppendFormat("Image application\t{0}\t{1}", image1Info.Application, image2Info.Application).
AppendLine();
sb.AppendFormat("Image application version\t{0}\t{1}", image1Info.ApplicationVersion,
image2Info.ApplicationVersion).AppendLine();
sb.AppendFormat("Image creator\t{0}\t{1}", image1Info.Creator, image2Info.Creator).AppendLine();
sb.AppendFormat("Image name\t{0}\t{1}", image1Info.MediaTitle, image2Info.MediaTitle).AppendLine();
sb.AppendFormat("Image comments\t{0}\t{1}", image1Info.Comments, image2Info.Comments).AppendLine();
sb.AppendFormat("Disk manufacturer\t{0}\t{1}", image1Info.MediaManufacturer,
image2Info.MediaManufacturer).AppendLine();
sb.AppendFormat("Disk model\t{0}\t{1}", image1Info.MediaModel, image2Info.MediaModel).AppendLine();
sb.AppendFormat("Disk serial number\t{0}\t{1}", image1Info.MediaSerialNumber,
image2Info.MediaSerialNumber).AppendLine();
sb.AppendFormat("Disk barcode\t{0}\t{1}", image1Info.MediaBarcode, image2Info.MediaBarcode)
.AppendLine();
sb.AppendFormat("Disk part no.\t{0}\t{1}", image1Info.MediaPartNumber, image2Info.MediaPartNumber)
.AppendLine();
sb.AppendFormat("Disk sequence\t{0}\t{1}", image1Info.MediaSequence, image2Info.MediaSequence)
.AppendLine();
sb.AppendFormat("Disk barcode\t{0}\t{1}", image1Info.MediaBarcode, image2Info.MediaBarcode).
AppendLine();
sb.AppendFormat("Disk part no.\t{0}\t{1}", image1Info.MediaPartNumber, image2Info.MediaPartNumber).
AppendLine();
sb.AppendFormat("Disk sequence\t{0}\t{1}", image1Info.MediaSequence, image2Info.MediaSequence).
AppendLine();
sb.AppendFormat("Last disk on sequence\t{0}\t{1}", image1Info.LastMediaSequence,
image2Info.LastMediaSequence).AppendLine();
sb.AppendFormat("Drive manufacturer\t{0}\t{1}", image1Info.DriveManufacturer,
image2Info.DriveManufacturer).AppendLine();
sb.AppendFormat("Drive firmware revision\t{0}\t{1}", image1Info.DriveFirmwareRevision,
image2Info.DriveFirmwareRevision).AppendLine();
sb.AppendFormat("Drive model\t{0}\t{1}", image1Info.DriveModel, image2Info.DriveModel).AppendLine();
sb.AppendFormat("Drive serial number\t{0}\t{1}", image1Info.DriveSerialNumber,
image2Info.DriveSerialNumber).AppendLine();
foreach(MediaTagType disktag in Enum.GetValues(typeof(MediaTagType)))
sb.AppendFormat("Has {0}?\t{1}\t{2}", disktag, image1DiskTags.ContainsKey(disktag),
image2DiskTags.ContainsKey(disktag)).AppendLine();
@@ -256,58 +261,76 @@ namespace DiscImageChef.Commands
if(image1Info.HasPartitions != image2Info.HasPartitions)
{
imagesDiffer = true;
if(!MainClass.Verbose) sb.AppendLine("Image partitioned status differ");
if(!verbose)
sb.AppendLine("Image partitioned status differ");
}
if(image1Info.HasSessions != image2Info.HasSessions)
{
imagesDiffer = true;
if(!MainClass.Verbose) sb.AppendLine("Image session status differ");
if(!verbose)
sb.AppendLine("Image session status differ");
}
if(image1Info.Sectors != image2Info.Sectors)
{
imagesDiffer = true;
if(!MainClass.Verbose) sb.AppendLine("Image sectors differ");
if(!verbose)
sb.AppendLine("Image sectors differ");
}
if(image1Info.SectorSize != image2Info.SectorSize)
{
imagesDiffer = true;
if(!MainClass.Verbose) sb.AppendLine("Image sector size differ");
if(!verbose)
sb.AppendLine("Image sector size differ");
}
if(image1Info.MediaType != image2Info.MediaType)
{
imagesDiffer = true;
if(!MainClass.Verbose) sb.AppendLine("Disk type differ");
if(!verbose)
sb.AppendLine("Disk type differ");
}
ulong leastSectors;
if(image1Info.Sectors < image2Info.Sectors)
{
imagesDiffer = true;
leastSectors = image1Info.Sectors;
if(!MainClass.Verbose) sb.AppendLine("Image 2 has more sectors");
if(!verbose)
sb.AppendLine("Image 2 has more sectors");
}
else if(image1Info.Sectors > image2Info.Sectors)
{
imagesDiffer = true;
leastSectors = image2Info.Sectors;
if(!MainClass.Verbose) sb.AppendLine("Image 1 has more sectors");
if(!verbose)
sb.AppendLine("Image 1 has more sectors");
}
else leastSectors = image1Info.Sectors;
else
leastSectors = image1Info.Sectors;
DicConsole.WriteLine("Comparing sectors...");
for(ulong sector = 0; sector < leastSectors; sector++)
{
DicConsole.Write("\rComparing sector {0} of {1}...", sector + 1, leastSectors);
try
{
byte[] image1Sector = input1Format.ReadSector(sector);
byte[] image2Sector = input2Format.ReadSector(sector);
ArrayHelpers.CompareBytes(out bool different, out bool sameSize, image1Sector, image2Sector);
if(different)
{
imagesDiffer = true;
@@ -316,8 +339,9 @@ namespace DiscImageChef.Commands
else if(!sameSize)
{
imagesDiffer = true;
sb
.AppendFormat("Sector {0} has different sizes ({1} bytes in image 1, {2} in image 2) but are otherwise identical",
sb.
AppendFormat("Sector {0} has different sizes ({1} bytes in image 1, {2} in image 2) but are otherwise identical",
sector, image1Sector.LongLength, image2Sector.LongLength).AppendLine();
}
}
@@ -335,7 +359,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine(sb.ToString());
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -31,79 +31,65 @@
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Settings;
using Mono.Options;
namespace DiscImageChef.Commands
{
class ConfigureCommand : Command
internal class ConfigureCommand : Command
{
readonly bool gdprChange;
bool autoCall;
bool showHelp;
readonly bool _autoCall;
readonly bool _gdprChange;
public ConfigureCommand(bool gdprChange, bool autoCall) : base("configure",
"Configures user settings and statistics.")
{
this.gdprChange = gdprChange;
this.autoCall = autoCall;
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name}",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
_gdprChange = gdprChange;
_autoCall = autoCall;
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
int Invoke(bool debug, bool verbose)
{
if(!autoCall)
if(!_autoCall)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count != 0)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
}
if(gdprChange)
if(_gdprChange)
{
DicConsole.WriteLine("In compliance with the European Union General Data Protection Regulation 2016/679 (GDPR),\n" +
"we must give you the following information about DiscImageChef and ask if you want to opt-in\n" +
"in some information sharing.");
DicConsole.WriteLine();
DicConsole.WriteLine("Disclaimer: Because DiscImageChef is an open source software this information, and therefore,\n" +
"compliance with GDPR only holds true if you obtained a certificated copy from its original\n" +
"authors. In case of doubt, close DiscImageChef now and ask in our IRC support channel.");
DicConsole.WriteLine();
DicConsole.WriteLine("For any information sharing your IP address may be stored in our server, in a way that is not\n" +
"possible for any person, manual, or automated process, to link with your identity, unless\n" +
"specified otherwise.");
}
ConsoleKeyInfo pressedKey = new ConsoleKeyInfo();
var pressedKey = new ConsoleKeyInfo();
#region Device reports
DicConsole.WriteLine();
DicConsole.WriteLine(
"With the 'device-report' command, DiscImageChef creates a report of a device, that includes its\n" +
"manufacturer, model, firmware revision and/or version, attached bus, size, and supported commands.\n" +
@@ -113,7 +99,8 @@ namespace DiscImageChef.Commands
"of devices. A human-readable copy of the report in XML format is always created in the same directory\n" +
"where DiscImageChef is being run from.");
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to save device reports in shared folder of your computer? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -124,12 +111,15 @@ namespace DiscImageChef.Commands
pressedKey = new ConsoleKeyInfo();
DicConsole.WriteLine();
DicConsole.WriteLine("Sharing a report with us will send it to our server, that's in the european union territory, where it\n" +
"will be manually analized by an european union citizen to remove any trace of personal identification\n" +
"from it. Once that is done, it will be shared in our stats website, https://www.discimagechef.app\n" +
"will be manually analyzed by an european union citizen to remove any trace of personal identification\n" +
"from it. Once that is done, it will be shared in our stats website, https://www.discimagechef.app\n" +
"These report will be used to improve DiscImageChef support, and in some cases, to provide emulation of the\n" +
"devices to other open-source projects. In any case, no information linking the report to you will be stored.");
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to share your device reports with us? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -141,13 +131,16 @@ namespace DiscImageChef.Commands
#region Statistics
DicConsole.WriteLine();
DicConsole.WriteLine("DiscImageChef can store some usage statistics. These statistics are limited to the number of times a\n" +
"command is executed, a filesystem, partition, or device is used, the operating system version, and other.\n" +
"In no case, any information besides pure statistical usage numbers is stored, and they're just joint to the\n" +
"pool with no way of using them to identify you.");
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to save stats about your DiscImageChef usage? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -159,7 +152,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats = new StatsSettings();
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to share your stats anonymously? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -169,7 +164,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.ShareStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about benchmarks? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -179,7 +176,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.BenchmarkStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about command usage? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -189,7 +188,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.CommandStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about found devices? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -199,7 +200,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.DeviceStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about found filesystems? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -209,7 +212,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.FilesystemStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about found file filters? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -219,7 +224,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.FilterStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about found media image formats? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -229,7 +236,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.MediaImageStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about scanned media? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -239,7 +248,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.MediaScanStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about found partitioning schemes? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -249,7 +260,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.PartitionStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about media types? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -259,7 +272,9 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.MediaStats = pressedKey.Key == ConsoleKey.Y;
pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
while(pressedKey.Key != ConsoleKey.Y &&
pressedKey.Key != ConsoleKey.N)
{
DicConsole.Write("Do you want to gather statistics about media image verifications? (Y/N): ");
pressedKey = System.Console.ReadKey();
@@ -268,12 +283,14 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.Stats.VerifyStats = pressedKey.Key == ConsoleKey.Y;
}
else Settings.Settings.Current.Stats = null;
else
Settings.Settings.Current.Stats = null;
#endregion Statistics
Settings.Settings.Current.GdprCompliance = DicSettings.GdprLevel;
Settings.Settings.SaveSettings();
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -32,6 +32,8 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
@@ -42,235 +44,271 @@ using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
using Schemas;
using ImageInfo = DiscImageChef.CommonTypes.Structs.ImageInfo;
using Version = DiscImageChef.CommonTypes.Interop.Version;
namespace DiscImageChef.Commands
{
class ConvertImageCommand : Command
internal class ConvertImageCommand : Command
{
string cicmXml;
string comments;
int count = 64;
string creator;
string driveFirmwareRevision;
string driveManufacturer;
string driveModel;
string driveSerialNumber;
bool force;
string inputFile;
int lastMediaSequence;
string mediaBarcode;
string mediaManufacturer;
string mediaModel;
string mediaPartNumber;
int mediaSequence;
string mediaSerialNumber;
string mediaTitle;
string outputFile;
string outputOptions;
string resumeFile;
bool showHelp;
string wantedOutputFormat;
public ConvertImageCommand() : base("convert-image", "Converts one image to another format.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--cicm-xml", "-x"
}, "Take metadata from existing CICM XML sidecar.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--comments", "Image comments.")
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] inputimage outputimage",
"",
Help,
{"cicm-xml|x=", "Take metadata from existing CICM XML sidecar.", s => cicmXml = s},
{"comments=", "Image comments.", s => comments = s},
{"count|c=", "How many sectors to convert at once.", (int i) => count = i},
{"creator=", "Who (person) created the image?.", s => creator = s},
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option(new[]
{
"drive-manufacturer=",
"Manufacturer of the drive used to read the media represented by the image.",
s => driveManufacturer = s
},
"--count", "-c"
}, "How many sectors to convert at once.")
{
"drive-model=", "Model of the drive used to read the media represented by the image.",
s => driveModel = s
},
Argument = new Argument<int>(() => 64), Required = false
});
Add(new Option("--creator", "Who (person) created the image?.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--drive-manufacturer",
"Manufacturer of the drive used to read the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--drive-model", "Model of the drive used to read the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--drive-revision",
"Firmware revision of the drive used to read the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--drive-serial",
"Serial number of the drive used to read the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option(new[]
{
"drive-revision=",
"Firmware revision of the drive used to read the media represented by the image.",
s => driveFirmwareRevision = s
},
"--force", "-f"
}, "Continue conversion even if sector or media tags will be lost in the process.")
{
"drive-serial=", "Serial number of the drive used to read the media represented by the image.",
s => driveSerialNumber = s
},
Argument = new Argument<bool>(() => false), Required = false
});
Add(new Option(new[]
{
"--format", "-p"
},
"Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--media-barcode", "Barcode of the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--media-lastsequence",
"Last media of the sequence the media represented by the image corresponds to.")
{
Argument = new Argument<int>(() => 0), Required = false
});
Add(new Option("--media-manufacturer", "Manufacturer of the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--media-model", "Model of the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--media-partnumber", "Part number of the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--media-sequence", "Number in sequence for the media represented by the image.")
{
Argument = new Argument<int>(() => 0), Required = false
});
Add(new Option("--media-serial", "Serial number of the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--media-title", "Title of the media represented by the image.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option(new[]
{
"force|f", "Continue conversion even if sector or media tags will be lost in the process.",
b => force = b != null
},
"--options", "-O"
}, "Comma separated name=value pairs of options to pass to output image plugin.")
{
"format|p=",
"Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.",
s => wantedOutputFormat = s
},
{"media-barcode=", "Barcode of the media represented by the image.", s => mediaBarcode = s},
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option(new[]
{
"media-lastsequence=",
"Last media of the sequence the media represented by the image corresponds to.",
(int i) => lastMediaSequence = i
},
"--resume-file", "-r"
}, "Take list of dump hardware from existing resume file.")
{
"media-manufacturer=", "Manufacturer of the media represented by the image.",
s => mediaManufacturer = s
},
{"media-model=", "Model of the media represented by the image.", s => mediaModel = s},
{
"media-partnumber=", "Part number of the media represented by the image.",
s => mediaPartNumber = s
},
{
"media-sequence=", "Number in sequence for the media represented by the image.",
(int i) => mediaSequence = i
},
{
"media-serial=", "Serial number of the media represented by the image.",
s => mediaSerialNumber = s
},
{"media-title=", "Title of the media represented by the image.", s => mediaTitle = s},
{
"options|O=", "Comma separated name=value pairs of options to pass to output image plugin.",
s => outputOptions = s
},
{"resume-file|r=", "Take list of dump hardware from existing resume file.", s => resumeFile = s},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Argument = new Argument<string>(() => null), Required = false
});
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne, Description = "Input image path", Name = "input-path"
});
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne, Description = "Output image path", Name = "output-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool verbose, bool debug, string cicmXml, string comments, int count, string creator,
string driveFirmwareRevision, string driveManufacturer, string driveModel,
string driveSerialNumber, bool force, string inputPath, int lastMediaSequence,
string mediaBarcode, string mediaManufacturer, string mediaModel, string mediaPartNumber,
int mediaSequence, string mediaSerialNumber, string mediaTitle, string outputPath,
string outputOptions, string resumeFile, string format)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("convert-image");
if(extra.Count > 2)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count <= 1)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
outputFile = extra[1];
DicConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml);
DicConsole.DebugWriteLine("Analyze command", "--comments={0}", comments);
DicConsole.DebugWriteLine("Analyze command", "--count={0}", count);
DicConsole.DebugWriteLine("Analyze command", "--creator={0}", creator);
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml);
DicConsole.DebugWriteLine("Analyze command", "--comments={0}", comments);
DicConsole.DebugWriteLine("Analyze command", "--count={0}", count);
DicConsole.DebugWriteLine("Analyze command", "--creator={0}", creator);
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Analyze command", "--drive-manufacturer={0}", driveManufacturer);
DicConsole.DebugWriteLine("Analyze command", "--drive-model={0}", driveModel);
DicConsole.DebugWriteLine("Analyze command", "--drive-revision={0}", driveFirmwareRevision);
DicConsole.DebugWriteLine("Analyze command", "--drive-serial={0}", driveSerialNumber);
DicConsole.DebugWriteLine("Analyze command", "--force={0}", force);
DicConsole.DebugWriteLine("Analyze command", "--format={0}", wantedOutputFormat);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Analyze command", "--media-barcode={0}", mediaBarcode);
DicConsole.DebugWriteLine("Analyze command", "--drive-model={0}", driveModel);
DicConsole.DebugWriteLine("Analyze command", "--drive-revision={0}", driveFirmwareRevision);
DicConsole.DebugWriteLine("Analyze command", "--drive-serial={0}", driveSerialNumber);
DicConsole.DebugWriteLine("Analyze command", "--force={0}", force);
DicConsole.DebugWriteLine("Analyze command", "--format={0}", format);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputPath);
DicConsole.DebugWriteLine("Analyze command", "--media-barcode={0}", mediaBarcode);
DicConsole.DebugWriteLine("Analyze command", "--media-lastsequence={0}", lastMediaSequence);
DicConsole.DebugWriteLine("Analyze command", "--media-manufacturer={0}", mediaManufacturer);
DicConsole.DebugWriteLine("Analyze command", "--media-model={0}", mediaModel);
DicConsole.DebugWriteLine("Analyze command", "--media-partnumber={0}", mediaPartNumber);
DicConsole.DebugWriteLine("Analyze command", "--media-sequence={0}", mediaSequence);
DicConsole.DebugWriteLine("Analyze command", "--media-serial={0}", mediaSerialNumber);
DicConsole.DebugWriteLine("Analyze command", "--media-title={0}", mediaTitle);
DicConsole.DebugWriteLine("Analyze command", "--options={0}", outputOptions);
DicConsole.DebugWriteLine("Analyze command", "--output={0}", outputFile);
DicConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Analyze command", "--media-model={0}", mediaModel);
DicConsole.DebugWriteLine("Analyze command", "--media-partnumber={0}", mediaPartNumber);
DicConsole.DebugWriteLine("Analyze command", "--media-sequence={0}", mediaSequence);
DicConsole.DebugWriteLine("Analyze command", "--media-serial={0}", mediaSerialNumber);
DicConsole.DebugWriteLine("Analyze command", "--media-title={0}", mediaTitle);
DicConsole.DebugWriteLine("Analyze command", "--options={0}", outputOptions);
DicConsole.DebugWriteLine("Analyze command", "--output={0}", outputPath);
DicConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose);
Dictionary<string, string> parsedOptions = Core.Options.Parse(outputOptions);
DicConsole.DebugWriteLine("Analyze command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Analyze command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
if(count == 0)
{
DicConsole.ErrorWriteLine("Need to specify more than 0 sectors to copy at once");
return (int)ErrorNumber.InvalidArgument;
return(int)ErrorNumber.InvalidArgument;
}
Resume resume = null;
CICMMetadataType sidecar = null;
XmlSerializer xs = new XmlSerializer(typeof(CICMMetadataType));
var xs = new XmlSerializer(typeof(CICMMetadataType));
if(cicmXml != null)
if(File.Exists(cicmXml))
try
{
StreamReader sr = new StreamReader(cicmXml);
var sr = new StreamReader(cicmXml);
sidecar = (CICMMetadataType)xs.Deserialize(sr);
sr.Close();
}
catch
{
DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing...");
return (int)ErrorNumber.InvalidSidecar;
return(int)ErrorNumber.InvalidSidecar;
}
else
{
DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing...");
return (int)ErrorNumber.FileNotFound;
return(int)ErrorNumber.FileNotFound;
}
xs = new XmlSerializer(typeof(Resume));
if(resumeFile != null)
if(File.Exists(resumeFile))
try
{
StreamReader sr = new StreamReader(resumeFile);
var sr = new StreamReader(resumeFile);
resume = (Resume)xs.Deserialize(sr);
sr.Close();
}
catch
{
DicConsole.ErrorWriteLine("Incorrect resume file, not continuing...");
return (int)ErrorNumber.InvalidResume;
return(int)ErrorNumber.InvalidResume;
}
else
{
DicConsole.ErrorWriteLine("Could not find resume file, not continuing...");
return (int)ErrorNumber.FileNotFound;
return(int)ErrorNumber.FileNotFound;
}
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputPath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
if(File.Exists(outputFile))
if(File.Exists(outputPath))
{
DicConsole.ErrorWriteLine("Output file already exists, not continuing.");
return (int)ErrorNumber.DestinationExists;
return(int)ErrorNumber.DestinationExists;
}
PluginBase plugins = GetPluginBase.Instance;
@@ -279,13 +317,15 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.WriteLine("Input image format not identified, not proceeding with conversion.");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("Input image format identified by {0} ({1}).", inputFormat.Name,
inputFormat.Id);
else DicConsole.WriteLine("Input image format identified by {0}.", inputFormat.Name);
else
DicConsole.WriteLine("Input image format identified by {0}.", inputFormat.Name);
try
{
@@ -293,13 +333,17 @@ namespace DiscImageChef.Commands
{
DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given");
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
DicConsole.DebugWriteLine("Convert-image command", "Correctly opened image file.");
DicConsole.DebugWriteLine("Convert-image command", "Image without headers is {0} bytes.",
inputFormat.Info.ImageSize);
DicConsole.DebugWriteLine("Convert-image command", "Image has {0} sectors.", inputFormat.Info.Sectors);
DicConsole.DebugWriteLine("Convert-image command", "Image identifies media type as {0}.",
inputFormat.Info.MediaType);
@@ -312,85 +356,101 @@ namespace DiscImageChef.Commands
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
DicConsole.DebugWriteLine("Convert-image command", "Stack trace: {0}", ex.StackTrace);
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
List<IWritableImage> candidates = new List<IWritableImage>();
// Try extension
if(string.IsNullOrEmpty(wantedOutputFormat))
if(string.IsNullOrEmpty(format))
candidates.AddRange(plugins.WritableImages.Values.Where(t =>
t.KnownExtensions
.Contains(Path.GetExtension(outputFile))));
t.KnownExtensions.
Contains(Path.GetExtension(outputPath))));
// Try Id
else if(Guid.TryParse(wantedOutputFormat, out Guid outId))
else if(Guid.TryParse(format, out Guid outId))
candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId)));
// Try name
else
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, wantedOutputFormat,
StringComparison
.InvariantCultureIgnoreCase)));
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, format,
StringComparison.
InvariantCultureIgnoreCase)));
if(candidates.Count == 0)
{
DicConsole.WriteLine("No plugin supports requested extension.");
return (int)ErrorNumber.FormatNotFound;
return(int)ErrorNumber.FormatNotFound;
}
if(candidates.Count > 1)
{
DicConsole.WriteLine("More than one plugin supports requested extension.");
return (int)ErrorNumber.TooManyFormats;
return(int)ErrorNumber.TooManyFormats;
}
IWritableImage outputFormat = candidates[0];
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id);
else DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name);
else
DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name);
if(!outputFormat.SupportedMediaTypes.Contains(inputFormat.Info.MediaType))
{
DicConsole.ErrorWriteLine("Output format does not support media type, cannot continue...");
return (int)ErrorNumber.UnsupportedMedia;
return(int)ErrorNumber.UnsupportedMedia;
}
foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags)
{
if(outputFormat.SupportedMediaTags.Contains(mediaTag) || force) continue;
if(outputFormat.SupportedMediaTags.Contains(mediaTag) || force)
continue;
DicConsole.ErrorWriteLine("Converting image will lose media tag {0}, not continuing...", mediaTag);
DicConsole.ErrorWriteLine("If you don't care, use force option.");
return (int)ErrorNumber.DataWillBeLost;
return(int)ErrorNumber.DataWillBeLost;
}
bool useLong = inputFormat.Info.ReadableSectorTags.Count != 0;
foreach(SectorTagType sectorTag in inputFormat.Info.ReadableSectorTags)
{
if(outputFormat.SupportedSectorTags.Contains(sectorTag)) continue;
if(outputFormat.SupportedSectorTags.Contains(sectorTag))
continue;
if(force)
{
if(sectorTag != SectorTagType.CdTrackFlags && sectorTag != SectorTagType.CdTrackIsrc &&
sectorTag != SectorTagType.CdSectorSubchannel) useLong = false;
if(sectorTag != SectorTagType.CdTrackFlags &&
sectorTag != SectorTagType.CdTrackIsrc &&
sectorTag != SectorTagType.CdSectorSubchannel)
useLong = false;
continue;
}
DicConsole.ErrorWriteLine("Converting image will lose sector tag {0}, not continuing...", sectorTag);
DicConsole
.ErrorWriteLine("If you don't care, use force option. This will skip all sector tags converting only user data.");
return (int)ErrorNumber.DataWillBeLost;
DicConsole.
ErrorWriteLine("If you don't care, use force option. This will skip all sector tags converting only user data.");
return(int)ErrorNumber.DataWillBeLost;
}
if(!outputFormat.Create(outputFile, inputFormat.Info.MediaType, parsedOptions, inputFormat.Info.Sectors,
if(!outputFormat.Create(outputPath, inputFormat.Info.MediaType, parsedOptions, inputFormat.Info.Sectors,
inputFormat.Info.SectorSize))
{
DicConsole.ErrorWriteLine("Error {0} creating output image.", outputFormat.ErrorMessage);
return (int)ErrorNumber.CannotCreateFormat;
return(int)ErrorNumber.CannotCreateFormat;
}
ImageInfo metadata = new ImageInfo
var metadata = new ImageInfo
{
Application = "DiscImageChef",
ApplicationVersion = Version.GetVersion(),
@@ -413,10 +473,12 @@ namespace DiscImageChef.Commands
if(!outputFormat.SetMetadata(metadata))
{
DicConsole.ErrorWrite("Error {0} setting metadata, ", outputFormat.ErrorMessage);
if(!force)
{
DicConsole.ErrorWriteLine("not continuing...");
return (int)ErrorNumber.WriteError;
return(int)ErrorNumber.WriteError;
}
DicConsole.ErrorWriteLine("continuing...");
@@ -427,11 +489,14 @@ namespace DiscImageChef.Commands
foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags)
{
if(force && !outputFormat.SupportedMediaTags.Contains(mediaTag)) continue;
if(force && !outputFormat.SupportedMediaTags.Contains(mediaTag))
continue;
DicConsole.WriteLine("Converting media tag {0}", mediaTag);
byte[] tag = inputFormat.ReadDiskTag(mediaTag);
if(outputFormat.WriteMediaTag(tag, mediaTag)) continue;
if(outputFormat.WriteMediaTag(tag, mediaTag))
continue;
if(force)
DicConsole.ErrorWriteLine("Error {0} writing media tag, continuing...", outputFormat.ErrorMessage);
@@ -439,35 +504,41 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Error {0} writing media tag, not continuing...",
outputFormat.ErrorMessage);
return (int)ErrorNumber.WriteError;
return(int)ErrorNumber.WriteError;
}
}
DicConsole.WriteLine("{0} sectors to convert", inputFormat.Info.Sectors);
ulong doneSectors = 0;
if(inputFormat is IOpticalMediaImage inputOptical && outputFormat is IWritableOpticalImage outputOptical &&
if(inputFormat is IOpticalMediaImage inputOptical &&
outputFormat is IWritableOpticalImage outputOptical &&
inputOptical.Tracks != null)
{
if(!outputOptical.SetTracks(inputOptical.Tracks))
{
DicConsole.ErrorWriteLine("Error {0} sending tracks list to output image.",
outputFormat.ErrorMessage);
return (int)ErrorNumber.WriteError;
return(int)ErrorNumber.WriteError;
}
foreach(Track track in inputOptical.Tracks)
{
doneSectors = 0;
ulong trackSectors = track.TrackEndSector - track.TrackStartSector + 1;
ulong trackSectors = (track.TrackEndSector - track.TrackStartSector) + 1;
while(doneSectors < trackSectors)
{
byte[] sector;
uint sectorsToDo;
if(trackSectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
else sectorsToDo = (uint)(trackSectors - doneSectors);
if(trackSectors - doneSectors >= (ulong)count)
sectorsToDo = (uint)count;
else
sectorsToDo = (uint)(trackSectors - doneSectors);
DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)",
doneSectors + track.TrackStartSector,
@@ -476,6 +547,7 @@ namespace DiscImageChef.Commands
track.TrackSequence);
bool result;
if(useLong)
if(sectorsToDo == 1)
{
@@ -485,6 +557,7 @@ namespace DiscImageChef.Commands
else
{
sector = inputFormat.ReadSectorsLong(doneSectors + track.TrackStartSector, sectorsToDo);
result = outputFormat.WriteSectorsLong(sector, doneSectors + track.TrackStartSector,
sectorsToDo);
}
@@ -498,6 +571,7 @@ namespace DiscImageChef.Commands
else
{
sector = inputFormat.ReadSectors(doneSectors + track.TrackStartSector, sectorsToDo);
result = outputFormat.WriteSectors(sector, doneSectors + track.TrackStartSector,
sectorsToDo);
}
@@ -511,7 +585,8 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors);
return (int)ErrorNumber.WriteError;
return(int)ErrorNumber.WriteError;
}
doneSectors += sectorsToDo;
@@ -520,11 +595,13 @@ namespace DiscImageChef.Commands
DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)", inputFormat.Info.Sectors,
inputFormat.Info.Sectors, 1.0, inputOptical.Tracks.Count);
DicConsole.WriteLine();
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.OrderBy(t => t))
{
if(!useLong) break;
if(!useLong)
break;
switch(tag)
{
@@ -540,12 +617,13 @@ namespace DiscImageChef.Commands
continue;
}
if(force && !outputFormat.SupportedSectorTags.Contains(tag)) continue;
if(force && !outputFormat.SupportedSectorTags.Contains(tag))
continue;
foreach(Track track in inputOptical.Tracks)
{
doneSectors = 0;
ulong trackSectors = track.TrackEndSector - track.TrackStartSector + 1;
ulong trackSectors = (track.TrackEndSector - track.TrackStartSector) + 1;
byte[] sector;
bool result;
@@ -556,8 +634,10 @@ namespace DiscImageChef.Commands
DicConsole.Write("\rConverting tag {0} in track {1} ({2:P2} done).", tag,
track.TrackSequence,
track.TrackSequence / (double)inputOptical.Tracks.Count);
sector = inputFormat.ReadSectorTag(track.TrackStartSector, tag);
result = outputFormat.WriteSectorTag(sector, track.TrackStartSector, tag);
if(!result)
if(force)
DicConsole.ErrorWriteLine("Error {0} writing tag, continuing...",
@@ -566,7 +646,8 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Error {0} writing tag, not continuing...",
outputFormat.ErrorMessage);
return (int)ErrorNumber.WriteError;
return(int)ErrorNumber.WriteError;
}
continue;
@@ -575,10 +656,11 @@ namespace DiscImageChef.Commands
while(doneSectors < trackSectors)
{
uint sectorsToDo;
if(trackSectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
if(trackSectors - doneSectors >= (ulong)count)
sectorsToDo = (uint)count;
else
sectorsToDo =
(uint)(trackSectors - doneSectors);
sectorsToDo = (uint)(trackSectors - doneSectors);
DicConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)",
doneSectors + track.TrackStartSector,
@@ -595,6 +677,7 @@ namespace DiscImageChef.Commands
{
sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo,
tag);
result = outputFormat.WriteSectorsTag(sector, doneSectors + track.TrackStartSector,
sectorsToDo, tag);
}
@@ -607,7 +690,8 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors);
return (int)ErrorNumber.WriteError;
return(int)ErrorNumber.WriteError;
}
doneSectors += sectorsToDo;
@@ -620,11 +704,13 @@ namespace DiscImageChef.Commands
case SectorTagType.CdTrackIsrc:
DicConsole.Write("\rConverting tag {0} in track {1} ({2:P2} done).", tag,
inputOptical.Tracks.Count, 1.0);
break;
default:
DicConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)",
inputFormat.Info.Sectors, inputFormat.Info.Sectors, 1.0,
inputOptical.Tracks.Count, tag);
break;
}
@@ -636,6 +722,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Setting geometry to {0} cylinders, {1} heads and {2} sectors per track",
inputFormat.Info.Cylinders, inputFormat.Info.Heads,
inputFormat.Info.SectorsPerTrack);
if(!outputFormat.SetGeometry(inputFormat.Info.Cylinders, inputFormat.Info.Heads,
inputFormat.Info.SectorsPerTrack))
DicConsole.ErrorWriteLine("Error {0} setting geometry, image may be incorrect, continuing...",
@@ -646,15 +733,17 @@ namespace DiscImageChef.Commands
byte[] sector;
uint sectorsToDo;
if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
if(inputFormat.Info.Sectors - doneSectors >= (ulong)count)
sectorsToDo = (uint)count;
else
sectorsToDo =
(uint)(inputFormat.Info.Sectors - doneSectors);
sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors);
DicConsole.Write("\rConverting sectors {0} to {1} ({2:P2} done)", doneSectors,
doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors);
bool result;
if(useLong)
if(sectorsToDo == 1)
{
@@ -688,7 +777,8 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors);
return (int)ErrorNumber.WriteError;
return(int)ErrorNumber.WriteError;
}
doneSectors += sectorsToDo;
@@ -696,11 +786,13 @@ namespace DiscImageChef.Commands
DicConsole.Write("\rConverting sectors {0} to {1} ({2:P2} done)", inputFormat.Info.Sectors,
inputFormat.Info.Sectors, 1.0);
DicConsole.WriteLine();
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags)
{
if(!useLong) break;
if(!useLong)
break;
switch(tag)
{
@@ -716,24 +808,28 @@ namespace DiscImageChef.Commands
continue;
}
if(force && !outputFormat.SupportedSectorTags.Contains(tag)) continue;
if(force && !outputFormat.SupportedSectorTags.Contains(tag))
continue;
doneSectors = 0;
while(doneSectors < inputFormat.Info.Sectors)
{
byte[] sector;
uint sectorsToDo;
if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
if(inputFormat.Info.Sectors - doneSectors >= (ulong)count)
sectorsToDo = (uint)count;
else
sectorsToDo =
(uint)(inputFormat.Info.Sectors - doneSectors);
sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors);
DicConsole.Write("\rConverting tag {2} for sectors {0} to {1} ({2:P2} done)", doneSectors,
doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors,
tag);
bool result;
if(sectorsToDo == 1)
{
sector = inputFormat.ReadSectorTag(doneSectors, tag);
@@ -753,7 +849,8 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors);
return (int)ErrorNumber.WriteError;
return(int)ErrorNumber.WriteError;
}
doneSectors += sectorsToDo;
@@ -761,24 +858,37 @@ namespace DiscImageChef.Commands
DicConsole.Write("\rConverting tag {2} for sectors {0} to {1} ({2:P2} done)",
inputFormat.Info.Sectors, inputFormat.Info.Sectors, 1.0, tag);
DicConsole.WriteLine();
}
}
bool ret = false;
if(resume != null || dumpHardware != null)
if(resume != null ||
dumpHardware != null)
{
if(resume != null) ret = outputFormat.SetDumpHardware(resume.Tries);
else if(dumpHardware != null) ret = outputFormat.SetDumpHardware(dumpHardware);
if(ret) DicConsole.WriteLine("Written dump hardware list to output image.");
if(resume != null)
ret = outputFormat.SetDumpHardware(resume.Tries);
else if(dumpHardware != null)
ret = outputFormat.SetDumpHardware(dumpHardware);
if(ret)
DicConsole.WriteLine("Written dump hardware list to output image.");
}
ret = false;
if(sidecar != null || cicmMetadata != null)
if(sidecar != null ||
cicmMetadata != null)
{
if(sidecar != null) ret = outputFormat.SetCicmMetadata(sidecar);
else if(cicmMetadata != null) ret = outputFormat.SetCicmMetadata(cicmMetadata);
if(ret) DicConsole.WriteLine("Written CICM XML metadata to output image.");
if(sidecar != null)
ret = outputFormat.SetCicmMetadata(sidecar);
else if(cicmMetadata != null)
ret = outputFormat.SetCicmMetadata(cicmMetadata);
if(ret)
DicConsole.WriteLine("Written CICM XML metadata to output image.");
}
DicConsole.WriteLine("Closing output image.");
@@ -790,7 +900,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine();
DicConsole.WriteLine("Conversion done.");
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -32,6 +32,8 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Linq;
using System.Text;
@@ -41,109 +43,109 @@ using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
using Schemas;
namespace DiscImageChef.Commands
{
class CreateSidecarCommand : Command
internal class CreateSidecarCommand : Command
{
uint blockSize;
string encodingName;
string inputFile;
bool showHelp;
bool tape;
public CreateSidecarCommand() : base("create-sidecar", "Creates CICM Metadata XML sidecar.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--block-size", "-b"
},
"Only used for tapes, indicates block size. Files in the folder whose size is not a multiple of this value will simply be ignored.")
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] input",
"",
Help,
Argument = new Argument<int>(() => 512), Required = false
});
Add(new Option(new[]
{
"block-size|b=",
"Only used for tapes, indicates block size. Files in the folder whose size is not a multiple of this value will simply be ignored.",
(uint i) => blockSize = i
},
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
"--encoding", "-e"
}, "Name of character encoding to use.")
{
"tape|t",
"When used indicates that input is a folder containing alphabetically sorted files extracted from a linear block-based tape with fixed block size (e.g. a SCSI tape device).",
b => tape = b != null
},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option(new[]
{
"--encoding", "-e"
}, "Name of character encoding to use.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option(new[]
{
"--tape", "-t"
},
"When used indicates that input is a folder containing alphabetically sorted files extracted from a linear block-based tape with fixed block size (e.g. a SCSI tape device).")
{
Argument = new Argument<bool>(() => false), Required = false
});
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, uint blockSize, string encodingName, string imagePath, bool tape)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("create-sidecar");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("Create sidecar command", "--block-size={0}", blockSize);
DicConsole.DebugWriteLine("Create sidecar command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Create sidecar command", "--encoding={0}", encodingName);
DicConsole.DebugWriteLine("Create sidecar command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Create sidecar command", "--tape={0}", tape);
DicConsole.DebugWriteLine("Create sidecar command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Create sidecar command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Create sidecar command", "--encoding={0}", encodingName);
DicConsole.DebugWriteLine("Create sidecar command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Create sidecar command", "--tape={0}", tape);
DicConsole.DebugWriteLine("Create sidecar command", "--verbose={0}", verbose);
Encoding encoding = null;
Encoding encodingClass = null;
if(encodingName != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(verbose)
DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
}
catch(ArgumentException)
{
DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return (int)ErrorNumber.EncodingUnknown;
return(int)ErrorNumber.EncodingUnknown;
}
if(File.Exists(inputFile))
if(File.Exists(imagePath))
{
if(tape)
{
DicConsole.ErrorWriteLine("You cannot use --tape option when input is a file.");
return (int)ErrorNumber.ExpectedDirectory;
return(int)ErrorNumber.ExpectedDirectory;
}
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
try
@@ -153,13 +155,15 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
imageFormat.Id);
else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
else
DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
try
{
@@ -167,7 +171,8 @@ namespace DiscImageChef.Commands
{
DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given");
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
DicConsole.DebugWriteLine("Analyze command", "Correctly opened image file.");
@@ -176,13 +181,14 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
Statistics.AddMediaFormat(imageFormat.Format);
Statistics.AddFilter(inputFilter.Name);
Sidecar sidecarClass = new Sidecar(imageFormat, inputFile, inputFilter.Id, encoding);
var sidecarClass = new Sidecar(imageFormat, imagePath, inputFilter.Id, encodingClass);
sidecarClass.InitProgressEvent += Progress.InitProgress;
sidecarClass.UpdateProgressEvent += Progress.UpdateProgress;
sidecarClass.EndProgressEvent += Progress.EndProgress;
@@ -190,21 +196,23 @@ namespace DiscImageChef.Commands
sidecarClass.UpdateProgressEvent2 += Progress.UpdateProgress2;
sidecarClass.EndProgressEvent2 += Progress.EndProgress2;
sidecarClass.UpdateStatusEvent += Progress.UpdateStatus;
System.Console.CancelKeyPress += (sender, e) =>
{
e.Cancel = true;
sidecarClass.Abort();
};
CICMMetadataType sidecar = sidecarClass.Create();
DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs =
var xmlFs =
new
FileStream(Path.Combine(Path.GetDirectoryName(inputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(inputFile) + ".cicm.xml"),
FileStream(Path.Combine(Path.GetDirectoryName(imagePath) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(imagePath) + ".cicm.xml"),
FileMode.CreateNew);
XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close();
}
@@ -212,23 +220,25 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
DicConsole.DebugWriteLine("Analyze command", ex.StackTrace);
return (int)ErrorNumber.UnexpectedException;
return(int)ErrorNumber.UnexpectedException;
}
}
else if(Directory.Exists(inputFile))
else if(Directory.Exists(imagePath))
{
if(!tape)
{
DicConsole.ErrorWriteLine("Cannot create a sidecar from a directory.");
return (int)ErrorNumber.ExpectedFile;
return(int)ErrorNumber.ExpectedFile;
}
string[] contents = Directory.GetFiles(inputFile, "*", SearchOption.TopDirectoryOnly);
string[] contents = Directory.GetFiles(imagePath, "*", SearchOption.TopDirectoryOnly);
List<string> files = contents.Where(file => new FileInfo(file).Length % blockSize == 0).ToList();
files.Sort(StringComparer.CurrentCultureIgnoreCase);
Sidecar sidecarClass = new Sidecar();
var sidecarClass = new Sidecar();
sidecarClass.InitProgressEvent += Progress.InitProgress;
sidecarClass.UpdateProgressEvent += Progress.UpdateProgress;
sidecarClass.EndProgressEvent += Progress.EndProgress;
@@ -236,22 +246,23 @@ namespace DiscImageChef.Commands
sidecarClass.UpdateProgressEvent2 += Progress.UpdateProgress2;
sidecarClass.EndProgressEvent2 += Progress.EndProgress2;
sidecarClass.UpdateStatusEvent += Progress.UpdateStatus;
CICMMetadataType sidecar = sidecarClass.BlockTape(Path.GetFileName(inputFile), files, blockSize);
CICMMetadataType sidecar = sidecarClass.BlockTape(Path.GetFileName(imagePath), files, blockSize);
DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs =
var xmlFs =
new
FileStream(Path.Combine(Path.GetDirectoryName(inputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(inputFile) + ".cicm.xml"),
FileStream(Path.Combine(Path.GetDirectoryName(imagePath) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(imagePath) + ".cicm.xml"),
FileMode.CreateNew);
XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close();
}
else DicConsole.ErrorWriteLine("The specified input file cannot be found.");
else
DicConsole.ErrorWriteLine("The specified input file cannot be found.");
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -30,7 +30,8 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
@@ -39,81 +40,82 @@ using DiscImageChef.Core;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.CD;
using DiscImageChef.Decoders.SCSI;
using Mono.Options;
namespace DiscImageChef.Commands
{
class DecodeCommand : Command
internal class DecodeCommand : Command
{
bool diskTags = true;
string inputFile;
string length = "all";
bool sectorTags = true;
bool showHelp;
ulong startSector;
public DecodeCommand() : base("decode", "Decodes and pretty prints disk and/or sector tags.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--disk-tags", "-f"
}, "Decode disk tags.")
{
Argument = new Argument<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>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"disk-tags|f", "Decode disk tags.", b => diskTags = b != null},
{"length|l=", "How many sectors to decode, or \"all\".", s => length = s},
{"sector-tags|p", "Decode sector tags.", b => sectorTags = b != null},
{"start|s=", "Name of character encoding to use.", (ulong ul) => startSector = ul},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool verbose, bool debug, bool diskTags, string imagePath, string length, bool sectorTags,
ulong startSector)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("decode");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("Decode command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", diskTags);
DicConsole.DebugWriteLine("Decode command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Decode command", "--length={0}", length);
DicConsole.DebugWriteLine("Decode command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", diskTags);
DicConsole.DebugWriteLine("Decode command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Decode command", "--length={0}", length);
DicConsole.DebugWriteLine("Decode command", "--sector-tags={0}", sectorTags);
DicConsole.DebugWriteLine("Decode command", "--start={0}", startSector);
DicConsole.DebugWriteLine("Decode command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Decode command", "--start={0}", startSector);
DicConsole.DebugWriteLine("Decode command", "--verbose={0}", verbose);
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -121,7 +123,8 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not decoding");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
inputFormat.Open(inputFilter);
@@ -139,16 +142,20 @@ namespace DiscImageChef.Commands
case MediaTagType.SCSI_INQUIRY:
{
byte[] inquiry = inputFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY);
if(inquiry == null)
DicConsole.WriteLine("Error reading SCSI INQUIRY response from disc image");
else
{
DicConsole.WriteLine("SCSI INQUIRY command response:");
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(Inquiry.Prettify(inquiry));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
}
break;
@@ -156,16 +163,20 @@ namespace DiscImageChef.Commands
case MediaTagType.ATA_IDENTIFY:
{
byte[] identify = inputFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY);
if(identify == null)
DicConsole.WriteLine("Error reading ATA IDENTIFY DEVICE response from disc image");
else
{
DicConsole.WriteLine("ATA IDENTIFY DEVICE command response:");
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(Identify.Prettify(identify));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
}
break;
@@ -173,17 +184,21 @@ namespace DiscImageChef.Commands
case MediaTagType.ATAPI_IDENTIFY:
{
byte[] identify = inputFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY);
if(identify == null)
DicConsole
.WriteLine("Error reading ATA IDENTIFY PACKET DEVICE response from disc image");
DicConsole.
WriteLine("Error reading ATA IDENTIFY PACKET DEVICE response from disc image");
else
{
DicConsole.WriteLine("ATA IDENTIFY PACKET DEVICE command response:");
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(Identify.Prettify(identify));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
}
break;
@@ -191,31 +206,41 @@ namespace DiscImageChef.Commands
case MediaTagType.CD_ATIP:
{
byte[] atip = inputFormat.ReadDiskTag(MediaTagType.CD_ATIP);
if(atip == null) DicConsole.WriteLine("Error reading CD ATIP from disc image");
if(atip == null)
DicConsole.WriteLine("Error reading CD ATIP from disc image");
else
{
DicConsole.WriteLine("CD ATIP:");
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(ATIP.Prettify(atip));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
}
break;
}
case MediaTagType.CD_FullTOC:
{
byte[] fulltoc = inputFormat.ReadDiskTag(MediaTagType.CD_FullTOC);
if(fulltoc == null) DicConsole.WriteLine("Error reading CD full TOC from disc image");
byte[] fullToc = inputFormat.ReadDiskTag(MediaTagType.CD_FullTOC);
if(fullToc == null)
DicConsole.WriteLine("Error reading CD full TOC from disc image");
else
{
DicConsole.WriteLine("CD full TOC:");
DicConsole
.WriteLine("================================================================================");
DicConsole.WriteLine(FullTOC.Prettify(fulltoc));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(FullTOC.Prettify(fullToc));
DicConsole.
WriteLine("================================================================================");
}
break;
@@ -223,48 +248,62 @@ namespace DiscImageChef.Commands
case MediaTagType.CD_PMA:
{
byte[] pma = inputFormat.ReadDiskTag(MediaTagType.CD_PMA);
if(pma == null) DicConsole.WriteLine("Error reading CD PMA from disc image");
if(pma == null)
DicConsole.WriteLine("Error reading CD PMA from disc image");
else
{
DicConsole.WriteLine("CD PMA:");
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(PMA.Prettify(pma));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
}
break;
}
case MediaTagType.CD_SessionInfo:
{
byte[] sessioninfo = inputFormat.ReadDiskTag(MediaTagType.CD_SessionInfo);
if(sessioninfo == null)
byte[] sessionInfo = inputFormat.ReadDiskTag(MediaTagType.CD_SessionInfo);
if(sessionInfo == null)
DicConsole.WriteLine("Error reading CD session information from disc image");
else
{
DicConsole.WriteLine("CD session information:");
DicConsole
.WriteLine("================================================================================");
DicConsole.WriteLine(Session.Prettify(sessioninfo));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(Session.Prettify(sessionInfo));
DicConsole.
WriteLine("================================================================================");
}
break;
}
case MediaTagType.CD_TEXT:
{
byte[] cdtext = inputFormat.ReadDiskTag(MediaTagType.CD_TEXT);
if(cdtext == null) DicConsole.WriteLine("Error reading CD-TEXT from disc image");
byte[] cdText = inputFormat.ReadDiskTag(MediaTagType.CD_TEXT);
if(cdText == null)
DicConsole.WriteLine("Error reading CD-TEXT from disc image");
else
{
DicConsole.WriteLine("CD-TEXT:");
DicConsole
.WriteLine("================================================================================");
DicConsole.WriteLine(CDTextOnLeadIn.Prettify(cdtext));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(CDTextOnLeadIn.Prettify(cdText));
DicConsole.
WriteLine("================================================================================");
}
break;
@@ -272,15 +311,20 @@ namespace DiscImageChef.Commands
case MediaTagType.CD_TOC:
{
byte[] toc = inputFormat.ReadDiskTag(MediaTagType.CD_TOC);
if(toc == null) DicConsole.WriteLine("Error reading CD TOC from disc image");
if(toc == null)
DicConsole.WriteLine("Error reading CD TOC from disc image");
else
{
DicConsole.WriteLine("CD TOC:");
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
DicConsole.WriteLine(TOC.Prettify(toc));
DicConsole
.WriteLine("================================================================================");
DicConsole.
WriteLine("================================================================================");
}
break;
@@ -288,6 +332,7 @@ namespace DiscImageChef.Commands
default:
DicConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.",
tag);
break;
}
@@ -300,6 +345,7 @@ namespace DiscImageChef.Commands
{
DicConsole.WriteLine("Value \"{0}\" is not a valid number for length.", length);
DicConsole.WriteLine("Not decoding sectors tags");
return 3;
}
}
@@ -313,13 +359,14 @@ namespace DiscImageChef.Commands
default:
DicConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.",
tag);
break;
}
// TODO: Not implemented
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -31,6 +31,8 @@
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
@@ -40,72 +42,46 @@ using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Decoders.SCSI.SSC;
using DiscImageChef.Devices;
using Mono.Options;
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
namespace DiscImageChef.Commands
{
internal class DeviceInfoCommand : Command
{
string devicePath;
string outputPrefix;
bool showHelp;
public DeviceInfoCommand() : base("device-info", "Gets information about a device.") => Options = new OptionSet
public DeviceInfoCommand() : base("device-info", "Gets information about a device.")
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] devicepath", "",
Help,
{
"output-prefix|w=", "Name of character encoding to use.", s => outputPrefix = s
},
{
"help|h|?", "Show this message and exit.", v => showHelp = v != null
}
};
Add(new Option(new[]
{
"--output-prefix", "-w"
}, "Prefix for saving binary information from device.")
{
Argument = new Argument<string>(() => null), Required = false
});
public override int Invoke(IEnumerable<string> arguments)
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
static int Invoke(bool debug, bool verbose, string devicePath, string outputPrefix)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return(int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug)
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("device-info");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return(int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing device path.");
return(int)ErrorNumber.MissingArgument;
}
devicePath = extra[0];
DicConsole.DebugWriteLine("Device-Info command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Device-Info command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Device-Info command", "--device={0}", devicePath);
DicConsole.DebugWriteLine("Device-Info command", "--output-prefix={0}", outputPrefix);
DicConsole.DebugWriteLine("Device-Info command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Device-Info command", "--verbose={0}", verbose);
if(devicePath.Length == 2 &&
devicePath[1] == ':' &&
@@ -932,7 +908,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("\tCan do challenge/response with Xbox discs");
if(devInfo.KreonFeatures.HasFlag(KreonFeatures.DecryptSs))
DicConsole.WriteLine("\tCan read and descrypt SS from Xbox discs");
DicConsole.WriteLine("\tCan read and decrypt SS from Xbox discs");
if(devInfo.KreonFeatures.HasFlag(KreonFeatures.XtremeUnlock))
DicConsole.WriteLine("\tCan set xtreme unlock state with Xbox discs");
@@ -944,7 +920,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("\tCan do challenge/response with Xbox 360 discs");
if(devInfo.KreonFeatures.HasFlag(KreonFeatures.DecryptSs360))
DicConsole.WriteLine("\tCan read and descrypt SS from Xbox 360 discs");
DicConsole.WriteLine("\tCan read and decrypt SS from Xbox 360 discs");
if(devInfo.KreonFeatures.HasFlag(KreonFeatures.XtremeUnlock360))
DicConsole.WriteLine("\tCan set xtreme unlock state with Xbox 360 discs");

View File

@@ -32,6 +32,8 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Threading;
using DiscImageChef.CommonTypes.Enums;
@@ -44,9 +46,8 @@ using DiscImageChef.Database.Models;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Devices;
using Mono.Options;
using Newtonsoft.Json;
using Command = Mono.Options.Command;
using Command = System.CommandLine.Command;
using Device = DiscImageChef.Devices.Device;
using DeviceReport = DiscImageChef.Core.Devices.Report.DeviceReport;
@@ -54,73 +55,44 @@ namespace DiscImageChef.Commands
{
internal class DeviceReportCommand : Command
{
string _devicePath;
bool _showHelp;
public DeviceReportCommand() : base("device-report",
"Tests the device capabilities and creates an JSON report of them.") =>
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} devicepath", "",
Help,
{
"help|h|?", "Show this message and exit.", v => _showHelp = v != null
}
};
public override int Invoke(IEnumerable<string> arguments)
"Tests the device capabilities and creates an JSON report of them.")
{
List<string> extra = Options.Parse(arguments);
if(_showHelp)
AddArgument(new Argument<string>
{
Options.WriteOptionDescriptions(CommandSet.Out);
Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path"
});
return(int)ErrorNumber.HelpRequested;
}
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
static int Invoke(bool debug, bool verbose, string devicePath)
{
MainClass.PrintCopyright();
if(MainClass.Debug)
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("device-report");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
DicConsole.DebugWriteLine("Device-Report command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Device-Report command", "--device={0}", devicePath);
DicConsole.DebugWriteLine("Device-Report command", "--verbose={0}", verbose);
return(int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing device path.");
return(int)ErrorNumber.MissingArgument;
}
_devicePath = extra[0];
DicConsole.DebugWriteLine("Device-Report command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Device-Report command", "--device={0}", _devicePath);
DicConsole.DebugWriteLine("Device-Report command", "--verbose={0}", MainClass.Verbose);
if(_devicePath.Length == 2 &&
_devicePath[1] == ':' &&
_devicePath[0] != '/' &&
char.IsLetter(_devicePath[0]))
_devicePath = "\\\\.\\" + char.ToUpper(_devicePath[0]) + ':';
if(devicePath.Length == 2 &&
devicePath[1] == ':' &&
devicePath[0] != '/' &&
char.IsLetter(devicePath[0]))
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
Device dev;
try
{
dev = new Device(_devicePath);
dev = new Device(devicePath);
if(dev.IsRemote)
Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,

View File

@@ -32,6 +32,8 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Linq;
using System.Text;
@@ -39,173 +41,195 @@ using System.Xml.Serialization;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Core.Devices.Dumping;
using DiscImageChef.Core.Logging;
using DiscImageChef.Devices;
using Mono.Options;
using Schemas;
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
namespace DiscImageChef.Commands
{
// TODO: Add raw dumping
internal class DumpMediaCommand : Command
{
string _cicmXml;
string _devicePath;
bool _doResume = true;
string _encodingName;
bool _firstTrackPregap;
bool _fixOffset = true;
bool _force;
bool _noMetadata;
bool _noTrim;
string _outputFile;
string _outputOptions;
bool _persistent;
ushort _retryPasses = 5;
bool _showHelp;
int _skip = 512;
int _speed;
bool _stopOnError;
string _wantedOutputFormat;
string _wantedSubchannel;
public DumpMediaCommand() : base("dump-media", "Dumps the media inserted on a device to a media image.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--cicm-xml", "-x"
}, "Take metadata from existing CICM XML sidecar.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option(new[]
{
"--encoding", "-e"
}, "Name of character encoding to use.")
{
Argument = new Argument<string>(() => null), Required = false
});
Add(new Option("--first-pregap", "Try to read first track pregap. Only applicable to CD/DDCD/GD.")
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] device_path output_image",
"", Help,
Argument = new Argument<bool>(() => false), Required = false
});
Add(new Option("--fix-offset", "Fix audio tracks offset. Only applicable to CD/GD.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"cicm-xml|x=", "Take metadata from existing CICM XML sidecar.", s => _cicmXml = s
},
"--force", "-f"
}, "Continue dump whatever happens.")
{
"encoding|e=", "Name of character encoding to use.", s => _encodingName = s
}
};
Argument = new Argument<bool>(() => false), Required = false
});
if(DetectOS.GetRealPlatformID() != PlatformID.FreeBSD)
Options.Add("first-pregap", "Try to read first track pregap. Only applicable to CD/DDCD/GD.",
b => _firstTrackPregap = b != null);
Add(new Option(new[]
{
"--format", "-t"
},
"Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.")
{
Argument = new Argument<string>(() => null), Required = false
});
Options.Add("fix-offset", "Fix audio tracks offset. Only applicable to CD/GD.",
b => _fixOffset = b != null);
Add(new Option("--no-metadata", "Disables creating CICM XML sidecar.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Options.Add("force|f", "Continue dump whatever happens.", b => _force = b != null);
Add(new Option("--no-trim", "Disables trimming errored from skipped sectors.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Options.Add("format|t=",
"Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.",
s => _wantedOutputFormat = s);
Add(new Option(new[]
{
"--options", "-O"
}, "Comma separated name=value pairs of options to pass to output image plugin.")
{
Argument = new Argument<string>(() => null), Required = false
});
Options.Add("no-metadata", "Disables creating CICM XML sidecar.", b => _noMetadata = b != null);
Options.Add("no-trim", "Disables trimming errored from skipped sectors.", b => _noTrim = b != null);
Add(new Option("--persistent", "Try to recover partial or incorrect data.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Options.Add("options|O=", "Comma separated name=value pairs of options to pass to output image plugin.",
s => _outputOptions = s);
Add(new Option(new[]
{
"--resume", "-r"
}, "Create/use resume mapfile.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Options.Add("persistent", "Try to recover partial or incorrect data.", b => _persistent = b != null);
Add(new Option(new[]
{
"--retry-passes", "-p"
}, "How many retry passes to do.")
{
Argument = new Argument<ushort>(() => 5), Required = false
});
Options.Add("resume|r", "Create/use resume mapfile.", b => _doResume = b != null);
Add(new Option(new[]
{
"--skip", "-k"
}, "When an unreadable sector is found skip this many sectors.")
{
Argument = new Argument<uint>(() => 512), Required = false
});
Options.Add("retry-passes|p=", "How many retry passes to do.", (ushort us) => _retryPasses = us);
Options.Add("skip|k=", "When an unreadable sector is found skip this many sectors.", (int i) => _skip = i);
Add(new Option(new[]
{
"--stop-on-error", "-s"
}, "Stop media dump on first error.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Options.Add("stop-on-error|s", "Stop media dump on first error.", b => _stopOnError = b != null);
Add(new Option("--subchannel",
"Subchannel to dump. Only applicable to CD/GD. Values: any, rw, rw-or-pq, pq, none.")
{
Argument = new Argument<string>(() => "any"), Required = false
});
Options.Add("help|h|?", "Show this message and exit.", v => _showHelp = v != null);
Add(new Option("--speed", "Speed to dump. Only applicable to optical drives, 0 for maximum.")
{
Argument = new Argument<byte>(() => 0), Required = false
});
Options.Add("subchannel",
"Subchannel to dump. Only applicable to CD/GD. Values: any, rw, rw-or-pq, pq, none",
s => _wantedSubchannel = s);
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path"
});
Options.Add("speed", "Speed to dump. Only applicable to optical drives, 0 for maximum",
(int i) => _speed = i);
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne, Description = "Output image path", Name = "output-path"
});
/* TODO: Disabled temporarily
Options.Add("raw|r", "Dump sectors with tags included. For optical media, dump scrambled sectors.", (b) => raw = b != null);*/
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, string cicmXml, string devicePath, bool resume, string encoding,
bool firstTrackPregap, bool fixOffset, bool force, bool noMetadata, bool noTrim,
string outputPath, string options, bool persistent, ushort retryPasses, int skip,
int speed, bool stopOnError, string format, string subchannel)
{
List<string> extra = Options.Parse(arguments);
if(_showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return(int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug)
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("dump-media");
if(extra.Count > 2)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return(int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count <= 1)
{
DicConsole.ErrorWriteLine("Missing paths.");
return(int)ErrorNumber.MissingArgument;
}
_devicePath = extra[0];
_outputFile = extra[1];
DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", _cicmXml);
DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", _devicePath);
DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", _encodingName);
DicConsole.DebugWriteLine("Dump-Media command", "--first-pregap={0}", _firstTrackPregap);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", _force);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", _force);
DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", _wantedOutputFormat);
DicConsole.DebugWriteLine("Dump-Media command", "--no-metadata={0}", _noMetadata);
DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", Options);
DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", _outputFile);
DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", _persistent);
DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", _doResume);
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", _retryPasses);
DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", _skip);
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", _stopOnError);
DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Dump-Media command", "--subchannel={0}", _wantedSubchannel);
DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", cicmXml);
DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", devicePath);
DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", encoding);
DicConsole.DebugWriteLine("Dump-Media command", "--first-pregap={0}", firstTrackPregap);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", force);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", force);
DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", format);
DicConsole.DebugWriteLine("Dump-Media command", "--no-metadata={0}", noMetadata);
DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", options);
DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", outputPath);
DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", persistent);
DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", resume);
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", retryPasses);
DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", skip);
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", stopOnError);
DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", verbose);
DicConsole.DebugWriteLine("Dump-Media command", "--subchannel={0}", subchannel);
// TODO: Disabled temporarily
//DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw);
Dictionary<string, string> parsedOptions = Core.Options.Parse(_outputOptions);
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Dump-Media command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
Encoding encoding = null;
Encoding encodingClass = null;
if(_encodingName != null)
if(encoding != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(_encodingName);
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
if(verbose)
DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
}
catch(ArgumentException)
{
@@ -214,48 +238,48 @@ namespace DiscImageChef.Commands
return(int)ErrorNumber.EncodingUnknown;
}
DumpSubchannel subchannel = DumpSubchannel.Any;
DumpSubchannel wantedSubchannel = DumpSubchannel.Any;
switch(_wantedSubchannel?.ToLowerInvariant())
switch(subchannel?.ToLowerInvariant())
{
case"any":
case null:
subchannel = DumpSubchannel.Any;
wantedSubchannel = DumpSubchannel.Any;
break;
case"rw":
subchannel = DumpSubchannel.Rw;
wantedSubchannel = DumpSubchannel.Rw;
break;
case"rw-or-pq":
subchannel = DumpSubchannel.RwOrPq;
wantedSubchannel = DumpSubchannel.RwOrPq;
break;
case"pq":
subchannel = DumpSubchannel.Pq;
wantedSubchannel = DumpSubchannel.Pq;
break;
case"none":
subchannel = DumpSubchannel.None;
wantedSubchannel = DumpSubchannel.None;
break;
default:
DicConsole.WriteLine("Incorrect subchannel type \"{0}\" requested.", _wantedSubchannel);
DicConsole.WriteLine("Incorrect subchannel type \"{0}\" requested.", subchannel);
break;
}
if(_devicePath.Length == 2 &&
_devicePath[1] == ':' &&
_devicePath[0] != '/' &&
char.IsLetter(_devicePath[0]))
_devicePath = "\\\\.\\" + char.ToUpper(_devicePath[0]) + ':';
if(devicePath.Length == 2 &&
devicePath[1] == ':' &&
devicePath[0] != '/' &&
char.IsLetter(devicePath[0]))
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
Device dev;
try
{
dev = new Device(_devicePath);
dev = new Device(devicePath);
if(dev.IsRemote)
Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
@@ -277,17 +301,17 @@ namespace DiscImageChef.Commands
Statistics.AddDevice(dev);
string outputPrefix = Path.Combine(Path.GetDirectoryName(_outputFile),
Path.GetFileNameWithoutExtension(_outputFile));
string outputPrefix = Path.Combine(Path.GetDirectoryName(outputPath),
Path.GetFileNameWithoutExtension(outputPath));
Resume resume = null;
var xs = new XmlSerializer(typeof(Resume));
Resume resumeClass = null;
var xs = new XmlSerializer(typeof(Resume));
if(File.Exists(outputPrefix + ".resume.xml") && _doResume)
if(File.Exists(outputPrefix + ".resume.xml") && resume)
try
{
var sr = new StreamReader(outputPrefix + ".resume.xml");
resume = (Resume)xs.Deserialize(sr);
resumeClass = (Resume)xs.Deserialize(sr);
sr.Close();
}
catch
@@ -297,10 +321,10 @@ namespace DiscImageChef.Commands
return(int)ErrorNumber.InvalidResume;
}
if(resume != null &&
resume.NextBlock > resume.LastBlock &&
resume.BadBlocks.Count == 0 &&
!resume.Tape)
if(resumeClass != null &&
resumeClass.NextBlock > resumeClass.LastBlock &&
resumeClass.BadBlocks.Count == 0 &&
!resumeClass.Tape)
{
DicConsole.WriteLine("Media already dumped correctly, not continuing...");
@@ -310,12 +334,12 @@ namespace DiscImageChef.Commands
CICMMetadataType sidecar = null;
var sidecarXs = new XmlSerializer(typeof(CICMMetadataType));
if(_cicmXml != null)
if(File.Exists(_cicmXml))
if(cicmXml != null)
if(File.Exists(cicmXml))
{
try
{
var sr = new StreamReader(_cicmXml);
var sr = new StreamReader(cicmXml);
sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
sr.Close();
}
@@ -337,19 +361,18 @@ namespace DiscImageChef.Commands
List<IWritableImage> candidates = new List<IWritableImage>();
// Try extension
if(string.IsNullOrEmpty(_wantedOutputFormat))
if(string.IsNullOrEmpty(format))
candidates.AddRange(plugins.WritableImages.Values.Where(t =>
t.KnownExtensions.
Contains(Path.
GetExtension(_outputFile))));
Contains(Path.GetExtension(outputPath))));
// Try Id
else if(Guid.TryParse(_wantedOutputFormat, out Guid outId))
else if(Guid.TryParse(format, out Guid outId))
candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId)));
// Try name
else
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, _wantedOutputFormat,
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, format,
StringComparison.
InvariantCultureIgnoreCase)));
@@ -371,7 +394,7 @@ namespace DiscImageChef.Commands
var dumpLog = new DumpLog(outputPrefix + ".log", dev);
if(MainClass.Verbose)
if(verbose)
{
dumpLog.WriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id);
DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id);
@@ -382,10 +405,10 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name);
}
var dumper = new Dump(_doResume, dev, _devicePath, outputFormat, _retryPasses, _force, false, _persistent,
_stopOnError, resume, dumpLog, encoding, outputPrefix, _outputFile, parsedOptions,
sidecar, (uint)_skip, _noMetadata, _noTrim, _firstTrackPregap, _fixOffset,
MainClass.Debug, subchannel, _speed);
var dumper = new Dump(resume, dev, devicePath, outputFormat, retryPasses, force, false, persistent,
stopOnError, resumeClass, dumpLog, encodingClass, outputPrefix, outputPath,
parsedOptions, sidecar, (uint)skip, noMetadata, noTrim, firstTrackPregap, fixOffset,
debug, wantedSubchannel, speed);
dumper.UpdateStatus += Progress.UpdateStatus;
dumper.ErrorMessage += Progress.ErrorMessage;

View File

@@ -30,92 +30,80 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class EntropyCommand : Command
internal class EntropyCommand : Command
{
bool duplicatedSectors = true;
string inputFile;
bool separatedTracks = true;
bool showHelp;
bool wholeDisc = true;
public EntropyCommand() : base("entropy", "Calculates entropy and/or duplicated sectors of an image.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--duplicated-sectors", "-p"
}, "Calculates how many sectors are duplicated (have same exact data in user area).")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--separated-tracks", "-t"
}, "Calculates entropy for each track separately.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--whole-disc", "-w"
}, "Calculates entropy for the whole disc.")
{
Argument = new Argument<bool>(() => true), Required = false
});
AddArgument(new Argument<string>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{
"duplicated-sectors|p",
"Calculates how many sectors are duplicated (have same exact data in user area).",
b => duplicatedSectors = b != null
},
{
"separated-tracks|t", "Calculates entropy for each track separately.",
b => separatedTracks = b != null
},
{"whole-disc|w", "Calculates entropy for the whole disc.", b => wholeDisc = b != null},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, bool duplicatedSectors, string imagePath, bool separatedTracks,
bool wholeDisc)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("entropy");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("Entropy command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Entropy command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Entropy command", "--duplicated-sectors={0}", duplicatedSectors);
DicConsole.DebugWriteLine("Entropy command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Entropy command", "--separated-tracks={0}", separatedTracks);
DicConsole.DebugWriteLine("Entropy command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Entropy command", "--whole-disc={0}", wholeDisc);
DicConsole.DebugWriteLine("Entropy command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Entropy command", "--separated-tracks={0}", separatedTracks);
DicConsole.DebugWriteLine("Entropy command", "--verbose={0}", verbose);
DicConsole.DebugWriteLine("Entropy command", "--whole-disc={0}", wholeDisc);
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -123,7 +111,8 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
inputFormat.Open(inputFilter);
@@ -131,7 +120,7 @@ namespace DiscImageChef.Commands
Statistics.AddMedia(inputFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
Entropy entropyCalculator = new Entropy(MainClass.Debug, MainClass.Verbose, inputFormat);
var entropyCalculator = new Entropy(debug, verbose, inputFormat);
entropyCalculator.InitProgressEvent += Progress.InitProgress;
entropyCalculator.InitProgress2Event += Progress.InitProgress2;
entropyCalculator.UpdateProgressEvent += Progress.UpdateProgress;
@@ -142,9 +131,11 @@ namespace DiscImageChef.Commands
if(separatedTracks)
{
EntropyResults[] tracksEntropy = entropyCalculator.CalculateTracksEntropy(duplicatedSectors);
foreach(EntropyResults trackEntropy in tracksEntropy)
{
DicConsole.WriteLine("Entropy for track {0} is {1:F4}.", trackEntropy.Track, trackEntropy.Entropy);
if(trackEntropy.UniqueSectors != null)
DicConsole.WriteLine("Track {0} has {1} unique sectors ({2:P3})", trackEntropy.Track,
trackEntropy.UniqueSectors,
@@ -152,16 +143,18 @@ namespace DiscImageChef.Commands
}
}
if(!wholeDisc) return (int)ErrorNumber.NoError;
if(!wholeDisc)
return(int)ErrorNumber.NoError;
EntropyResults entropy = entropyCalculator.CalculateMediaEntropy(duplicatedSectors);
DicConsole.WriteLine("Entropy for disk is {0:F4}.", entropy.Entropy);
if(entropy.UniqueSectors != null)
DicConsole.WriteLine("Disk has {0} unique sectors ({1:P3})", entropy.UniqueSectors,
(double)entropy.UniqueSectors / (double)entropy.Sectors);
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -32,6 +32,8 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Text;
using DiscImageChef.CommonTypes;
@@ -40,110 +42,115 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
using FileAttributes = DiscImageChef.CommonTypes.Structs.FileAttributes;
namespace DiscImageChef.Commands
{
class ExtractFilesCommand : Command
internal class ExtractFilesCommand : Command
{
string encodingName;
bool extractXattrs;
string inputFile;
string @namespace;
string outputDir;
string pluginOptions;
bool showHelp;
public ExtractFilesCommand() : base("extract-files", "Extracts all files in disc image.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--encoding", "-e"
}, "Name of character encoding to use.")
{
Argument = new Argument<string>(() => null), 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[]
{
"--xattrs", "-x"
}, "Extract extended attributes if present.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Add(new Option(new[]
{
"--namespace", "-n"
}, "Namespace to use for filenames.")
{
Argument = new Argument<string>(() => null), Required = false
});
AddArgument(new Argument<string>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
{
"options|O=", "Comma separated name=value pairs of options to pass to filesystem plugin.",
s => pluginOptions = s
},
{
"output|o=", "Directory where extracted files will be created. Will abort if it exists.",
s => outputDir = s
},
{"xattrs|x", "Extract extended attributes if present.", b => extractXattrs = b != null},
{"namespace|n=", "Namespace to use for filenames.", s => @namespace = s},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "Disc image path", Name = "image-path"
});
AddArgument(new Argument<string>
{
Arity = ArgumentArity.ExactlyOne,
Description = "Directory where extracted files will be created. Will abort if it exists",
Name = "output-dir"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, string encoding, bool xattrs, string imagePath, string @namespace,
string outputDir, string options)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("extract-files");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
DicConsole.DebugWriteLine("Extract-Files command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Extract-Files command", "--encoding={0}", encoding);
DicConsole.DebugWriteLine("Extract-Files command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Extract-Files command", "--options={0}", options);
DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", outputDir);
DicConsole.DebugWriteLine("Extract-Files command", "--verbose={0}", verbose);
DicConsole.DebugWriteLine("Extract-Files command", "--xattrs={0}", xattrs);
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
inputFile = extra[0];
DicConsole.DebugWriteLine("Extract-Files command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Extract-Files command", "--encoding={0}", encodingName);
DicConsole.DebugWriteLine("Extract-Files command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Extract-Files command", "--options={0}", pluginOptions);
DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", outputDir);
DicConsole.DebugWriteLine("Extract-Files command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Extract-Files command", "--xattrs={0}", extractXattrs);
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
Dictionary<string, string> parsedOptions = Core.Options.Parse(pluginOptions);
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
DicConsole.DebugWriteLine("Extract-Files command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Extract-Files command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
parsedOptions.Add("debug", MainClass.Debug.ToString());
parsedOptions.Add("debug", debug.ToString());
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
Encoding encoding = null;
Encoding encodingClass = null;
if(encodingName != null)
if(encoding != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
if(verbose)
DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
}
catch(ArgumentException)
{
DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return (int)ErrorNumber.EncodingUnknown;
return(int)ErrorNumber.EncodingUnknown;
}
PluginBase plugins = GetPluginBase.Instance;
@@ -155,24 +162,29 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
imageFormat.Id);
else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
else
DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
if (outputDir == null)
if(outputDir == null)
{
DicConsole.WriteLine("Output directory missing.");
return (int)ErrorNumber.MissingArgument;
return(int)ErrorNumber.MissingArgument;
}
if(Directory.Exists(outputDir) || File.Exists(outputDir))
if(Directory.Exists(outputDir) ||
File.Exists(outputDir))
{
DicConsole.ErrorWriteLine("Destination exists, aborting.");
return (int)ErrorNumber.DestinationExists;
return(int)ErrorNumber.DestinationExists;
}
Directory.CreateDirectory(outputDir);
@@ -183,14 +195,18 @@ namespace DiscImageChef.Commands
{
DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given");
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
DicConsole.DebugWriteLine("Extract-Files command", "Correctly opened image file.");
DicConsole.DebugWriteLine("Extract-Files command", "Image without headers is {0} bytes.",
imageFormat.Info.ImageSize);
DicConsole.DebugWriteLine("Extract-Files command", "Image has {0} sectors.",
imageFormat.Info.Sectors);
DicConsole.DebugWriteLine("Extract-Files command", "Image identifies disk type as {0}.",
imageFormat.Info.MediaType);
@@ -202,7 +218,8 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
@@ -211,7 +228,9 @@ namespace DiscImageChef.Commands
List<string> idPlugins;
IReadOnlyFilesystem plugin;
Errno error;
if(partitions.Count == 0) DicConsole.DebugWriteLine("Extract-Files command", "No partitions found");
if(partitions.Count == 0)
DicConsole.DebugWriteLine("Extract-Files command", "No partitions found");
else
{
DicConsole.WriteLine("{0} partitions found.", partitions.Count);
@@ -224,7 +243,9 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Identifying filesystem on partition");
Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]);
if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified");
if(idPlugins.Count == 0)
DicConsole.WriteLine("Filesystem not identified");
else if(idPlugins.Count > 1)
{
DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");
@@ -233,20 +254,22 @@ namespace DiscImageChef.Commands
if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
{
DicConsole.WriteLine($"As identified by {plugin.Name}.");
IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
.GetType()
.GetConstructor(Type.EmptyTypes)
?.Invoke(new object[] { });
error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace);
var fs = (IReadOnlyFilesystem)plugin.
GetType().GetConstructor(Type.EmptyTypes)?.
Invoke(new object[]
{ });
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions,
@namespace);
if(error == Errno.NoError)
{
string volumeName =
string.IsNullOrEmpty(fs.XmlFsType.VolumeName)
? "NO NAME"
string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME"
: fs.XmlFsType.VolumeName;
ExtractFilesInDir("/", fs, volumeName);
ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs);
Statistics.AddFilesystem(fs.XmlFsType.Type);
}
@@ -259,34 +282,38 @@ namespace DiscImageChef.Commands
{
plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
DicConsole.WriteLine($"Identified by {plugin.Name}.");
IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
.GetType().GetConstructor(Type.EmptyTypes)
?.Invoke(new object[] { });
error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace);
var fs = (IReadOnlyFilesystem)plugin.
GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{ });
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace);
if(error == Errno.NoError)
{
string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName)
? "NO NAME"
string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME"
: fs.XmlFsType.VolumeName;
ExtractFilesInDir("/", fs, volumeName);
ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs);
Statistics.AddFilesystem(fs.XmlFsType.Type);
}
else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
else
DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
}
}
}
Partition wholePart = new Partition
var wholePart = new Partition
{
Name = "Whole device",
Length = imageFormat.Info.Sectors,
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
Name = "Whole device", Length = imageFormat.Info.Sectors,
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
};
Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified");
if(idPlugins.Count == 0)
DicConsole.WriteLine("Filesystem not identified");
else if(idPlugins.Count > 1)
{
DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");
@@ -295,67 +322,79 @@ namespace DiscImageChef.Commands
if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
{
DicConsole.WriteLine($"As identified by {plugin.Name}.");
IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
.GetType().GetConstructor(Type.EmptyTypes)
?.Invoke(new object[] { });
error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace);
var fs = (IReadOnlyFilesystem)plugin.
GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{ });
error = fs.Mount(imageFormat, wholePart, encodingClass, parsedOptions, @namespace);
if(error == Errno.NoError)
{
string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName)
? "NO NAME"
string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME"
: fs.XmlFsType.VolumeName;
ExtractFilesInDir("/", fs, volumeName);
ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs);
Statistics.AddFilesystem(fs.XmlFsType.Type);
}
else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
else
DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
}
}
else
{
plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
DicConsole.WriteLine($"Identified by {plugin.Name}.");
IReadOnlyFilesystem fs =
(IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { });
error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace);
var fs = (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{ });
error = fs.Mount(imageFormat, wholePart, encodingClass, parsedOptions, @namespace);
if(error == Errno.NoError)
{
string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName)
? "NO NAME"
string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME"
: fs.XmlFsType.VolumeName;
ExtractFilesInDir("/", fs, volumeName);
ExtractFilesInDir("/", fs, volumeName, outputDir, xattrs);
Statistics.AddFilesystem(fs.XmlFsType.Type);
}
else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
else
DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
}
}
catch(Exception ex)
{
DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
DicConsole.DebugWriteLine("Extract-Files command", ex.StackTrace);
return (int)ErrorNumber.UnexpectedException;
return(int)ErrorNumber.UnexpectedException;
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
void ExtractFilesInDir(string path, IReadOnlyFilesystem fs, string volumeName)
static void ExtractFilesInDir(string path, IReadOnlyFilesystem fs, string volumeName, string outputDir,
bool doXattrs)
{
if(path.StartsWith("/")) path = path.Substring(1);
if(path.StartsWith("/"))
path = path.Substring(1);
Errno error = fs.ReadDir(path, out List<string> directory);
if(error != Errno.NoError)
{
DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
return;
}
foreach(string entry in directory)
{
error = fs.Stat(path + "/" + entry, out FileEntryInfo stat);
if(error == Errno.NoError)
{
string outputPath;
@@ -370,14 +409,15 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Created subdirectory at {0}", outputPath);
ExtractFilesInDir(path + "/" + entry, fs, volumeName);
ExtractFilesInDir(path + "/" + entry, fs, volumeName, outputDir, doXattrs);
DirectoryInfo di = new DirectoryInfo(outputPath);
var di = new DirectoryInfo(outputPath);
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
try
{
if(stat.CreationTimeUtc.HasValue) di.CreationTimeUtc = stat.CreationTimeUtc.Value;
if(stat.CreationTimeUtc.HasValue)
di.CreationTimeUtc = stat.CreationTimeUtc.Value;
}
catch
{
@@ -386,7 +426,8 @@ namespace DiscImageChef.Commands
try
{
if(stat.LastWriteTimeUtc.HasValue) di.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value;
if(stat.LastWriteTimeUtc.HasValue)
di.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value;
}
catch
{
@@ -395,7 +436,8 @@ namespace DiscImageChef.Commands
try
{
if(stat.AccessTimeUtc.HasValue) di.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
if(stat.AccessTimeUtc.HasValue)
di.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
}
catch
{
@@ -407,15 +449,19 @@ namespace DiscImageChef.Commands
}
FileStream outputFile;
if(extractXattrs)
if(doXattrs)
{
error = fs.ListXAttr(path + "/" + entry, out List<string> xattrs);
if(error == Errno.NoError)
foreach(string xattr in xattrs)
{
byte[] xattrBuf = new byte[0];
error = fs.GetXattr(path + "/" + entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue;
if(error != Errno.NoError)
continue;
Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type, volumeName,
".xattrs", xattr));
@@ -427,9 +473,10 @@ namespace DiscImageChef.Commands
{
outputFile = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite,
FileShare.None);
outputFile.Write(xattrBuf, 0, xattrBuf.Length);
outputFile.Close();
FileInfo fi = new FileInfo(outputPath);
var fi = new FileInfo(outputPath);
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
try
{
@@ -453,7 +500,8 @@ namespace DiscImageChef.Commands
try
{
if(stat.AccessTimeUtc.HasValue) fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
if(stat.AccessTimeUtc.HasValue)
fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
}
catch
{
@@ -483,13 +531,15 @@ namespace DiscImageChef.Commands
{
outputFile = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite,
FileShare.None);
outputFile.Write(outBuf, 0, outBuf.Length);
outputFile.Close();
FileInfo fi = new FileInfo(outputPath);
var fi = new FileInfo(outputPath);
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
try
{
if(stat.CreationTimeUtc.HasValue) fi.CreationTimeUtc = stat.CreationTimeUtc.Value;
if(stat.CreationTimeUtc.HasValue)
fi.CreationTimeUtc = stat.CreationTimeUtc.Value;
}
catch
{
@@ -498,7 +548,8 @@ namespace DiscImageChef.Commands
try
{
if(stat.LastWriteTimeUtc.HasValue) fi.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value;
if(stat.LastWriteTimeUtc.HasValue)
fi.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value;
}
catch
{
@@ -507,7 +558,8 @@ namespace DiscImageChef.Commands
try
{
if(stat.AccessTimeUtc.HasValue) fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
if(stat.AccessTimeUtc.HasValue)
fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
}
catch
{
@@ -517,11 +569,14 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Written {0} bytes of file {1} to {2}", outBuf.Length, entry,
outputPath);
}
else DicConsole.ErrorWriteLine("Error {0} reading file {1}", error, entry);
else
DicConsole.ErrorWriteLine("Error {0} reading file {1}", error, entry);
}
else DicConsole.ErrorWriteLine("Cannot write file {0}, output exists", entry);
else
DicConsole.ErrorWriteLine("Cannot write file {0}, output exists", entry);
}
else DicConsole.ErrorWriteLine("Error reading file {0}", entry);
else
DicConsole.ErrorWriteLine("Error reading file {0}", entry);
}
}
}

View File

@@ -31,6 +31,8 @@
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
@@ -38,123 +40,121 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Partitions;
using Mono.Options;
namespace DiscImageChef.Commands
{
class FormatsCommand : Command
internal class FormatsCommand : Command
{
bool showHelp;
public FormatsCommand() : base("formats",
"Lists all supported disc images, partition schemes and file systems.")
"Lists all supported disc images, partition schemes and file systems.") =>
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
static int Invoke(bool verbose, bool debug)
{
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name}",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("formats");
if(extra.Count > 0)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
DicConsole.DebugWriteLine("Formats command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Formats command", "--verbose={0}", verbose);
DicConsole.DebugWriteLine("Formats command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Formats command", "--verbose={0}", MainClass.Verbose);
PluginBase plugins = GetPluginBase.Instance;
FiltersList filtersList = new FiltersList();
PluginBase plugins = GetPluginBase.Instance;
var filtersList = new FiltersList();
DicConsole.WriteLine("Supported filters ({0}):", filtersList.Filters.Count);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tFilter");
if(verbose)
DicConsole.VerboseWriteLine("GUID\t\t\t\t\tFilter");
foreach(KeyValuePair<string, IFilter> kvp in filtersList.Filters)
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine();
DicConsole.WriteLine("Read-only media image formats ({0}):",
plugins.ImagePluginsList.Count(t => !t.Value.GetType().GetInterfaces()
.Contains(typeof(IWritableImage))));
if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IMediaImage> kvp in plugins.ImagePluginsList.Where(t => !t.Value.GetType()
.GetInterfaces()
.Contains(typeof(
plugins.ImagePluginsList.Count(t => !t.Value.GetType().GetInterfaces().
Contains(typeof(IWritableImage))));
if(verbose)
DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IMediaImage> kvp in plugins.ImagePluginsList.Where(t => !t.Value.GetType().
GetInterfaces().
Contains(typeof(
IWritableImage
))))
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine();
DicConsole.WriteLine("Read/write media image formats ({0}):", plugins.WritableImages.Count);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
if(verbose)
DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IWritableImage> kvp in plugins.WritableImages)
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine();
DicConsole.WriteLine("Supported filesystems for identification and information only ({0}):",
plugins.PluginsList.Count(t => !t.Value.GetType().GetInterfaces()
.Contains(typeof(IReadOnlyFilesystem))));
if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IFilesystem> kvp in plugins.PluginsList.Where(t => !t.Value.GetType()
.GetInterfaces()
.Contains(typeof(
plugins.PluginsList.Count(t => !t.Value.GetType().GetInterfaces().
Contains(typeof(IReadOnlyFilesystem))));
if(verbose)
DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IFilesystem> kvp in plugins.PluginsList.Where(t => !t.Value.GetType().
GetInterfaces().
Contains(typeof(
IReadOnlyFilesystem
))))
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine();
DicConsole.WriteLine("Supported filesystems that can read their contents ({0}):",
plugins.ReadOnlyFilesystems.Count);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
if(verbose)
DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IReadOnlyFilesystem> kvp in plugins.ReadOnlyFilesystems)
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine();
DicConsole.WriteLine("Supported partitioning schemes ({0}):", plugins.PartPluginsList.Count);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
if(verbose)
DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IPartition> kvp in plugins.PartPluginsList)
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -31,77 +31,53 @@
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class ImageInfoCommand : Command
internal class ImageInfoCommand : Command
{
string inputFile;
bool showHelp;
public ImageInfoCommand() : base("image-info",
"Opens a media image and shows information about the media it represents and metadata.")
{
Options = new OptionSet
AddArgument(new Argument<string>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} imagefile",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, string imagePath)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("image-info");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose);
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", MainClass.Verbose);
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
try
@@ -111,7 +87,8 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
DicConsole.WriteLine("Image format not identified.");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
DicConsole.WriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id);
@@ -123,7 +100,8 @@ namespace DiscImageChef.Commands
{
DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given");
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
ImageInfo.PrintImageInfo(imageFormat);
@@ -137,17 +115,19 @@ namespace DiscImageChef.Commands
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
DicConsole.DebugWriteLine("Image-info command", "Stack trace: {0}", ex.StackTrace);
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
}
catch(Exception ex)
{
DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
DicConsole.DebugWriteLine("Image-info command", ex.StackTrace);
return (int)ErrorNumber.UnexpectedException;
return(int)ErrorNumber.UnexpectedException;
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -30,70 +30,47 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Devices;
using Mono.Options;
namespace DiscImageChef.Commands
{
internal class ListDevicesCommand : Command
{
bool showHelp;
public ListDevicesCommand() : base("list-devices", "Lists all connected devices.") => Options = new OptionSet
public ListDevicesCommand() : base("list-devices", "Lists all connected devices.")
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [dic-remote-host]", "",
Help,
AddArgument(new Argument<string>
{
"help|h|?", "Show this message and exit.", v => showHelp = v != null
}
};
Arity = ArgumentArity.ZeroOrOne, Description = "dicremote host", Name = "dic-remote-host"
});
public override int Invoke(IEnumerable<string> arguments)
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
static int Invoke(bool debug, bool verbose, string dicRemoteHost)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return(int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug)
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("list-devices");
string dicRemote = null;
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return(int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 1)
dicRemote = extra[0];
DicConsole.DebugWriteLine("List-Devices command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("List-Devices command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("List-Devices command", "--debug={0}", debug);
DicConsole.DebugWriteLine("List-Devices command", "--verbose={0}", verbose);
DeviceInfo[] devices = Device.ListDevices(out bool isRemote, out string serverApplication,
out string serverVersion, out string serverOperatingSystem,
out string serverOperatingSystemVersion,
out string serverArchitecture, dicRemote);
out string serverArchitecture, dicRemoteHost);
if(isRemote)
{
@@ -110,7 +87,7 @@ namespace DiscImageChef.Commands
{
devices = devices.OrderBy(d => d.Path).ToArray();
if(dicRemote is null)
if(dicRemoteHost is null)
{
DicConsole.WriteLine("{0,-22}|{1,-16}|{2,-24}|{3,-24}|{4,-10}|{5,-10}", "Path", "Vendor", "Model",
"Serial", "Bus", "Supported?");

View File

@@ -31,76 +31,52 @@
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using System.Text;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class ListEncodingsCommand : Command
internal class ListEncodingsCommand : Command
{
bool showHelp;
public ListEncodingsCommand() : base("list-encodings", "Lists all supported text encodings and code pages.") =>
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
public ListEncodingsCommand() : base("list-encodings", "Lists all supported text encodings and code pages.")
static int Invoke(bool debug, bool verbose)
{
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name}",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("list-encodings");
if(extra.Count > 0)
DicConsole.DebugWriteLine("List-Encodings command", "--debug={0}", debug);
DicConsole.DebugWriteLine("List-Encodings command", "--verbose={0}", verbose);
List<CommonEncodingInfo> encodings = Encoding.GetEncodings().Select(info => new CommonEncodingInfo
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
Name = info.Name, DisplayName = info.GetEncoding().EncodingName
}).ToList();
DicConsole.DebugWriteLine("List-Encodings command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("List-Encodings command", "--verbose={0}", MainClass.Verbose);
List<CommonEncodingInfo> encodings = Encoding
.GetEncodings().Select(info => new CommonEncodingInfo
{
Name = info.Name,
DisplayName =
info.GetEncoding().EncodingName
}).ToList();
encodings.AddRange(Claunia.Encoding.Encoding.GetEncodings()
.Select(info => new CommonEncodingInfo
{
Name = info.Name, DisplayName = info.DisplayName
}));
encodings.AddRange(Claunia.Encoding.Encoding.GetEncodings().Select(info => new CommonEncodingInfo
{
Name = info.Name, DisplayName = info.DisplayName
}));
DicConsole.WriteLine("{0,-16} {1,-8}", "Name", "Description");
foreach(CommonEncodingInfo info in encodings.OrderBy(t => t.DisplayName))
DicConsole.WriteLine("{0,-16} {1,-8}", info.Name, info.DisplayName);
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
struct CommonEncodingInfo

View File

@@ -31,73 +31,54 @@
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class ListNamespacesCommand : Command
internal class ListNamespacesCommand : Command
{
bool showHelp;
public ListNamespacesCommand() : base("list-namespaces",
"Lists all namespaces supported by read-only filesystems.")
"Lists all namespaces supported by read-only filesystems.") =>
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
static int Invoke(bool debug, bool verbose)
{
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name}",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count > 0)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
DicConsole.DebugWriteLine("List-Namespaces command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("List-Namespaces command", "--verbose={0}", MainClass.Verbose);
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
DicConsole.DebugWriteLine("List-Namespaces command", "--debug={0}", debug);
DicConsole.DebugWriteLine("List-Namespaces command", "--verbose={0}", verbose);
Statistics.AddCommand("list-namespaces");
PluginBase plugins = GetPluginBase.Instance;
foreach(KeyValuePair<string, IReadOnlyFilesystem> kvp in plugins.ReadOnlyFilesystems)
{
if(kvp.Value.Namespaces is null) continue;
if(kvp.Value.Namespaces is null)
continue;
DicConsole.WriteLine("\tNamespaces for {0}:", kvp.Value.Name);
DicConsole.WriteLine("\tNamespaces for {0}:", kvp.Value.Name);
DicConsole.WriteLine("\t\t{0,-16} {1,-16}", "Namespace", "Description");
foreach(KeyValuePair<string, string> @namespace in kvp.Value.Namespaces.OrderBy(t => t.Key))
DicConsole.WriteLine("\t\t{0,-16} {1,-16}", @namespace.Key, @namespace.Value);
DicConsole.WriteLine();
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -32,109 +32,107 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class ListOptionsCommand : Command
internal class ListOptionsCommand : Command
{
bool showHelp;
public ListOptionsCommand() : base("list-options",
"Lists all options supported by read-only filesystems and writable media images.")
"Lists all options supported by read-only filesystems and writable media images.") =>
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
static int Invoke(bool debug, bool verbose)
{
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name}",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count > 0)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
DicConsole.DebugWriteLine("List-Options command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("List-Options command", "--verbose={0}", MainClass.Verbose);
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
DicConsole.DebugWriteLine("List-Options command", "--debug={0}", debug);
DicConsole.DebugWriteLine("List-Options command", "--verbose={0}", verbose);
Statistics.AddCommand("list-options");
PluginBase plugins = GetPluginBase.Instance;
DicConsole.WriteLine("Read-only filesystems options:");
foreach(KeyValuePair<string, IReadOnlyFilesystem> kvp in plugins.ReadOnlyFilesystems)
{
List<(string name, Type type, string description)> options = kvp.Value.SupportedOptions.ToList();
if(options.Count == 0) continue;
DicConsole.WriteLine("\tOptions for {0}:", kvp.Value.Name);
if(options.Count == 0)
continue;
DicConsole.WriteLine("\tOptions for {0}:", kvp.Value.Name);
DicConsole.WriteLine("\t\t{0,-16} {1,-16} {2,-8}", "Name", "Type", "Description");
foreach((string name, Type type, string description) option in options.OrderBy(t => t.name))
DicConsole.WriteLine("\t\t{0,-16} {1,-16} {2,-8}", option.name, TypeToString(option.type),
option.description);
DicConsole.WriteLine();
}
DicConsole.WriteLine();
DicConsole.WriteLine("Read/Write media images options:");
foreach(KeyValuePair<string, IWritableImage> kvp in plugins.WritableImages)
{
List<(string name, Type type, string description, object @default)> options =
kvp.Value.SupportedOptions.ToList();
if(options.Count == 0) continue;
DicConsole.WriteLine("\tOptions for {0}:", kvp.Value.Name);
if(options.Count == 0)
continue;
DicConsole.WriteLine("\tOptions for {0}:", kvp.Value.Name);
DicConsole.WriteLine("\t\t{0,-20} {1,-10} {2,-12} {3,-8}", "Name", "Type", "Default", "Description");
foreach((string name, Type type, string description, object @default) option in
options.OrderBy(t => t.name))
DicConsole.WriteLine("\t\t{0,-20} {1,-10} {2,-12} {3,-8}", option.name, TypeToString(option.type),
option.@default, option.description);
DicConsole.WriteLine();
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
static string TypeToString(Type type)
{
if(type == typeof(bool)) return "boolean";
if(type == typeof(bool))
return"boolean";
if(type == typeof(sbyte) || type == typeof(short) || type == typeof(int) || type == typeof(long))
return "signed number";
if(type == typeof(sbyte) ||
type == typeof(short) ||
type == typeof(int) ||
type == typeof(long))
return"signed number";
if(type == typeof(byte) || type == typeof(ushort) || type == typeof(uint) || type == typeof(ulong))
return "number";
if(type == typeof(byte) ||
type == typeof(ushort) ||
type == typeof(uint) ||
type == typeof(ulong))
return"number";
if(type == typeof(float) || type == typeof(double)) return "float number";
if(type == typeof(float) ||
type == typeof(double))
return"float number";
if(type == typeof(Guid)) return "uuid";
if(type == typeof(Guid))
return"uuid";
return type == typeof(string) ? "string" : type.ToString();
}

View File

@@ -32,6 +32,8 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using System.Text;
using DiscImageChef.CommonTypes;
@@ -40,102 +42,104 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class LsCommand : Command
internal class LsCommand : Command
{
string encodingName;
string inputFile;
bool longFormat;
string @namespace;
string pluginOptions;
bool showHelp;
public LsCommand() : base("ls", "Lists files in disc image.")
{
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
{"long|l", "Uses long format.", b => longFormat = b != null},
Add(new Option(new[]
{
"options|O=", "Comma separated name=value pairs of options to pass to filesystem plugin.",
s => pluginOptions = s
},
{"namespace|n=", "Namespace to use for filenames.", s => @namespace = s},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
"--encoding", "-e"
}, "Name of character encoding to use.")
{
Argument = new Argument<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, Description = "Media image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, string encoding, string imagePath, bool longFormat,
string @namespace, string options)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
inputFile = extra[0];
DicConsole.DebugWriteLine("Ls command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Ls command", "--encoding={0}", encodingName);
DicConsole.DebugWriteLine("Ls command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Ls command", "--options={0}", pluginOptions);
DicConsole.DebugWriteLine("Ls command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Ls command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Ls command", "--encoding={0}", encoding);
DicConsole.DebugWriteLine("Ls command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Ls command", "--options={0}", options);
DicConsole.DebugWriteLine("Ls command", "--verbose={0}", verbose);
Statistics.AddCommand("ls");
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
Dictionary<string, string> parsedOptions = Core.Options.Parse(pluginOptions);
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
DicConsole.DebugWriteLine("Ls command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Ls command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
parsedOptions.Add("debug", MainClass.Debug.ToString());
parsedOptions.Add("debug", debug.ToString());
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
Encoding encoding = null;
Encoding encodingClass = null;
if(encodingName != null)
if(encoding != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encodingClass = Claunia.Encoding.Encoding.GetEncoding(encoding);
if(verbose)
DicConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
}
catch(ArgumentException)
{
DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return (int)ErrorNumber.EncodingUnknown;
return(int)ErrorNumber.EncodingUnknown;
}
PluginBase plugins = GetPluginBase.Instance;
@@ -147,13 +151,15 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
imageFormat.Id);
else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
else
DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
try
{
@@ -161,13 +167,17 @@ namespace DiscImageChef.Commands
{
DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given");
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
DicConsole.DebugWriteLine("Ls command", "Correctly opened image file.");
DicConsole.DebugWriteLine("Ls command", "Image without headers is {0} bytes.",
imageFormat.Info.ImageSize);
DicConsole.DebugWriteLine("Ls command", "Image has {0} sectors.", imageFormat.Info.Sectors);
DicConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.",
imageFormat.Info.MediaType);
@@ -179,7 +189,8 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return (int)ErrorNumber.CannotOpenFormat;
return(int)ErrorNumber.CannotOpenFormat;
}
List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
@@ -188,7 +199,9 @@ namespace DiscImageChef.Commands
List<string> idPlugins;
IReadOnlyFilesystem plugin;
Errno error;
if(partitions.Count == 0) DicConsole.DebugWriteLine("Ls command", "No partitions found");
if(partitions.Count == 0)
DicConsole.DebugWriteLine("Ls command", "No partitions found");
else
{
DicConsole.WriteLine("{0} partitions found.", partitions.Count);
@@ -201,7 +214,9 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Identifying filesystem on partition");
Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]);
if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified");
if(idPlugins.Count == 0)
DicConsole.WriteLine("Filesystem not identified");
else if(idPlugins.Count > 1)
{
DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");
@@ -210,17 +225,21 @@ namespace DiscImageChef.Commands
if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
{
DicConsole.WriteLine($"As identified by {plugin.Name}.");
IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
.GetType()
.GetConstructor(Type.EmptyTypes)
?.Invoke(new object[] { });
if(fs == null) continue;
var fs = (IReadOnlyFilesystem)plugin.
GetType().GetConstructor(Type.EmptyTypes)?.
Invoke(new object[]
{ });
if(fs == null)
continue;
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions,
@namespace);
error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace);
if(error == Errno.NoError)
{
ListFilesInDir("/", fs);
ListFilesInDir("/", fs, longFormat);
Statistics.AddFilesystem(fs.XmlFsType.Type);
}
@@ -232,35 +251,43 @@ namespace DiscImageChef.Commands
else
{
plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
if(plugin == null) continue;
if(plugin == null)
continue;
DicConsole.WriteLine($"Identified by {plugin.Name}.");
IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
.GetType().GetConstructor(Type.EmptyTypes)
?.Invoke(new object[] { });
if(fs == null) continue;
error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace);
var fs = (IReadOnlyFilesystem)plugin.
GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{ });
if(fs == null)
continue;
error = fs.Mount(imageFormat, partitions[i], encodingClass, parsedOptions, @namespace);
if(error == Errno.NoError)
{
ListFilesInDir("/", fs);
ListFilesInDir("/", fs, longFormat);
Statistics.AddFilesystem(fs.XmlFsType.Type);
}
else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
else
DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
}
}
}
Partition wholePart = new Partition
var wholePart = new Partition
{
Name = "Whole device",
Length = imageFormat.Info.Sectors,
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
Name = "Whole device", Length = imageFormat.Info.Sectors,
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
};
Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified");
if(idPlugins.Count == 0)
DicConsole.WriteLine("Filesystem not identified");
else if(idPlugins.Count > 1)
{
DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");
@@ -269,40 +296,50 @@ namespace DiscImageChef.Commands
if(plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
{
DicConsole.WriteLine($"As identified by {plugin.Name}.");
IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
.GetType().GetConstructor(Type.EmptyTypes)
?.Invoke(new object[] { });
if(fs == null) continue;
error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace);
var fs = (IReadOnlyFilesystem)plugin.
GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{ });
if(fs == null)
continue;
error = fs.Mount(imageFormat, wholePart, encodingClass, parsedOptions, @namespace);
if(error == Errno.NoError)
{
ListFilesInDir("/", fs);
ListFilesInDir("/", fs, longFormat);
Statistics.AddFilesystem(fs.XmlFsType.Type);
}
else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
else
DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
}
}
else
{
plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
if(plugin != null)
{
DicConsole.WriteLine($"Identified by {plugin.Name}.");
IReadOnlyFilesystem fs =
(IReadOnlyFilesystem)plugin
.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { });
var fs = (IReadOnlyFilesystem)plugin.
GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{ });
if(fs != null)
{
error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace);
error = fs.Mount(imageFormat, wholePart, encodingClass, parsedOptions, @namespace);
if(error == Errno.NoError)
{
ListFilesInDir("/", fs);
ListFilesInDir("/", fs, longFormat);
Statistics.AddFilesystem(fs.XmlFsType.Type);
}
else DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
else
DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
}
}
}
@@ -311,15 +348,17 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
DicConsole.DebugWriteLine("Ls command", ex.StackTrace);
return (int)ErrorNumber.UnexpectedException;
return(int)ErrorNumber.UnexpectedException;
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
void ListFilesInDir(string path, IReadOnlyFilesystem fs)
static void ListFilesInDir(string path, IReadOnlyFilesystem fs, bool longFormat)
{
if(path.StartsWith("/")) path = path.Substring(1);
if(path.StartsWith("/"))
path = path.Substring(1);
DicConsole.WriteLine(string.IsNullOrEmpty(path) ? "Root directory" : $"Directory: {path}");
@@ -328,6 +367,7 @@ namespace DiscImageChef.Commands
if(error != Errno.NoError)
{
DicConsole.ErrorWriteLine("Error {0} reading root directory {1}", error.ToString(), path);
return;
}
@@ -335,7 +375,7 @@ namespace DiscImageChef.Commands
foreach(string entry in directory)
{
error = fs.Stat(path + "/" + entry, out FileEntryInfo stat);
fs.Stat(path + "/" + entry, out FileEntryInfo stat);
stats.Add(entry, stat);
}
@@ -355,30 +395,36 @@ namespace DiscImageChef.Commands
entry.Key);
error = fs.ListXAttr(path + "/" + entry.Key, out List<string> xattrs);
if(error != Errno.NoError) continue;
if(error != Errno.NoError)
continue;
foreach(string xattr in xattrs)
{
byte[] xattrBuf = new byte[0];
error = fs.GetXattr(path + "/" + entry.Key, xattr, ref xattrBuf);
if(error == Errno.NoError)
DicConsole.WriteLine("\t\t{0}\t{1:##,#}", xattr, xattrBuf.Length);
}
}
else DicConsole.WriteLine("{0, 47}{1}", string.Empty, entry.Key);
else
DicConsole.WriteLine("{0, 47}{1}", string.Empty, entry.Key);
}
else
{
if(entry.Value != null && entry.Value.Attributes.HasFlag(FileAttributes.Directory))
if(entry.Value != null &&
entry.Value.Attributes.HasFlag(FileAttributes.Directory))
DicConsole.WriteLine("{0}/", entry.Key);
else DicConsole.WriteLine("{0}", entry.Key);
else
DicConsole.WriteLine("{0}", entry.Key);
}
DicConsole.WriteLine();
foreach(KeyValuePair<string, FileEntryInfo> subdirectory in
stats.Where(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == true))
ListFilesInDir(path + "/" + subdirectory.Key, fs);
ListFilesInDir(path + "/" + subdirectory.Key, fs, longFormat);
}
}
}

View File

@@ -32,6 +32,8 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
@@ -44,7 +46,6 @@ using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Decoders.SCSI.SSC;
using DiscImageChef.Decoders.Xbox;
using DiscImageChef.Devices;
using Mono.Options;
using BCA = DiscImageChef.Decoders.Bluray.BCA;
using Cartridge = DiscImageChef.Decoders.DVD.Cartridge;
using DDS = DiscImageChef.Decoders.DVD.DDS;
@@ -55,65 +56,40 @@ namespace DiscImageChef.Commands
{
internal class MediaInfoCommand : Command
{
string devicePath;
string outputPrefix;
bool showHelp;
public MediaInfoCommand() : base("media-info", "Gets information about the media inserted on a device.") =>
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] devicepath", "",
Help,
{
"output-prefix|w=", "Write binary responses from device with that prefix.", s => outputPrefix = s
},
{
"help|h|?", "Show this message and exit.", v => showHelp = v != null
}
};
public override int Invoke(IEnumerable<string> arguments)
public MediaInfoCommand() : base("media-info", "Gets information about the media inserted on a device.")
{
List<string> extra = Options.Parse(arguments);
Add(new Option(new[]
{
"--output-prefix", "-w"
}, "Write binary responses from device with that prefix.")
{
Argument = new Argument<string>(() => null), Required = false
});
if(showHelp)
AddArgument(new Argument<string>
{
Options.WriteOptionDescriptions(CommandSet.Out);
Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path"
});
return(int)ErrorNumber.HelpRequested;
}
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
static int Invoke(bool debug, bool verbose, string devicePath, string outputPrefix)
{
MainClass.PrintCopyright();
if(MainClass.Debug)
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("media-info");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return(int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing device path.");
return(int)ErrorNumber.MissingArgument;
}
devicePath = extra[0];
DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Media-Info command", "--device={0}", devicePath);
DicConsole.DebugWriteLine("Media-Info command", "--output-prefix={0}", outputPrefix);
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", verbose);
if(devicePath.Length == 2 &&
devicePath[1] == ':' &&

View File

@@ -30,82 +30,61 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Core.Devices.Scanning;
using DiscImageChef.Devices;
using Mono.Options;
namespace DiscImageChef.Commands
{
internal class MediaScanCommand : Command
{
string devicePath;
string ibgLogPath;
string mhddLogPath;
bool showHelp;
public MediaScanCommand() : base("media-scan", "Scans the media inserted on a device.") =>
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] devicepath", "",
Help,
{
"mhdd-log|mw=", "Write a log of the scan in the format used by MHDD.", s => mhddLogPath = s
},
{
"ibg-log|b=", "Write a log of the scan in the format used by ImgBurn.", s => ibgLogPath = s
},
{
"help|h|?", "Show this message and exit.", v => showHelp = v != null
}
};
public override int Invoke(IEnumerable<string> arguments)
public MediaScanCommand() : base("media-scan", "Scans the media inserted on a device.")
{
List<string> extra = Options.Parse(arguments);
Add(new Option(new[]
{
"--mhdd-log", "-m"
}, "Write a log of the scan in the format used by MHDD.")
{
Argument = new Argument<string>(() => null), Required = false
});
if(showHelp)
Add(new Option(new[]
{
"--ibg-log", "-b"
}, "Write a log of the scan in the format used by ImgBurn.")
{
Argument = new Argument<bool>(() => true), Required = false
});
AddArgument(new Argument<string>
{
Options.WriteOptionDescriptions(CommandSet.Out);
Arity = ArgumentArity.ExactlyOne, Description = "Device path", Name = "device-path"
});
return(int)ErrorNumber.HelpRequested;
}
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
static int Invoke(bool debug, bool verbose, string devicePath, string ibgLog, string mhddLog)
{
MainClass.PrintCopyright();
if(MainClass.Debug)
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("media-scan");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return(int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing device path.");
return(int)ErrorNumber.MissingArgument;
}
devicePath = extra[0];
DicConsole.DebugWriteLine("Media-Scan command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Media-Scan command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Media-Scan command", "--device={0}", devicePath);
DicConsole.DebugWriteLine("Media-Scan command", "--ibg-log={0}", ibgLogPath);
DicConsole.DebugWriteLine("Media-Scan command", "--mhdd-log={0}", mhddLogPath);
DicConsole.DebugWriteLine("Media-Scan command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Media-Scan command", "--ibg-log={0}", ibgLog);
DicConsole.DebugWriteLine("Media-Scan command", "--mhdd-log={0}", mhddLog);
DicConsole.DebugWriteLine("Media-Scan command", "--verbose={0}", verbose);
if(devicePath.Length == 2 &&
devicePath[1] == ':' &&
@@ -139,7 +118,7 @@ namespace DiscImageChef.Commands
Statistics.AddDevice(dev);
var scanner = new MediaScan(mhddLogPath, ibgLogPath, devicePath, dev);
var scanner = new MediaScan(mhddLog, ibgLog, devicePath, dev);
scanner.UpdateStatus += Progress.UpdateStatus;
scanner.StoppingErrorMessage += Progress.ErrorMessage;
scanner.UpdateProgress += Progress.UpdateProgress;
@@ -177,9 +156,13 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine();
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
// ReSharper disable CompareOfFloatsByEqualityOperator
if(results.SeekTotal != 0 ||
results.SeekMin != double.MaxValue ||
results.SeekMax != double.MinValue)
// ReSharper restore CompareOfFloatsByEqualityOperator
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.WriteLine("Testing {0} seeks, longest seek took {1:F3} ms, fastest one took {2:F3} ms. ({3:F3} ms average)",
results.SeekTimes, results.SeekMax, results.SeekMin, results.SeekTotal / 1000);

View File

@@ -30,93 +30,89 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class PrintHexCommand : Command
internal class PrintHexCommand : Command
{
string inputFile;
ulong length = 1;
bool longSectors;
bool showHelp;
ulong? startSector;
ushort widthBytes = 32;
public PrintHexCommand() : base("printhex", "Prints a sector, in hexadecimal values, to the console.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--length", "-l"
}, "How many sectors to print.")
{
Argument = new Argument<ulong>(() => 1), Required = false
});
Add(new Option(new[]
{
"--long-sectors", "-r"
}, "Print sectors with tags included.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Add(new Option(new[]
{
"--start", "-s"
}, "Starting sector.")
{
Argument = new Argument<ulong>(), Required = true
});
Add(new Option(new[]
{
"--width", "-w"
}, "How many bytes to print per line.")
{
Argument = new Argument<ushort>(() => 32), Required = false
});
AddArgument(new Argument<string>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"length|l=", "How many sectors to print.", (ulong ul) => length = ul},
{"long-sectors|r", "Print sectors with tags included.", b => longSectors = b != null},
{"start|s=", "Name of character encoding to use.", (ulong ul) => startSector = ul},
{"width|w=", "How many bytes to print per line.", (ushort us) => widthBytes = us},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "Media image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, string imagePath, ulong length, bool longSectors, ulong startSector,
ushort widthBytes)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("print-hex");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
if(startSector is null)
{
DicConsole.ErrorWriteLine("Missing starting sector.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("PrintHex command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("PrintHex command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("PrintHex command", "--length={0}", length);
DicConsole.DebugWriteLine("PrintHex command", "--debug={0}", debug);
DicConsole.DebugWriteLine("PrintHex command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("PrintHex command", "--length={0}", length);
DicConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", longSectors);
DicConsole.DebugWriteLine("PrintHex command", "--start={0}", startSector);
DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", widthBytes);
DicConsole.DebugWriteLine("PrintHex command", "--start={0}", startSector);
DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", verbose);
DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", widthBytes);
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -124,7 +120,8 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying");
return (int)ErrorNumber.UnrecognizedFormat;
return(int)ErrorNumber.UnrecognizedFormat;
}
inputFormat.Open(inputFilter);
@@ -135,28 +132,29 @@ namespace DiscImageChef.Commands
if(inputFormat.Info.ReadableSectorTags == null)
{
DicConsole
.WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
DicConsole.
WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
longSectors = false;
}
else
{
if(inputFormat.Info.ReadableSectorTags.Count == 0)
{
DicConsole
.WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
DicConsole.
WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
longSectors = false;
}
}
byte[] sector = longSectors
? inputFormat.ReadSectorLong(startSector.Value + i)
: inputFormat.ReadSector(startSector.Value + i);
byte[] sector = longSectors ? inputFormat.ReadSectorLong(startSector + i)
: inputFormat.ReadSector(startSector + i);
PrintHex.PrintHexArray(sector, widthBytes);
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -33,71 +33,42 @@
// TODO: Fix errors returned
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
using Remote = DiscImageChef.Devices.Remote.Remote;
namespace DiscImageChef.Commands
{
internal class RemoteCommand : Command
{
string host;
bool showHelp;
public RemoteCommand() : base("remote", "Tests connection to a DiscImageChef Remote Server.") =>
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] host", "",
Help,
{
"help|h|?", "Show this message and exit.", v => showHelp = v != null
}
};
public override int Invoke(IEnumerable<string> arguments)
public RemoteCommand() : base("remote", "Tests connection to a DiscImageChef Remote Server.")
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
AddArgument(new Argument<string>
{
Options.WriteOptionDescriptions(CommandSet.Out);
Arity = ArgumentArity.ExactlyOne, Description = "dicremote host", Name = "host"
});
return(int)ErrorNumber.HelpRequested;
}
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
static int Invoke(bool debug, bool verbose, string host)
{
MainClass.PrintCopyright();
if(MainClass.Debug)
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose)
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
// Statistics.AddCommand("remote");
Statistics.AddCommand("remote");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return(int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return(int)ErrorNumber.MissingArgument;
}
host = extra[0];
DicConsole.DebugWriteLine("Remote command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Remote command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Remote command", "--host={0}", host);
DicConsole.DebugWriteLine("Remote command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Remote command", "--verbose={0}", verbose);
try
{

View File

@@ -30,62 +30,44 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine.Invocation;
using System.Linq;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Database;
using DiscImageChef.Database.Models;
using Mono.Options;
using Command = Mono.Options.Command;
using Command = System.CommandLine.Command;
namespace DiscImageChef.Commands
{
class StatisticsCommand : Command
internal class StatisticsCommand : Command
{
bool showHelp;
public StatisticsCommand() : base("stats", "Shows statistics.") =>
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
public StatisticsCommand() : base("stats", "Shows statistics.")
static int Invoke(bool debug, bool verbose)
{
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name}",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count > 0)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
DicContext ctx = DicContext.Create(Settings.Settings.LocalDbPath);
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(!ctx.Commands.Any() && !ctx.Filesystems.Any() && !ctx.Filters.Any() && !ctx.MediaFormats.Any() &&
!ctx.Medias.Any() && !ctx.Partitions.Any() && !ctx.SeenDevices.Any())
var ctx = DicContext.Create(Settings.Settings.LocalDbPath);
if(!ctx.Commands.Any() &&
!ctx.Filesystems.Any() &&
!ctx.Filters.Any() &&
!ctx.MediaFormats.Any() &&
!ctx.Medias.Any() &&
!ctx.Partitions.Any() &&
!ctx.SeenDevices.Any())
{
DicConsole.WriteLine("There are no statistics.");
return (int)ErrorNumber.NothingFound;
return(int)ErrorNumber.NothingFound;
}
bool thereAreStats = false;
@@ -97,11 +79,13 @@ namespace DiscImageChef.Commands
foreach(string command in ctx.Commands.OrderBy(c => c.Name).Select(c => c.Name).Distinct())
{
ulong count = ctx.Commands.Where(c => c.Name == command && c.Synchronized).Select(c => c.Count)
.FirstOrDefault();
ulong count = ctx.Commands.Where(c => c.Name == command && c.Synchronized).Select(c => c.Count).
FirstOrDefault();
count += (ulong)ctx.Commands.LongCount(c => c.Name == command && !c.Synchronized);
if(count == 0) continue;
if(count == 0)
continue;
DicConsole.WriteLine("You have called the {0} command {1} times.", command, count);
thereAreStats = true;
@@ -117,11 +101,13 @@ namespace DiscImageChef.Commands
foreach(string filter in ctx.Filters.OrderBy(c => c.Name).Select(c => c.Name).Distinct())
{
ulong count = ctx.Filters.Where(c => c.Name == filter && c.Synchronized).Select(c => c.Count)
.FirstOrDefault();
ulong count = ctx.Filters.Where(c => c.Name == filter && c.Synchronized).Select(c => c.Count).
FirstOrDefault();
count += (ulong)ctx.Filters.LongCount(c => c.Name == filter && !c.Synchronized);
if(count == 0) continue;
if(count == 0)
continue;
DicConsole.WriteLine("Filter {0} has been found {1} times.", filter, count);
thereAreStats = true;
@@ -137,11 +123,13 @@ namespace DiscImageChef.Commands
foreach(string format in ctx.MediaFormats.OrderBy(c => c.Name).Select(c => c.Name).Distinct())
{
ulong count = ctx.MediaFormats.Where(c => c.Name == format && c.Synchronized).Select(c => c.Count)
.FirstOrDefault();
ulong count = ctx.MediaFormats.Where(c => c.Name == format && c.Synchronized).Select(c => c.Count).
FirstOrDefault();
count += (ulong)ctx.MediaFormats.LongCount(c => c.Name == format && !c.Synchronized);
if(count == 0) continue;
if(count == 0)
continue;
DicConsole.WriteLine("Format {0} has been found {1} times.", format, count);
thereAreStats = true;
@@ -157,11 +145,13 @@ namespace DiscImageChef.Commands
foreach(string partition in ctx.Partitions.OrderBy(c => c.Name).Select(c => c.Name).Distinct())
{
ulong count = ctx.Partitions.Where(c => c.Name == partition && c.Synchronized).Select(c => c.Count)
.FirstOrDefault();
ulong count = ctx.Partitions.Where(c => c.Name == partition && c.Synchronized).Select(c => c.Count).
FirstOrDefault();
count += (ulong)ctx.Partitions.LongCount(c => c.Name == partition && !c.Synchronized);
if(count == 0) continue;
if(count == 0)
continue;
DicConsole.WriteLine("Partitioning scheme {0} has been found {1} times.", partition, count);
thereAreStats = true;
@@ -177,11 +167,13 @@ namespace DiscImageChef.Commands
foreach(string filesystem in ctx.Filesystems.OrderBy(c => c.Name).Select(c => c.Name).Distinct())
{
ulong count = ctx.Filesystems.Where(c => c.Name == filesystem && c.Synchronized)
.Select(c => c.Count).FirstOrDefault();
ulong count = ctx.Filesystems.Where(c => c.Name == filesystem && c.Synchronized).
Select(c => c.Count).FirstOrDefault();
count += (ulong)ctx.Filesystems.LongCount(c => c.Name == filesystem && !c.Synchronized);
if(count == 0) continue;
if(count == 0)
continue;
DicConsole.WriteLine("Filesystem {0} has been found {1} times.", filesystem, count);
thereAreStats = true;
@@ -195,10 +187,10 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Device statistics");
DicConsole.WriteLine("=================");
foreach(DeviceStat ds in ctx.SeenDevices.OrderBy(ds => ds.Manufacturer).ThenBy(ds => ds.Model)
.ThenBy(ds => ds.Revision).ThenBy(ds => ds.Bus))
DicConsole
.WriteLine("Device model {0}, manufactured by {1}, with revision {2} and attached via {3}.",
foreach(DeviceStat ds in ctx.SeenDevices.OrderBy(ds => ds.Manufacturer).ThenBy(ds => ds.Model).
ThenBy(ds => ds.Revision).ThenBy(ds => ds.Bus))
DicConsole.
WriteLine("Device model {0}, manufactured by {1}, with revision {2} and attached via {3}.",
ds.Model, ds.Manufacturer, ds.Revision, ds.Bus);
DicConsole.WriteLine();
@@ -212,8 +204,9 @@ namespace DiscImageChef.Commands
foreach(string media in ctx.Medias.OrderBy(ms => ms.Type).Select(ms => ms.Type).Distinct())
{
ulong count = ctx.Medias.Where(c => c.Type == media && c.Synchronized && c.Real)
.Select(c => c.Count).FirstOrDefault();
ulong count = ctx.Medias.Where(c => c.Type == media && c.Synchronized && c.Real).
Select(c => c.Count).FirstOrDefault();
count += (ulong)ctx.Medias.LongCount(c => c.Type == media && !c.Synchronized && c.Real);
if(count > 0)
@@ -222,11 +215,13 @@ namespace DiscImageChef.Commands
thereAreStats = true;
}
count = ctx.Medias.Where(c => c.Type == media && c.Synchronized && !c.Real).Select(c => c.Count)
.FirstOrDefault();
count = ctx.Medias.Where(c => c.Type == media && c.Synchronized && !c.Real).Select(c => c.Count).
FirstOrDefault();
count += (ulong)ctx.Medias.LongCount(c => c.Type == media && !c.Synchronized && !c.Real);
if(count == 0) continue;
if(count == 0)
continue;
DicConsole.WriteLine("Media type {0} has been found {1} times in a media image.", media, count);
thereAreStats = true;
@@ -235,8 +230,10 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine();
}
if(!thereAreStats) DicConsole.WriteLine("There are no statistics.");
return (int)ErrorNumber.NoError;
if(!thereAreStats)
DicConsole.WriteLine("There are no statistics.");
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -30,62 +30,44 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class UpdateCommand : Command
internal class UpdateCommand : Command
{
readonly bool masterDbUpdate;
bool showHelp;
readonly bool _masterDbUpdate;
public UpdateCommand(bool masterDbUpdate) : base("update", "Updates the database.")
{
this.masterDbUpdate = masterDbUpdate;
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name}",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
_masterDbUpdate = masterDbUpdate;
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
int Invoke(bool debug, bool verbose)
{
if(masterDbUpdate) return (int)ErrorNumber.NoError;
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
if(_masterDbUpdate)
return(int)ErrorNumber.NoError;
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count > 0)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
DicConsole.DebugWriteLine("Update command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Update command", "--verbose={0}", MainClass.Verbose);
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
DicConsole.DebugWriteLine("Update command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Update command", "--verbose={0}", verbose);
DoUpdate(false);
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
internal static void DoUpdate(bool create)

View File

@@ -32,81 +32,71 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
class VerifyCommand : Command
internal class VerifyCommand : Command
{
string inputFile;
bool showHelp;
bool verifyDisc = true;
bool verifySectors = true;
public VerifyCommand() : base("verify", "Verifies a disc image integrity, and if supported, sector integrity.")
{
Options = new OptionSet
Add(new Option(new[]
{
"--verify-disc", "-w"
}, "Verify disc image if supported.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--verify-sectors", "-s"
}, "Verify all sectors if supported.")
{
Argument = new Argument<bool>(() => true), Required = false
});
AddArgument(new Argument<string>
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"verify-disc|w", "Verify disc image if supported.", b => verifyDisc = b != null},
{"verify-sectors|s", "Verify all sectors if supported.", b => verifySectors = b != null},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
Arity = ArgumentArity.ExactlyOne, Description = "Disc image path", Name = "image-path"
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
}
public override int Invoke(IEnumerable<string> arguments)
static int Invoke(bool debug, bool verbose, string imagePath, bool verifyDisc = true, bool verifySectors = true)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return (int)ErrorNumber.HelpRequested;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(debug)
DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(verbose)
DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Statistics.AddCommand("verify");
if(extra.Count > 1)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return (int)ErrorNumber.UnexpectedArgumentCount;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return (int)ErrorNumber.MissingArgument;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("Verify command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Verify command", "--input={0}", inputFile);
DicConsole.DebugWriteLine("Verify command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Verify command", "--verify-disc={0}", verifyDisc);
DicConsole.DebugWriteLine("Verify command", "--debug={0}", debug);
DicConsole.DebugWriteLine("Verify command", "--input={0}", imagePath);
DicConsole.DebugWriteLine("Verify command", "--verbose={0}", verbose);
DicConsole.DebugWriteLine("Verify command", "--verify-disc={0}", verifyDisc);
DicConsole.DebugWriteLine("Verify command", "--verify-sectors={0}", verifySectors);
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(inputFile);
var filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(imagePath);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return (int)ErrorNumber.CannotOpenFile;
return(int)ErrorNumber.CannotOpenFile;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -114,7 +104,8 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying");
return (int)ErrorNumber.FormatNotFound;
return(int)ErrorNumber.FormatNotFound;
}
inputFormat.Open(inputFilter);
@@ -123,18 +114,19 @@ namespace DiscImageChef.Commands
Statistics.AddFilter(inputFilter.Name);
bool? correctImage = null;
long totalSectors = 0;
long errorSectors = 0;
bool? correctSectors = null;
long unknownSectors = 0;
IVerifiableImage verifiableImage = inputFormat as IVerifiableImage;
IVerifiableSectorsImage verifiableSectorsImage = inputFormat as IVerifiableSectorsImage;
var verifiableImage = inputFormat as IVerifiableImage;
var verifiableSectorsImage = inputFormat as IVerifiableSectorsImage;
if(verifiableImage is null && verifiableSectorsImage is null)
if(verifiableImage is null &&
verifiableSectorsImage is null)
{
DicConsole.ErrorWriteLine("The specified image does not support any kind of verification");
return (int)ErrorNumber.NotVerificable;
return(int)ErrorNumber.NotVerificable;
}
if(verifyDisc && verifiableImage != null)
@@ -149,12 +141,15 @@ namespace DiscImageChef.Commands
{
case true:
DicConsole.WriteLine("Disc image checksums are correct");
break;
case false:
DicConsole.WriteLine("Disc image checksums are incorrect");
break;
case null:
DicConsole.WriteLine("Disc image does not contain checksums");
break;
}
@@ -175,6 +170,7 @@ namespace DiscImageChef.Commands
ulong currentSectorAll = 0;
startCheck = DateTime.UtcNow;
foreach(Track currentTrack in inputTracks)
{
ulong remainingSectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector;
@@ -185,20 +181,20 @@ namespace DiscImageChef.Commands
DicConsole.Write("\rChecking sector {0} of {1}, on track {2}", currentSectorAll,
inputFormat.Info.Sectors, currentTrack.TrackSequence);
List<ulong> tempfailingLbas;
List<ulong> tempunknownLbas;
List<ulong> tempFailingLbas;
List<ulong> tempUnknownLbas;
if(remainingSectors < 512)
opticalMediaImage.VerifySectors(currentSector, (uint)remainingSectors,
currentTrack.TrackSequence, out tempfailingLbas,
out tempunknownLbas);
currentTrack.TrackSequence, out tempFailingLbas,
out tempUnknownLbas);
else
opticalMediaImage.VerifySectors(currentSector, 512, currentTrack.TrackSequence,
out tempfailingLbas, out tempunknownLbas);
out tempFailingLbas, out tempUnknownLbas);
failingLbas.AddRange(tempfailingLbas);
failingLbas.AddRange(tempFailingLbas);
unknownLbas.AddRange(tempunknownLbas);
unknownLbas.AddRange(tempUnknownLbas);
if(remainingSectors < 512)
{
@@ -223,23 +219,24 @@ namespace DiscImageChef.Commands
ulong currentSector = 0;
startCheck = DateTime.UtcNow;
while(remainingSectors > 0)
{
DicConsole.Write("\rChecking sector {0} of {1}", currentSector, inputFormat.Info.Sectors);
List<ulong> tempfailingLbas;
List<ulong> tempunknownLbas;
List<ulong> tempFailingLbas;
List<ulong> tempUnknownLbas;
if(remainingSectors < 512)
verifiableSectorsImage.VerifySectors(currentSector, (uint)remainingSectors,
out tempfailingLbas, out tempunknownLbas);
out tempFailingLbas, out tempUnknownLbas);
else
verifiableSectorsImage.VerifySectors(currentSector, 512, out tempfailingLbas,
out tempunknownLbas);
verifiableSectorsImage.VerifySectors(currentSector, 512, out tempFailingLbas,
out tempUnknownLbas);
failingLbas.AddRange(tempfailingLbas);
failingLbas.AddRange(tempFailingLbas);
unknownLbas.AddRange(tempunknownLbas);
unknownLbas.AddRange(tempUnknownLbas);
if(remainingSectors < 512)
{
@@ -262,15 +259,20 @@ namespace DiscImageChef.Commands
if(unknownSectors > 0)
DicConsole.WriteLine("There is at least one sector that does not contain a checksum");
if(errorSectors > 0)
DicConsole.WriteLine("There is at least one sector with incorrect checksum or errors");
if(unknownSectors == 0 && errorSectors == 0) DicConsole.WriteLine("All sector checksums are correct");
if(unknownSectors == 0 &&
errorSectors == 0)
DicConsole.WriteLine("All sector checksums are correct");
DicConsole.VerboseWriteLine("Checking sector checksums took {0} seconds", checkTime.TotalSeconds);
if(MainClass.Verbose)
if(verbose)
{
DicConsole.VerboseWriteLine("LBAs with error:");
if(failingLbas.Count == (int)inputFormat.Info.Sectors)
DicConsole.VerboseWriteLine("\tall sectors.");
else
@@ -278,6 +280,7 @@ namespace DiscImageChef.Commands
DicConsole.VerboseWriteLine("\t{0}", t);
DicConsole.WriteLine("LBAs without checksum:");
if(unknownLbas.Count == (int)inputFormat.Info.Sectors)
DicConsole.VerboseWriteLine("\tall sectors.");
else
@@ -290,27 +293,26 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Total unknowns.......... {0}", unknownLbas.Count);
DicConsole.WriteLine("Total errors+unknowns... {0}", failingLbas.Count + unknownLbas.Count);
totalSectors = (long)inputFormat.Info.Sectors;
errorSectors = failingLbas.Count;
unknownSectors = unknownLbas.Count;
if(failingLbas.Count > 0) correctSectors = false;
else if((ulong)unknownLbas.Count < inputFormat.Info.Sectors) correctSectors = true;
if(failingLbas.Count > 0)
correctSectors = false;
else if((ulong)unknownLbas.Count < inputFormat.Info.Sectors)
correctSectors = true;
}
switch(correctImage)
{
case null when correctSectors is null: return (int)ErrorNumber.NotVerificable;
case null when correctSectors == false: return (int)ErrorNumber.BadSectorsImageNotVerified;
case null when correctSectors == true: return (int)ErrorNumber.CorrectSectorsImageNotVerified;
case false when correctSectors is null: return (int)ErrorNumber.BadImageSectorsNotVerified;
case false when correctSectors == false: return (int)ErrorNumber.BadImageBadSectors;
case false when correctSectors == true: return (int)ErrorNumber.CorrectSectorsBadImage;
case true when correctSectors is null: return (int)ErrorNumber.CorrectImageSectorsNotVerified;
case true when correctSectors == false: return (int)ErrorNumber.CorrectImageBadSectors;
case true when correctSectors == true: return (int)ErrorNumber.NoError;
case null when correctSectors is null: return(int)ErrorNumber.NotVerificable;
case null when correctSectors == false: return(int)ErrorNumber.BadSectorsImageNotVerified;
case null when correctSectors == true: return(int)ErrorNumber.CorrectSectorsImageNotVerified;
case false when correctSectors is null: return(int)ErrorNumber.BadImageSectorsNotVerified;
case false when correctSectors == false: return(int)ErrorNumber.BadImageBadSectors;
case false when correctSectors == true: return(int)ErrorNumber.CorrectSectorsBadImage;
case true when correctSectors is null: return(int)ErrorNumber.CorrectImageSectorsNotVerified;
case true when correctSectors == false: return(int)ErrorNumber.CorrectImageBadSectors;
case true when correctSectors == true: return(int)ErrorNumber.NoError;
}
return (int)ErrorNumber.NoError;
return(int)ErrorNumber.NoError;
}
}
}

View File

@@ -264,8 +264,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Mono.Options" Version="5.3.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="System.CommandLine.Experimental" Version="0.3.0-alpha.19577.1" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.3.0" />

View File

@@ -31,44 +31,43 @@
// ****************************************************************************/
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using DiscImageChef.Commands;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Database;
using DiscImageChef.Settings;
using Microsoft.EntityFrameworkCore;
using Mono.Options;
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
namespace DiscImageChef
{
internal class MainClass
{
internal static bool Verbose;
internal static bool Debug;
internal static string AssemblyCopyright;
internal static string AssemblyTitle;
internal static AssemblyInformationalVersionAttribute AssemblyVersion;
static string _assemblyCopyright;
static string _assemblyTitle;
static AssemblyInformationalVersionAttribute _assemblyVersion;
[STAThread]
public static int Main(string[] args)
{
var attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
AssemblyTitle = ((AssemblyTitleAttribute) attributes[0]).Title;
attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
AssemblyVersion =
object[] attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
_assemblyTitle = ((AssemblyTitleAttribute)attributes[0]).Title;
attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
_assemblyVersion =
Attribute.GetCustomAttribute(typeof(MainClass).Assembly, typeof(AssemblyInformationalVersionAttribute))
as AssemblyInformationalVersionAttribute;
AssemblyCopyright = ((AssemblyCopyrightAttribute) attributes[0]).Copyright;
DicConsole.WriteLineEvent += System.Console.WriteLine;
DicConsole.WriteEvent += System.Console.Write;
_assemblyCopyright = ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
DicConsole.WriteLineEvent += System.Console.WriteLine;
DicConsole.WriteEvent += System.Console.Write;
DicConsole.ErrorWriteLineEvent += System.Console.Error.WriteLine;
Settings.Settings.LoadSettings();
@@ -77,16 +76,17 @@ namespace DiscImageChef
ctx.Database.Migrate();
ctx.SaveChanges();
var masterDbUpdate = false;
if (!File.Exists(Settings.Settings.MasterDbPath))
bool masterDbUpdate = false;
if(!File.Exists(Settings.Settings.MasterDbPath))
{
masterDbUpdate = true;
UpdateCommand.DoUpdate(true);
}
var mctx = DicContext.Create(Settings.Settings.MasterDbPath);
var masterContext = DicContext.Create(Settings.Settings.MasterDbPath);
if(mctx.Database.GetPendingMigrations().Any())
if(masterContext.Database.GetPendingMigrations().Any())
{
DicConsole.WriteLine("New database version, updating...");
@@ -103,84 +103,76 @@ namespace DiscImageChef
UpdateCommand.DoUpdate(true);
}
if ((args.Length < 1 || args[0].ToLowerInvariant() != "gui") &&
Settings.Settings.Current.GdprCompliance < DicSettings.GdprLevel)
if((args.Length < 1 || args[0].ToLowerInvariant() != "gui") &&
Settings.Settings.Current.GdprCompliance < DicSettings.GdprLevel)
new ConfigureCommand(true, true).Invoke(args);
Statistics.LoadStats();
if (Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.ShareStats)
Task.Run(() => { Statistics.SubmitStats(); });
var currentPlatform = DetectOS.GetRealPlatformID();
Statistics.LoadStats();
if(Settings.Settings.Current.Stats != null &&
Settings.Settings.Current.Stats.ShareStats)
Task.Run(Statistics.SubmitStats);
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var commands = new CommandSet("DiscImageChef")
{
$"{AssemblyTitle} {AssemblyVersion?.InformationalVersion}",
$"{AssemblyCopyright}",
"",
"usage: DiscImageChef COMMAND [OPTIONS]",
"",
"Global options:",
{"verbose|v", "Shows verbose output.", b => Verbose = b != null},
{"debug|d", "Shows debug output from plugins.", b => Debug = b != null},
"",
"Available commands:",
new AnalyzeCommand(),
new BenchmarkCommand(),
new ChecksumCommand(),
new CompareCommand(),
new ConfigureCommand(false, false),
new ConvertImageCommand(),
new CreateSidecarCommand(),
new DecodeCommand()
};
if (currentPlatform == PlatformID.FreeBSD || currentPlatform == PlatformID.Linux ||
currentPlatform == PlatformID.Win32NT)
{
commands.Add(new DeviceInfoCommand());
commands.Add(new DeviceReportCommand());
commands.Add(new DumpMediaCommand());
}
commands.Add(new EntropyCommand());
commands.Add(new ExtractFilesCommand());
commands.Add(new FormatsCommand());
commands.Add(new ImageInfoCommand());
if (currentPlatform == PlatformID.FreeBSD || currentPlatform == PlatformID.Linux ||
currentPlatform == PlatformID.Win32NT) commands.Add(new ListDevicesCommand());
commands.Add(new ListEncodingsCommand());
commands.Add(new ListNamespacesCommand());
commands.Add(new ListOptionsCommand());
commands.Add(new LsCommand());
if (currentPlatform == PlatformID.FreeBSD || currentPlatform == PlatformID.Linux ||
currentPlatform == PlatformID.Win32NT)
{
commands.Add(new MediaInfoCommand());
commands.Add(new MediaScanCommand());
}
commands.Add(new PrintHexCommand());
commands.Add(new StatisticsCommand());
commands.Add(new UpdateCommand(masterDbUpdate));
commands.Add(new VerifyCommand());
commands.Add(new RemoteCommand());
var ret = commands.Run(args);
Statistics.SaveStats();
return ret;
var rootCommand = new RootCommand
{
new Option(new[]
{
"--verbose", "-v"
}, "Shows verbose output.")
{
Argument = new Argument<bool>(() => false)
},
new Option(new[]
{
"--debug", "-d"
}, "Shows debug output from plugins.")
{
Argument = new Argument<bool>(() => false)
}
};
rootCommand.Description =
$"{_assemblyTitle} {_assemblyVersion?.InformationalVersion}\n{_assemblyCopyright}";
rootCommand.AddCommand(new AnalyzeCommand());
rootCommand.AddCommand(new BenchmarkCommand());
rootCommand.AddCommand(new ChecksumCommand());
rootCommand.AddCommand(new CompareCommand());
rootCommand.AddCommand(new ConfigureCommand(false, false));
rootCommand.AddCommand(new ConvertImageCommand());
rootCommand.AddCommand(new CreateSidecarCommand());
rootCommand.AddCommand(new DecodeCommand());
rootCommand.AddCommand(new DeviceInfoCommand());
rootCommand.AddCommand(new DeviceReportCommand());
rootCommand.AddCommand(new DumpMediaCommand());
rootCommand.AddCommand(new EntropyCommand());
rootCommand.AddCommand(new ExtractFilesCommand());
rootCommand.AddCommand(new FormatsCommand());
rootCommand.AddCommand(new ImageInfoCommand());
rootCommand.AddCommand(new ListDevicesCommand());
rootCommand.AddCommand(new ListEncodingsCommand());
rootCommand.AddCommand(new ListNamespacesCommand());
rootCommand.AddCommand(new ListOptionsCommand());
rootCommand.AddCommand(new LsCommand());
rootCommand.AddCommand(new MediaInfoCommand());
rootCommand.AddCommand(new MediaScanCommand());
rootCommand.AddCommand(new PrintHexCommand());
rootCommand.AddCommand(new StatisticsCommand());
rootCommand.AddCommand(new UpdateCommand(masterDbUpdate));
rootCommand.AddCommand(new VerifyCommand());
rootCommand.AddCommand(new RemoteCommand());
return rootCommand.Invoke(args);
}
internal static void PrintCopyright()
{
DicConsole.WriteLine("{0} {1}", AssemblyTitle, AssemblyVersion?.InformationalVersion);
DicConsole.WriteLine("{0}", AssemblyCopyright);
DicConsole.WriteLine("{0} {1}", _assemblyTitle, _assemblyVersion?.InformationalVersion);
DicConsole.WriteLine("{0}", _assemblyCopyright);
DicConsole.WriteLine();
}
}