Use Mono.Options as command line parser.

This commit is contained in:
2019-01-05 16:59:23 +00:00
parent bbedcfe843
commit 104bc55c5e
30 changed files with 2221 additions and 1392 deletions

View File

@@ -33,6 +33,7 @@
<e p="Entropy.cs" t="Include" /> <e p="Entropy.cs" t="Include" />
<e p="ExtractFiles.cs" t="Include" /> <e p="ExtractFiles.cs" t="Include" />
<e p="Formats.cs" t="Include" /> <e p="Formats.cs" t="Include" />
<e p="Gui.cs" t="Include" />
<e p="ImageInfo.cs" t="Include" /> <e p="ImageInfo.cs" t="Include" />
<e p="ListDevices.cs" t="Include" /> <e p="ListDevices.cs" t="Include" />
<e p="ListEncodings.cs" t="Include" /> <e p="ListEncodings.cs" t="Include" />
@@ -49,7 +50,6 @@
<e p="Info.plist" t="Include" /> <e p="Info.plist" t="Include" />
<e p="MacIcon.icns" t="Include" /> <e p="MacIcon.icns" t="Include" />
<e p="Main.cs" t="Include" /> <e p="Main.cs" t="Include" />
<e p="Options.cs" t="Include" />
<e p="Progress.cs" t="Include" /> <e p="Progress.cs" t="Include" />
<e p="Properties" t="Include"> <e p="Properties" t="Include">
<e p="launchSettings.json" t="Include" /> <e p="launchSettings.json" t="Include" />

View File

@@ -37,41 +37,92 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Analyze class AnalyzeCommand : Command
{ {
internal static void DoAnalyze(AnalyzeOptions options) 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.")
{ {
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Analyze command", "--input={0}", options.InputFile); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Analyze command", "--filesystems={0}", options.SearchForFilesystems); $"{MainClass.AssemblyCopyright}",
DicConsole.DebugWriteLine("Analyze command", "--partitions={0}", options.SearchForPartitions); "",
DicConsole.DebugWriteLine("Analyze command", "--encoding={0}", options.EncodingName); $"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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 2;
} }
Encoding encoding = null; Encoding encoding = null;
if(options.EncodingName != null) if(encodingName != null)
try try
{ {
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName); encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
} }
catch(ArgumentException) catch(ArgumentException)
{ {
DicConsole.ErrorWriteLine("Specified encoding is not supported."); DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return; return 5;
} }
PluginBase plugins = GetPluginBase.Instance; PluginBase plugins = GetPluginBase.Instance;
@@ -85,10 +136,10 @@ namespace DiscImageChef.Commands
if(imageFormat == null) if(imageFormat == null)
{ {
DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
return; return 3;
} }
if(options.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
imageFormat.Id); imageFormat.Id);
else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
@@ -100,31 +151,31 @@ namespace DiscImageChef.Commands
{ {
DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given"); DicConsole.WriteLine("No error given");
return; return 4;
} }
if(options.Verbose) if(MainClass.Verbose)
{ {
Core.ImageInfo.PrintImageInfo(imageFormat); ImageInfo.PrintImageInfo(imageFormat);
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
Core.Statistics.AddMediaFormat(imageFormat.Format); Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddMedia(imageFormat.Info.MediaType, false); Statistics.AddMedia(imageFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
} }
catch(Exception ex) catch(Exception ex)
{ {
DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message); DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
DicConsole.DebugWriteLine("Analyze command", "Stack trace: {0}", ex.StackTrace); DicConsole.DebugWriteLine("Analyze command", "Stack trace: {0}", ex.StackTrace);
return; return -1;
} }
List<string> idPlugins; List<string> idPlugins;
IFilesystem plugin; IFilesystem plugin;
string information; string information;
if(options.SearchForPartitions) if(searchForPartitions)
{ {
List<Partition> partitions = Core.Partitions.GetAll(imageFormat); List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
Core.Partitions.AddSchemesToStats(partitions); Core.Partitions.AddSchemesToStats(partitions);
@@ -132,10 +183,10 @@ namespace DiscImageChef.Commands
if(partitions.Count == 0) if(partitions.Count == 0)
{ {
DicConsole.DebugWriteLine("Analyze command", "No partitions found"); DicConsole.DebugWriteLine("Analyze command", "No partitions found");
if(!options.SearchForFilesystems) if(!searchForFilesystems)
{ {
DicConsole.WriteLine("No partitions founds, not searching for filesystems"); DicConsole.WriteLine("No partitions founds, not searching for filesystems");
return; return -2;
} }
checkraw = true; checkraw = true;
@@ -158,7 +209,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Partition description:"); DicConsole.WriteLine("Partition description:");
DicConsole.WriteLine(partitions[i].Description); DicConsole.WriteLine(partitions[i].Description);
if(!options.SearchForFilesystems) continue; if(!searchForFilesystems) continue;
DicConsole.WriteLine("Identifying filesystem on partition"); DicConsole.WriteLine("Identifying filesystem on partition");
@@ -174,7 +225,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine($"As identified by {plugin.Name}."); DicConsole.WriteLine($"As identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, partitions[i], out information, encoding); plugin.GetInformation(imageFormat, partitions[i], out information, encoding);
DicConsole.Write(information); DicConsole.Write(information);
Core.Statistics.AddFilesystem(plugin.XmlFsType.Type); Statistics.AddFilesystem(plugin.XmlFsType.Type);
} }
} }
else else
@@ -185,7 +236,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine($"Identified by {plugin.Name}."); DicConsole.WriteLine($"Identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, partitions[i], out information, encoding); plugin.GetInformation(imageFormat, partitions[i], out information, encoding);
DicConsole.Write("{0}", information); DicConsole.Write("{0}", information);
Core.Statistics.AddFilesystem(plugin.XmlFsType.Type); Statistics.AddFilesystem(plugin.XmlFsType.Type);
} }
} }
} }
@@ -212,7 +263,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine($"As identified by {plugin.Name}."); DicConsole.WriteLine($"As identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, wholePart, out information, encoding); plugin.GetInformation(imageFormat, wholePart, out information, encoding);
DicConsole.Write(information); DicConsole.Write(information);
Core.Statistics.AddFilesystem(plugin.XmlFsType.Type); Statistics.AddFilesystem(plugin.XmlFsType.Type);
} }
} }
else else
@@ -223,7 +274,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine($"Identified by {plugin.Name}."); DicConsole.WriteLine($"Identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, wholePart, out information, encoding); plugin.GetInformation(imageFormat, wholePart, out information, encoding);
DicConsole.Write(information); DicConsole.Write(information);
Core.Statistics.AddFilesystem(plugin.XmlFsType.Type); Statistics.AddFilesystem(plugin.XmlFsType.Type);
} }
} }
} }
@@ -234,7 +285,8 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Analyze command", ex.StackTrace); DicConsole.DebugWriteLine("Analyze command", ex.StackTrace);
} }
Core.Statistics.AddCommand("analyze"); Statistics.AddCommand("analyze");
return 0;
} }
} }
} }

View File

@@ -33,19 +33,60 @@
using System.Collections.Generic; using System.Collections.Generic;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Benchmark class BenchmarkCommand : Command
{ {
internal static void DoBenchmark(BenchmarkOptions options) int blockSize = 512;
{ int bufferSize = 128;
Dictionary<string, double> checksumTimes = new Dictionary<string, double>(); bool showHelp;
Core.Benchmark.InitProgressEvent += Progress.InitProgress;
Core.Benchmark.UpdateProgressEvent += Progress.UpdateProgress;
Core.Benchmark.EndProgressEvent += Progress.EndProgress;
BenchmarkResults results = Core.Benchmark.Do(options.BufferSize * 1024 * 1024, options.BlockSize); public BenchmarkCommand() : base("benchmark", "Benchmarks hashing and entropy calculation.")
{
Options = new OptionSet
{
$"{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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
DicConsole.DebugWriteLine("Benchmark command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Benchmark command", "--verbose={0}", MainClass.Verbose);
Benchmark.InitProgressEvent += Progress.InitProgress;
Benchmark.UpdateProgressEvent += Progress.UpdateProgress;
Benchmark.EndProgressEvent += Progress.EndProgress;
BenchmarkResults results = Benchmark.Do(bufferSize * 1024 * 1024, blockSize);
DicConsole.WriteLine("Took {0} seconds to fill buffer, {1:F3} MiB/sec.", results.FillTime, DicConsole.WriteLine("Took {0} seconds to fill buffer, {1:F3} MiB/sec.", results.FillTime,
results.FillSpeed); results.FillSpeed);
@@ -55,11 +96,8 @@ namespace DiscImageChef.Commands
results.EntropySpeed); results.EntropySpeed);
foreach(KeyValuePair<string, BenchmarkEntry> entry in results.Entries) foreach(KeyValuePair<string, BenchmarkEntry> entry in results.Entries)
{
checksumTimes.Add(entry.Key, entry.Value.TimeSpan);
DicConsole.WriteLine("Took {0} seconds to {1} buffer, {2:F3} MiB/sec.", entry.Value.TimeSpan, entry.Key, DicConsole.WriteLine("Took {0} seconds to {1} buffer, {2:F3} MiB/sec.", entry.Value.TimeSpan, entry.Key,
entry.Value.Speed); entry.Value.Speed);
}
DicConsole.WriteLine("Took {0} seconds to do all algorithms at the same time, {1:F3} MiB/sec.", DicConsole.WriteLine("Took {0} seconds to do all algorithms at the same time, {1:F3} MiB/sec.",
results.TotalTime, results.TotalSpeed); results.TotalTime, results.TotalSpeed);
@@ -70,7 +108,8 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Max memory used is {0} bytes", results.MaxMemory); DicConsole.WriteLine("Max memory used is {0} bytes", results.MaxMemory);
DicConsole.WriteLine("Min memory used is {0} bytes", results.MinMemory); DicConsole.WriteLine("Min memory used is {0} bytes", results.MinMemory);
Core.Statistics.AddCommand("benchmark"); Statistics.AddCommand("benchmark");
return 0;
} }
} }
} }

View File

@@ -37,43 +37,117 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs; using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
using Schemas; using Schemas;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Checksum class ChecksumCommand : Command
{ {
// How many sectors to read at once // How many sectors to read at once
const uint SECTORS_TO_READ = 256; const uint SECTORS_TO_READ = 256;
internal static void DoChecksum(ChecksumOptions options) bool doAdler32 = true;
bool doCrc16 = true;
bool doCrc32 = true;
bool doCrc64;
bool doFletcher16;
bool doFletcher32;
bool doMd5 = true;
bool doRipemd160;
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.")
{ {
DicConsole.DebugWriteLine("Checksum command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Checksum command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Checksum command", "--separated-tracks={0}", options.SeparatedTracks); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Checksum command", "--whole-disc={0}", options.WholeDisc); $"{MainClass.AssemblyCopyright}",
DicConsole.DebugWriteLine("Checksum command", "--input={0}", options.InputFile); "",
DicConsole.DebugWriteLine("Checksum command", "--adler32={0}", options.DoAdler32); $"usage: DiscImageChef {Name} [OPTIONS] imagefile",
DicConsole.DebugWriteLine("Checksum command", "--crc16={0}", options.DoCrc16); "",
DicConsole.DebugWriteLine("Checksum command", "--crc32={0}", options.DoCrc32); Help,
DicConsole.DebugWriteLine("Checksum command", "--crc64={0}", options.DoCrc64); {"adler32|a", "Calculates Adler-32.", b => doAdler32 = b != null},
DicConsole.DebugWriteLine("Checksum command", "--md5={0}", options.DoMd5); {"crc16", "Calculates CRC16.", b => doCrc16 = b != null},
DicConsole.DebugWriteLine("Checksum command", "--ripemd160={0}", options.DoRipemd160); {"crc32|c", "Calculates CRC32.", b => doCrc32 = b != null},
DicConsole.DebugWriteLine("Checksum command", "--sha1={0}", options.DoSha1); {"crc64", "Calculates CRC64 (ECMA).", b => doCrc64 = b != null},
DicConsole.DebugWriteLine("Checksum command", "--sha256={0}", options.DoSha256); {"fletcher16", "Calculates Fletcher-16.", b => doFletcher16 = b != null},
DicConsole.DebugWriteLine("Checksum command", "--sha384={0}", options.DoSha384); {"fletcher32", "Calculates Fletcher-32.", b => doFletcher32 = b != null},
DicConsole.DebugWriteLine("Checksum command", "--sha512={0}", options.DoSha512); {"md5|m", "Calculates MD5.", b => doMd5 = b != null},
DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", options.DoSpamSum); {"ripemd160", "Calculates RIPEMD160.", b => doRipemd160 = b != null},
DicConsole.DebugWriteLine("Checksum command", "--fletcher16={0}", options.DoFletcher16); {"separated-tracks|t", "Checksums each track separately.", b => separatedTracks = b != null},
DicConsole.DebugWriteLine("Checksum command", "--fletcher32={0}", options.DoFletcher32); {"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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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", "--ripemd160={0}", doRipemd160);
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);
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 1;
} }
IMediaImage inputFormat = ImageFormat.Detect(inputFilter); IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -81,44 +155,44 @@ namespace DiscImageChef.Commands
if(inputFormat == null) if(inputFormat == null)
{ {
DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming"); DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming");
return; return 2;
} }
inputFormat.Open(inputFilter); inputFormat.Open(inputFilter);
Core.Statistics.AddMediaFormat(inputFormat.Format); Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
EnableChecksum enabledChecksums = new EnableChecksum(); EnableChecksum enabledChecksums = new EnableChecksum();
if(options.DoAdler32) enabledChecksums |= EnableChecksum.Adler32; if(doAdler32) enabledChecksums |= EnableChecksum.Adler32;
if(options.DoCrc16) enabledChecksums |= EnableChecksum.Crc16; if(doCrc16) enabledChecksums |= EnableChecksum.Crc16;
if(options.DoCrc32) enabledChecksums |= EnableChecksum.Crc32; if(doCrc32) enabledChecksums |= EnableChecksum.Crc32;
if(options.DoCrc64) enabledChecksums |= EnableChecksum.Crc64; if(doCrc64) enabledChecksums |= EnableChecksum.Crc64;
if(options.DoMd5) enabledChecksums |= EnableChecksum.Md5; if(doMd5) enabledChecksums |= EnableChecksum.Md5;
if(options.DoRipemd160) enabledChecksums |= EnableChecksum.Ripemd160; if(doRipemd160) enabledChecksums |= EnableChecksum.Ripemd160;
if(options.DoSha1) enabledChecksums |= EnableChecksum.Sha1; if(doSha1) enabledChecksums |= EnableChecksum.Sha1;
if(options.DoSha256) enabledChecksums |= EnableChecksum.Sha256; if(doSha256) enabledChecksums |= EnableChecksum.Sha256;
if(options.DoSha384) enabledChecksums |= EnableChecksum.Sha384; if(doSha384) enabledChecksums |= EnableChecksum.Sha384;
if(options.DoSha512) enabledChecksums |= EnableChecksum.Sha512; if(doSha512) enabledChecksums |= EnableChecksum.Sha512;
if(options.DoSpamSum) enabledChecksums |= EnableChecksum.SpamSum; if(doSpamSum) enabledChecksums |= EnableChecksum.SpamSum;
if(options.DoFletcher16) enabledChecksums |= EnableChecksum.Fletcher16; if(doFletcher16) enabledChecksums |= EnableChecksum.Fletcher16;
if(options.DoFletcher32) enabledChecksums |= EnableChecksum.Fletcher32; if(doFletcher32) enabledChecksums |= EnableChecksum.Fletcher32;
Core.Checksum mediaChecksum = null; Checksum mediaChecksum = null;
if(inputFormat.Info.HasPartitions) if(inputFormat.Info.HasPartitions)
try try
{ {
Core.Checksum trackChecksum = null; Checksum trackChecksum = null;
if(options.WholeDisc) mediaChecksum = new Core.Checksum(enabledChecksums); if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums);
ulong previousTrackEnd = 0; ulong previousTrackEnd = 0;
List<Track> inputTracks = inputFormat.Tracks; List<Track> inputTracks = inputFormat.Tracks;
foreach(Track currentTrack in inputTracks) foreach(Track currentTrack in inputTracks)
{ {
if(currentTrack.TrackStartSector - previousTrackEnd != 0 && options.WholeDisc) if(currentTrack.TrackStartSector - previousTrackEnd != 0 && wholeDisc)
for(ulong i = previousTrackEnd + 1; i < currentTrack.TrackStartSector; i++) for(ulong i = previousTrackEnd + 1; i < currentTrack.TrackStartSector; i++)
{ {
DicConsole.Write("\rHashing track-less sector {0}", i); DicConsole.Write("\rHashing track-less sector {0}", i);
@@ -133,7 +207,7 @@ namespace DiscImageChef.Commands
currentTrack.TrackSequence, currentTrack.TrackStartSector, currentTrack.TrackSequence, currentTrack.TrackStartSector,
currentTrack.TrackEndSector); currentTrack.TrackEndSector);
if(options.SeparatedTracks) trackChecksum = new Core.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; ulong doneSectors = 0;
@@ -160,14 +234,14 @@ namespace DiscImageChef.Commands
doneSectors += sectors - doneSectors; doneSectors += sectors - doneSectors;
} }
if(options.WholeDisc) mediaChecksum?.Update(sector); if(wholeDisc) mediaChecksum?.Update(sector);
if(options.SeparatedTracks) trackChecksum?.Update(sector); if(separatedTracks) trackChecksum?.Update(sector);
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
if(options.SeparatedTracks) if(separatedTracks)
if(trackChecksum != null) if(trackChecksum != null)
foreach(ChecksumType chk in trackChecksum.End()) foreach(ChecksumType chk in trackChecksum.End())
DicConsole.WriteLine("Track {0}'s {1}: {2}", currentTrack.TrackSequence, chk.type, DicConsole.WriteLine("Track {0}'s {1}: {2}", currentTrack.TrackSequence, chk.type,
@@ -176,7 +250,7 @@ namespace DiscImageChef.Commands
previousTrackEnd = currentTrack.TrackEndSector; previousTrackEnd = currentTrack.TrackEndSector;
} }
if(inputFormat.Info.Sectors - previousTrackEnd != 0 && options.WholeDisc) if(inputFormat.Info.Sectors - previousTrackEnd != 0 && wholeDisc)
for(ulong i = previousTrackEnd + 1; i < inputFormat.Info.Sectors; i++) for(ulong i = previousTrackEnd + 1; i < inputFormat.Info.Sectors; i++)
{ {
DicConsole.Write("\rHashing track-less sector {0}", i); DicConsole.Write("\rHashing track-less sector {0}", i);
@@ -185,19 +259,19 @@ namespace DiscImageChef.Commands
mediaChecksum?.Update(hiddenSector); mediaChecksum?.Update(hiddenSector);
} }
if(options.WholeDisc) if(wholeDisc)
if(mediaChecksum != null) if(mediaChecksum != null)
foreach(ChecksumType chk in mediaChecksum.End()) foreach(ChecksumType chk in mediaChecksum.End())
DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value); DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value);
} }
catch(Exception ex) catch(Exception ex)
{ {
if(options.Debug) DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message); if(MainClass.Debug) DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message);
else DicConsole.WriteLine("Unable to get separate tracks, not checksumming them"); else DicConsole.WriteLine("Unable to get separate tracks, not checksumming them");
} }
else else
{ {
mediaChecksum = new Core.Checksum(enabledChecksums); mediaChecksum = new Checksum(enabledChecksums);
ulong sectors = inputFormat.Info.Sectors; ulong sectors = inputFormat.Info.Sectors;
DicConsole.WriteLine("Sectors {0}", sectors); DicConsole.WriteLine("Sectors {0}", sectors);
@@ -230,7 +304,8 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value); DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value);
} }
Core.Statistics.AddCommand("checksum"); Statistics.AddCommand("checksum");
return 0;
} }
} }
} }

View File

@@ -39,33 +39,80 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs; using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
using ImageInfo = DiscImageChef.CommonTypes.Structs.ImageInfo;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Compare class CompareCommand : Command
{ {
internal static void DoCompare(CompareOptions options) string InputFile1;
string InputFile2;
bool ShowHelp;
public CompareCommand() : base("compare", "Compares two disc images.")
{ {
DicConsole.DebugWriteLine("Compare command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Compare command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Compare command", "--input1={0}", options.InputFile1); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Compare command", "--input2={0}", options.InputFile2); $"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} imagefile1 imagefile2",
"",
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 0;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count > 2)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return 1;
}
if(extra.Count <= 1)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
InputFile1 = extra[0];
InputFile1 = 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(); FiltersList filtersList = new FiltersList();
IFilter inputFilter1 = filtersList.GetFilter(options.InputFile1); IFilter inputFilter1 = filtersList.GetFilter(InputFile1);
filtersList = new FiltersList(); filtersList = new FiltersList();
IFilter inputFilter2 = filtersList.GetFilter(options.InputFile2); IFilter inputFilter2 = filtersList.GetFilter(InputFile2);
if(inputFilter1 == null) if(inputFilter1 == null)
{ {
DicConsole.ErrorWriteLine("Cannot open input file 1"); DicConsole.ErrorWriteLine("Cannot open input file 1");
return; return 1;
} }
if(inputFilter2 == null) if(inputFilter2 == null)
{ {
DicConsole.ErrorWriteLine("Cannot open input file 2"); DicConsole.ErrorWriteLine("Cannot open input file 2");
return; return 2;
} }
IMediaImage input1Format = ImageFormat.Detect(inputFilter1); IMediaImage input1Format = ImageFormat.Detect(inputFilter1);
@@ -74,10 +121,10 @@ namespace DiscImageChef.Commands
if(input1Format == null) if(input1Format == null)
{ {
DicConsole.ErrorWriteLine("Input file 1 format not identified, not proceeding with comparison."); DicConsole.ErrorWriteLine("Input file 1 format not identified, not proceeding with comparison.");
return; return 3;
} }
if(options.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Input file 1 format identified by {0} ({1}).", input1Format.Name, DicConsole.VerboseWriteLine("Input file 1 format identified by {0} ({1}).", input1Format.Name,
input1Format.Id); 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);
@@ -85,10 +132,10 @@ namespace DiscImageChef.Commands
if(input2Format == null) if(input2Format == null)
{ {
DicConsole.ErrorWriteLine("Input file 2 format not identified, not proceeding with comparison."); DicConsole.ErrorWriteLine("Input file 2 format not identified, not proceeding with comparison.");
return; return 4;
} }
if(options.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Input file 2 format identified by {0} ({1}).", input2Format.Name, DicConsole.VerboseWriteLine("Input file 2 format identified by {0} ({1}).", input2Format.Name,
input2Format.Id); 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);
@@ -96,32 +143,32 @@ namespace DiscImageChef.Commands
input1Format.Open(inputFilter1); input1Format.Open(inputFilter1);
input2Format.Open(inputFilter2); input2Format.Open(inputFilter2);
Core.Statistics.AddMediaFormat(input1Format.Format); Statistics.AddMediaFormat(input1Format.Format);
Core.Statistics.AddMediaFormat(input2Format.Format); Statistics.AddMediaFormat(input2Format.Format);
Core.Statistics.AddMedia(input1Format.Info.MediaType, false); Statistics.AddMedia(input1Format.Info.MediaType, false);
Core.Statistics.AddMedia(input2Format.Info.MediaType, false); Statistics.AddMedia(input2Format.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter1.Name); Statistics.AddFilter(inputFilter1.Name);
Core.Statistics.AddFilter(inputFilter2.Name); Statistics.AddFilter(inputFilter2.Name);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if(options.Verbose) if(MainClass.Verbose)
{ {
sb.AppendLine("\tDisc image 1\tDisc image 2"); sb.AppendLine("\tDisc image 1\tDisc image 2");
sb.AppendLine("================================"); sb.AppendLine("================================");
sb.AppendFormat("File\t{0}\t{1}", options.InputFile1, options.InputFile2).AppendLine(); sb.AppendFormat("File\t{0}\t{1}", InputFile1, InputFile2).AppendLine();
sb.AppendFormat("Disc image format\t{0}\t{1}", input1Format.Name, input2Format.Name).AppendLine(); sb.AppendFormat("Disc image format\t{0}\t{1}", input1Format.Name, input2Format.Name).AppendLine();
} }
else else
{ {
sb.AppendFormat("Disc image 1: {0}", options.InputFile1).AppendLine(); sb.AppendFormat("Disc image 1: {0}", InputFile1).AppendLine();
sb.AppendFormat("Disc image 2: {0}", options.InputFile2).AppendLine(); sb.AppendFormat("Disc image 2: {0}", InputFile2).AppendLine();
} }
bool imagesDiffer = false; bool imagesDiffer = false;
CommonTypes.Structs.ImageInfo image1Info = new CommonTypes.Structs.ImageInfo(); ImageInfo image1Info = new ImageInfo();
CommonTypes.Structs.ImageInfo image2Info = new CommonTypes.Structs.ImageInfo(); ImageInfo image2Info = new ImageInfo();
List<Session> image1Sessions = new List<Session>(); List<Session> image1Sessions = new List<Session>();
List<Session> image2Sessions = new List<Session>(); List<Session> image2Sessions = new List<Session>();
Dictionary<MediaTagType, byte[]> image1DiskTags = new Dictionary<MediaTagType, byte[]>(); Dictionary<MediaTagType, byte[]> image1DiskTags = new Dictionary<MediaTagType, byte[]>();
@@ -221,7 +268,7 @@ namespace DiscImageChef.Commands
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
} }
if(options.Verbose) if(MainClass.Verbose)
{ {
sb.AppendFormat("Has partitions?\t{0}\t{1}", image1Info.HasPartitions, image2Info.HasPartitions) sb.AppendFormat("Has partitions?\t{0}\t{1}", image1Info.HasPartitions, image2Info.HasPartitions)
.AppendLine(); .AppendLine();
@@ -272,31 +319,31 @@ namespace DiscImageChef.Commands
if(image1Info.HasPartitions != image2Info.HasPartitions) if(image1Info.HasPartitions != image2Info.HasPartitions)
{ {
imagesDiffer = true; imagesDiffer = true;
if(!options.Verbose) sb.AppendLine("Image partitioned status differ"); if(!MainClass.Verbose) sb.AppendLine("Image partitioned status differ");
} }
if(image1Info.HasSessions != image2Info.HasSessions) if(image1Info.HasSessions != image2Info.HasSessions)
{ {
imagesDiffer = true; imagesDiffer = true;
if(!options.Verbose) sb.AppendLine("Image session status differ"); if(!MainClass.Verbose) sb.AppendLine("Image session status differ");
} }
if(image1Info.Sectors != image2Info.Sectors) if(image1Info.Sectors != image2Info.Sectors)
{ {
imagesDiffer = true; imagesDiffer = true;
if(!options.Verbose) sb.AppendLine("Image sectors differ"); if(!MainClass.Verbose) sb.AppendLine("Image sectors differ");
} }
if(image1Info.SectorSize != image2Info.SectorSize) if(image1Info.SectorSize != image2Info.SectorSize)
{ {
imagesDiffer = true; imagesDiffer = true;
if(!options.Verbose) sb.AppendLine("Image sector size differ"); if(!MainClass.Verbose) sb.AppendLine("Image sector size differ");
} }
if(image1Info.MediaType != image2Info.MediaType) if(image1Info.MediaType != image2Info.MediaType)
{ {
imagesDiffer = true; imagesDiffer = true;
if(!options.Verbose) sb.AppendLine("Disk type differ"); if(!MainClass.Verbose) sb.AppendLine("Disk type differ");
} }
ulong leastSectors; ulong leastSectors;
@@ -304,13 +351,13 @@ namespace DiscImageChef.Commands
{ {
imagesDiffer = true; imagesDiffer = true;
leastSectors = image1Info.Sectors; leastSectors = image1Info.Sectors;
if(!options.Verbose) sb.AppendLine("Image 2 has more sectors"); if(!MainClass.Verbose) sb.AppendLine("Image 2 has more sectors");
} }
else if(image1Info.Sectors > image2Info.Sectors) else if(image1Info.Sectors > image2Info.Sectors)
{ {
imagesDiffer = true; imagesDiffer = true;
leastSectors = image2Info.Sectors; leastSectors = image2Info.Sectors;
if(!options.Verbose) sb.AppendLine("Image 1 has more sectors"); if(!MainClass.Verbose) sb.AppendLine("Image 1 has more sectors");
} }
else leastSectors = image1Info.Sectors; else leastSectors = image1Info.Sectors;
@@ -351,7 +398,8 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine(sb.ToString()); DicConsole.WriteLine(sb.ToString());
Core.Statistics.AddCommand("compare"); Statistics.AddCommand("compare");
return 0;
} }
} }
} }

View File

@@ -31,15 +31,59 @@
// ****************************************************************************/ // ****************************************************************************/
using System; using System;
using System.Collections.Generic;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Settings; using DiscImageChef.Settings;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Configure class ConfigureCommand : Command
{ {
internal static void DoConfigure(bool gdprChange) readonly bool gdprChange;
bool showHelp;
public ConfigureCommand(bool gdprChange) : base("configure", "Configures user settings and statistics.")
{ {
this.gdprChange = gdprChange;
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 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
if(gdprChange) if(gdprChange)
{ {
DicConsole.WriteLine("In compliance with the European Union General Data Protection Regulation 2016/679 (GDPR),\n" + DicConsole.WriteLine("In compliance with the European Union General Data Protection Regulation 2016/679 (GDPR),\n" +
@@ -228,6 +272,7 @@ namespace DiscImageChef.Commands
Settings.Settings.Current.GdprCompliance = DicSettings.GdprLevel; Settings.Settings.Current.GdprCompliance = DicSettings.GdprLevel;
Settings.Settings.SaveSettings(); Settings.Settings.SaveSettings();
return 0;
} }
} }
} }

View File

@@ -42,107 +42,234 @@ using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.CommonTypes.Structs; using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
using Schemas; using Schemas;
using ImageInfo = DiscImageChef.CommonTypes.Structs.ImageInfo;
using Version = DiscImageChef.CommonTypes.Interop.Version; using Version = DiscImageChef.CommonTypes.Interop.Version;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
public static class ConvertImage class ConvertImageCommand : Command
{ {
public static void DoConvert(ConvertImageOptions options) string cicmXml;
{ string comments;
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", options.Debug); int count = 64;
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", options.Verbose); string creator;
DicConsole.DebugWriteLine("Analyze command", "--input={0}", options.InputFile); string driveFirmwareRevision;
DicConsole.DebugWriteLine("Analyze command", "--output={0}", options.OutputFile); string driveManufacturer;
DicConsole.DebugWriteLine("Analyze command", "--format={0}", options.OutputFormat); string driveModel;
DicConsole.DebugWriteLine("Analyze command", "--count={0}", options.Count); string driveSerialNumber;
DicConsole.DebugWriteLine("Analyze command", "--force={0}", options.Force); bool force;
DicConsole.DebugWriteLine("Analyze command", "--creator={0}", options.Creator); string inputFile;
DicConsole.DebugWriteLine("Analyze command", "--media-title={0}", options.MediaTitle); int lastMediaSequence;
DicConsole.DebugWriteLine("Analyze command", "--comments={0}", options.Comments); string mediaBarcode;
DicConsole.DebugWriteLine("Analyze command", "--media-manufacturer={0}", options.MediaManufacturer); string mediaManufacturer;
DicConsole.DebugWriteLine("Analyze command", "--media-model={0}", options.MediaModel); string mediaModel;
DicConsole.DebugWriteLine("Analyze command", "--media-serial={0}", options.MediaSerialNumber); string mediaPartNumber;
DicConsole.DebugWriteLine("Analyze command", "--media-barcode={0}", options.MediaBarcode); int mediaSequence;
DicConsole.DebugWriteLine("Analyze command", "--media-partnumber={0}", options.MediaPartNumber); string mediaSerialNumber;
DicConsole.DebugWriteLine("Analyze command", "--media-sequence={0}", options.MediaSequence); string mediaTitle;
DicConsole.DebugWriteLine("Analyze command", "--media-lastsequence={0}", options.LastMediaSequence); string outputFile;
DicConsole.DebugWriteLine("Analyze command", "--drive-manufacturer={0}", options.DriveManufacturer); string outputOptions;
DicConsole.DebugWriteLine("Analyze command", "--drive-model={0}", options.DriveModel); string resumeFile;
DicConsole.DebugWriteLine("Analyze command", "--drive-serial={0}", options.DriveSerialNumber); bool showHelp;
DicConsole.DebugWriteLine("Analyze command", "--drive-revision={0}", options.DriveFirmwareRevision); string wantedOutputFormat;
DicConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", options.CicmXml);
DicConsole.DebugWriteLine("Analyze command", "--resume-file={0}", options.ResumeFile);
DicConsole.DebugWriteLine("Analyze command", "--options={0}", options.Options);
Dictionary<string, string> parsedOptions = Options.Parse(options.Options); public ConvertImageCommand() : base("convert-image", "Converts one image to another format.")
{
Options = new OptionSet
{
$"{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},
{
"drive-manufacturer=",
"Manufacturer of the drive used to read the media represented by the image.",
s => driveManufacturer = s
},
{
"drive-model=", "Model of the drive used to read the media represented by the image.",
s => driveModel = s
},
{
"drive-revision=",
"Firmware revision of the drive used to read the media represented by the image.",
s => driveFirmwareRevision = s
},
{
"drive-serial=", "Serial number of the drive used to read the media represented by the image.",
s => driveSerialNumber = s
},
{
"force|f", "Continue conversion even if sector or media tags will be lost in the process.",
b => force = b != null
},
{
"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},
{
"media-lastsequence=",
"Last media of the sequence the media represented by the image corresponds to.",
(int i) => lastMediaSequence = i
},
{
"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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count > 2)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return 1;
}
if(extra.Count <= 1)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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", "--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", "--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);
Dictionary<string, string> parsedOptions = Core.Options.Parse(outputOptions);
DicConsole.DebugWriteLine("Analyze command", "Parsed options:"); DicConsole.DebugWriteLine("Analyze command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions) foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Analyze command", "{0} = {1}", parsedOption.Key, parsedOption.Value); DicConsole.DebugWriteLine("Analyze command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
if(options.Count == 0) if(count == 0)
{ {
DicConsole.ErrorWriteLine("Need to specify more than 0 sectors to copy at once"); DicConsole.ErrorWriteLine("Need to specify more than 0 sectors to copy at once");
return; return 1;
} }
Resume resume = null; Resume resume = null;
CICMMetadataType sidecar = null; CICMMetadataType sidecar = null;
XmlSerializer xs = new XmlSerializer(typeof(CICMMetadataType)); XmlSerializer xs = new XmlSerializer(typeof(CICMMetadataType));
if(options.CicmXml != null) if(cicmXml != null)
if(File.Exists(options.CicmXml)) if(File.Exists(cicmXml))
try try
{ {
StreamReader sr = new StreamReader(options.CicmXml); StreamReader sr = new StreamReader(cicmXml);
sidecar = (CICMMetadataType)xs.Deserialize(sr); sidecar = (CICMMetadataType)xs.Deserialize(sr);
sr.Close(); sr.Close();
} }
catch catch
{ {
DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing..."); DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing...");
return; return 2;
} }
else else
{ {
DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing..."); DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing...");
return; return 3;
} }
xs = new XmlSerializer(typeof(Resume)); xs = new XmlSerializer(typeof(Resume));
if(options.ResumeFile != null) if(resumeFile != null)
if(File.Exists(options.ResumeFile)) if(File.Exists(resumeFile))
try try
{ {
StreamReader sr = new StreamReader(options.ResumeFile); StreamReader sr = new StreamReader(resumeFile);
resume = (Resume)xs.Deserialize(sr); resume = (Resume)xs.Deserialize(sr);
sr.Close(); sr.Close();
} }
catch catch
{ {
DicConsole.ErrorWriteLine("Incorrect resume file, not continuing..."); DicConsole.ErrorWriteLine("Incorrect resume file, not continuing...");
return; return 4;
} }
else else
{ {
DicConsole.ErrorWriteLine("Could not find resume file, not continuing..."); DicConsole.ErrorWriteLine("Could not find resume file, not continuing...");
return; return 5;
} }
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 6;
} }
if(File.Exists(options.OutputFile)) if(File.Exists(outputFile))
{ {
DicConsole.ErrorWriteLine("Output file already exists, not continuing."); DicConsole.ErrorWriteLine("Output file already exists, not continuing.");
return; return 8;
} }
PluginBase plugins = GetPluginBase.Instance; PluginBase plugins = GetPluginBase.Instance;
@@ -151,10 +278,10 @@ namespace DiscImageChef.Commands
if(inputFormat == null) if(inputFormat == null)
{ {
DicConsole.WriteLine("Input image format not identified, not proceeding with conversion."); DicConsole.WriteLine("Input image format not identified, not proceeding with conversion.");
return; return 7;
} }
if(options.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Input image format identified by {0} ({1}).", inputFormat.Name, DicConsole.VerboseWriteLine("Input image format identified by {0} ({1}).", inputFormat.Name,
inputFormat.Id); inputFormat.Id);
else DicConsole.WriteLine("Input image format identified by {0}.", inputFormat.Name); else DicConsole.WriteLine("Input image format identified by {0}.", inputFormat.Name);
@@ -165,7 +292,7 @@ namespace DiscImageChef.Commands
{ {
DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given"); DicConsole.WriteLine("No error given");
return; return 9;
} }
DicConsole.DebugWriteLine("Convert-image command", "Correctly opened image file."); DicConsole.DebugWriteLine("Convert-image command", "Correctly opened image file.");
@@ -175,66 +302,65 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Convert-image command", "Image identifies media type as {0}.", DicConsole.DebugWriteLine("Convert-image command", "Image identifies media type as {0}.",
inputFormat.Info.MediaType); inputFormat.Info.MediaType);
Core.Statistics.AddMediaFormat(inputFormat.Format); Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
} }
catch(Exception ex) catch(Exception ex)
{ {
DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message); DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
DicConsole.DebugWriteLine("Convert-image command", "Stack trace: {0}", ex.StackTrace); DicConsole.DebugWriteLine("Convert-image command", "Stack trace: {0}", ex.StackTrace);
return; return 10;
} }
List<IWritableImage> candidates = new List<IWritableImage>(); List<IWritableImage> candidates = new List<IWritableImage>();
// Try extension // Try extension
if(string.IsNullOrEmpty(options.OutputFormat)) if(string.IsNullOrEmpty(wantedOutputFormat))
candidates.AddRange(plugins.WritableImages.Values.Where(t => candidates.AddRange(plugins.WritableImages.Values.Where(t =>
t.KnownExtensions t.KnownExtensions
.Contains(Path.GetExtension(options .Contains(Path.GetExtension(outputFile))));
.OutputFile))));
// Try Id // Try Id
else if(Guid.TryParse(options.OutputFormat, out Guid outId)) else if(Guid.TryParse(wantedOutputFormat, out Guid outId))
candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId))); candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId)));
// Try name // Try name
else else
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, options.OutputFormat, candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, wantedOutputFormat,
StringComparison StringComparison
.InvariantCultureIgnoreCase))); .InvariantCultureIgnoreCase)));
if(candidates.Count == 0) if(candidates.Count == 0)
{ {
DicConsole.WriteLine("No plugin supports requested extension."); DicConsole.WriteLine("No plugin supports requested extension.");
return; return 11;
} }
if(candidates.Count > 1) if(candidates.Count > 1)
{ {
DicConsole.WriteLine("More than one plugin supports requested extension."); DicConsole.WriteLine("More than one plugin supports requested extension.");
return; return 12;
} }
IWritableImage outputFormat = candidates[0]; IWritableImage outputFormat = candidates[0];
if(options.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id); 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)) if(!outputFormat.SupportedMediaTypes.Contains(inputFormat.Info.MediaType))
{ {
DicConsole.ErrorWriteLine("Output format does not support media type, cannot continue..."); DicConsole.ErrorWriteLine("Output format does not support media type, cannot continue...");
return; return 13;
} }
foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags) foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags)
{ {
if(outputFormat.SupportedMediaTags.Contains(mediaTag) || options.Force) continue; if(outputFormat.SupportedMediaTags.Contains(mediaTag) || force) continue;
DicConsole.ErrorWriteLine("Converting image will lose media tag {0}, not continuing...", mediaTag); DicConsole.ErrorWriteLine("Converting image will lose media tag {0}, not continuing...", mediaTag);
DicConsole.ErrorWriteLine("If you don't care, use force option."); DicConsole.ErrorWriteLine("If you don't care, use force option.");
return; return 14;
} }
bool useLong = inputFormat.Info.ReadableSectorTags.Count != 0; bool useLong = inputFormat.Info.ReadableSectorTags.Count != 0;
@@ -243,7 +369,7 @@ namespace DiscImageChef.Commands
{ {
if(outputFormat.SupportedSectorTags.Contains(sectorTag)) continue; if(outputFormat.SupportedSectorTags.Contains(sectorTag)) continue;
if(options.Force) if(force)
{ {
if(sectorTag != SectorTagType.CdTrackFlags && sectorTag != SectorTagType.CdTrackIsrc && if(sectorTag != SectorTagType.CdTrackFlags && sectorTag != SectorTagType.CdTrackIsrc &&
sectorTag != SectorTagType.CdSectorSubchannel) useLong = false; sectorTag != SectorTagType.CdSectorSubchannel) useLong = false;
@@ -253,44 +379,43 @@ namespace DiscImageChef.Commands
DicConsole.ErrorWriteLine("Converting image will lose sector tag {0}, not continuing...", sectorTag); DicConsole.ErrorWriteLine("Converting image will lose sector tag {0}, not continuing...", sectorTag);
DicConsole DicConsole
.ErrorWriteLine("If you don't care, use force option. This will skip all sector tags converting only user data."); .ErrorWriteLine("If you don't care, use force option. This will skip all sector tags converting only user data.");
return; return 15;
} }
if(!outputFormat.Create(options.OutputFile, inputFormat.Info.MediaType, parsedOptions, if(!outputFormat.Create(outputFile, inputFormat.Info.MediaType, parsedOptions, inputFormat.Info.Sectors,
inputFormat.Info.Sectors, inputFormat.Info.SectorSize)) inputFormat.Info.SectorSize))
{ {
DicConsole.ErrorWriteLine("Error {0} creating output image.", outputFormat.ErrorMessage); DicConsole.ErrorWriteLine("Error {0} creating output image.", outputFormat.ErrorMessage);
return; return 16;
} }
CommonTypes.Structs.ImageInfo metadata = new CommonTypes.Structs.ImageInfo ImageInfo metadata = new ImageInfo
{ {
Application = "DiscImageChef", Application = "DiscImageChef",
ApplicationVersion = Version.GetVersion(), ApplicationVersion = Version.GetVersion(),
Comments = options.Comments ?? inputFormat.Info.Comments, Comments = comments ?? inputFormat.Info.Comments,
Creator = options.Creator ?? inputFormat.Info.Creator, Creator = creator ?? inputFormat.Info.Creator,
DriveFirmwareRevision = options.DriveFirmwareRevision ?? inputFormat.Info.DriveFirmwareRevision, DriveFirmwareRevision = driveFirmwareRevision ?? inputFormat.Info.DriveFirmwareRevision,
DriveManufacturer = options.DriveManufacturer ?? inputFormat.Info.DriveManufacturer, DriveManufacturer = driveManufacturer ?? inputFormat.Info.DriveManufacturer,
DriveModel = options.DriveModel ?? inputFormat.Info.DriveModel, DriveModel = driveModel ?? inputFormat.Info.DriveModel,
DriveSerialNumber = options.DriveSerialNumber ?? inputFormat.Info.DriveSerialNumber, DriveSerialNumber = driveSerialNumber ?? inputFormat.Info.DriveSerialNumber,
LastMediaSequence = LastMediaSequence = lastMediaSequence != 0 ? lastMediaSequence : inputFormat.Info.LastMediaSequence,
options.LastMediaSequence != 0 ? options.LastMediaSequence : inputFormat.Info.LastMediaSequence, MediaBarcode = mediaBarcode ?? inputFormat.Info.MediaBarcode,
MediaBarcode = options.MediaBarcode ?? inputFormat.Info.MediaBarcode, MediaManufacturer = mediaManufacturer ?? inputFormat.Info.MediaManufacturer,
MediaManufacturer = options.MediaManufacturer ?? inputFormat.Info.MediaManufacturer, MediaModel = mediaModel ?? inputFormat.Info.MediaModel,
MediaModel = options.MediaModel ?? inputFormat.Info.MediaModel, MediaPartNumber = mediaPartNumber ?? inputFormat.Info.MediaPartNumber,
MediaPartNumber = options.MediaPartNumber ?? inputFormat.Info.MediaPartNumber, MediaSequence = mediaSequence != 0 ? mediaSequence : inputFormat.Info.MediaSequence,
MediaSequence = options.MediaSequence != 0 ? options.MediaSequence : inputFormat.Info.MediaSequence, MediaSerialNumber = mediaSerialNumber ?? inputFormat.Info.MediaSerialNumber,
MediaSerialNumber = options.MediaSerialNumber ?? inputFormat.Info.MediaSerialNumber, MediaTitle = mediaTitle ?? inputFormat.Info.MediaTitle
MediaTitle = options.MediaTitle ?? inputFormat.Info.MediaTitle
}; };
if(!outputFormat.SetMetadata(metadata)) if(!outputFormat.SetMetadata(metadata))
{ {
DicConsole.ErrorWrite("Error {0} setting metadata, ", outputFormat.ErrorMessage); DicConsole.ErrorWrite("Error {0} setting metadata, ", outputFormat.ErrorMessage);
if(!options.Force) if(!force)
{ {
DicConsole.ErrorWriteLine("not continuing..."); DicConsole.ErrorWriteLine("not continuing...");
return; return 17;
} }
DicConsole.ErrorWriteLine("continuing..."); DicConsole.ErrorWriteLine("continuing...");
@@ -309,24 +434,24 @@ namespace DiscImageChef.Commands
{ {
DicConsole.ErrorWriteLine("Error {0} sending tracks list to output image.", DicConsole.ErrorWriteLine("Error {0} sending tracks list to output image.",
outputFormat.ErrorMessage); outputFormat.ErrorMessage);
return; return 18;
} }
foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags) foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags)
{ {
if(options.Force && !outputFormat.SupportedMediaTags.Contains(mediaTag)) continue; if(force && !outputFormat.SupportedMediaTags.Contains(mediaTag)) continue;
DicConsole.WriteLine("Converting media tag {0}", mediaTag); DicConsole.WriteLine("Converting media tag {0}", mediaTag);
byte[] tag = inputFormat.ReadDiskTag(mediaTag); byte[] tag = inputFormat.ReadDiskTag(mediaTag);
if(outputFormat.WriteMediaTag(tag, mediaTag)) continue; if(outputFormat.WriteMediaTag(tag, mediaTag)) continue;
if(options.Force) if(force)
DicConsole.ErrorWriteLine("Error {0} writing media tag, continuing...", outputFormat.ErrorMessage); DicConsole.ErrorWriteLine("Error {0} writing media tag, continuing...", outputFormat.ErrorMessage);
else else
{ {
DicConsole.ErrorWriteLine("Error {0} writing media tag, not continuing...", DicConsole.ErrorWriteLine("Error {0} writing media tag, not continuing...",
outputFormat.ErrorMessage); outputFormat.ErrorMessage);
return; return 19;
} }
} }
@@ -348,9 +473,10 @@ namespace DiscImageChef.Commands
byte[] sector; byte[] sector;
uint sectorsToDo; uint sectorsToDo;
if(inputFormat.Info.Sectors - doneSectors >= (ulong)options.Count) if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
sectorsToDo = (uint)options.Count; else
else sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors); sectorsToDo =
(uint)(inputFormat.Info.Sectors - doneSectors);
DicConsole.Write("\rConverting sectors {0} to {1} ({2:P2} done)", doneSectors, DicConsole.Write("\rConverting sectors {0} to {1} ({2:P2} done)", doneSectors,
doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors); doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors);
@@ -382,14 +508,14 @@ namespace DiscImageChef.Commands
} }
if(!result) if(!result)
if(options.Force) if(force)
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...", DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...",
outputFormat.ErrorMessage, doneSectors); outputFormat.ErrorMessage, doneSectors);
else else
{ {
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...", DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors); outputFormat.ErrorMessage, doneSectors);
return; return 20;
} }
doneSectors += sectorsToDo; doneSectors += sectorsToDo;
@@ -417,7 +543,7 @@ namespace DiscImageChef.Commands
continue; continue;
} }
if(options.Force && !outputFormat.SupportedSectorTags.Contains(tag)) continue; if(force && !outputFormat.SupportedSectorTags.Contains(tag)) continue;
doneSectors = 0; doneSectors = 0;
while(doneSectors < inputFormat.Info.Sectors) while(doneSectors < inputFormat.Info.Sectors)
@@ -425,9 +551,10 @@ namespace DiscImageChef.Commands
byte[] sector; byte[] sector;
uint sectorsToDo; uint sectorsToDo;
if(inputFormat.Info.Sectors - doneSectors >= (ulong)options.Count) if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
sectorsToDo = (uint)options.Count; else
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, DicConsole.Write("\rConverting tag {2} for sectors {0} to {1} ({2:P2} done)", doneSectors,
doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors, doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors,
@@ -446,14 +573,14 @@ namespace DiscImageChef.Commands
} }
if(!result) if(!result)
if(options.Force) if(force)
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...", DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...",
outputFormat.ErrorMessage, doneSectors); outputFormat.ErrorMessage, doneSectors);
else else
{ {
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...", DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors); outputFormat.ErrorMessage, doneSectors);
return; return 21;
} }
doneSectors += sectorsToDo; doneSectors += sectorsToDo;
@@ -476,10 +603,8 @@ namespace DiscImageChef.Commands
byte[] sector; byte[] sector;
uint sectorsToDo; uint sectorsToDo;
if(trackSectors - doneSectors >= (ulong)options.Count) sectorsToDo = (uint)options.Count; if(trackSectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
else else sectorsToDo = (uint)(trackSectors - doneSectors);
sectorsToDo =
(uint)(trackSectors - doneSectors);
DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)", DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)",
doneSectors + track.TrackStartSector, doneSectors + track.TrackStartSector,
@@ -516,14 +641,14 @@ namespace DiscImageChef.Commands
} }
if(!result) if(!result)
if(options.Force) if(force)
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...", DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...",
outputFormat.ErrorMessage, doneSectors); outputFormat.ErrorMessage, doneSectors);
else else
{ {
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...", DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors); outputFormat.ErrorMessage, doneSectors);
return; return 22;
} }
doneSectors += sectorsToDo; doneSectors += sectorsToDo;
@@ -552,7 +677,7 @@ namespace DiscImageChef.Commands
continue; continue;
} }
if(options.Force && !outputFormat.SupportedSectorTags.Contains(tag)) continue; if(force && !outputFormat.SupportedSectorTags.Contains(tag)) continue;
foreach(Track track in tracks) foreach(Track track in tracks)
{ {
@@ -570,14 +695,14 @@ namespace DiscImageChef.Commands
sector = inputFormat.ReadSectorTag(track.TrackStartSector, tag); sector = inputFormat.ReadSectorTag(track.TrackStartSector, tag);
result = outputFormat.WriteSectorTag(sector, track.TrackStartSector, tag); result = outputFormat.WriteSectorTag(sector, track.TrackStartSector, tag);
if(!result) if(!result)
if(options.Force) if(force)
DicConsole.ErrorWriteLine("Error {0} writing tag, continuing...", DicConsole.ErrorWriteLine("Error {0} writing tag, continuing...",
outputFormat.ErrorMessage); outputFormat.ErrorMessage);
else else
{ {
DicConsole.ErrorWriteLine("Error {0} writing tag, not continuing...", DicConsole.ErrorWriteLine("Error {0} writing tag, not continuing...",
outputFormat.ErrorMessage); outputFormat.ErrorMessage);
return; return 23;
} }
continue; continue;
@@ -586,7 +711,7 @@ namespace DiscImageChef.Commands
while(doneSectors < trackSectors) while(doneSectors < trackSectors)
{ {
uint sectorsToDo; uint sectorsToDo;
if(trackSectors - doneSectors >= (ulong)options.Count) sectorsToDo = (uint)options.Count; if(trackSectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
else else
sectorsToDo = sectorsToDo =
(uint)(trackSectors - doneSectors); (uint)(trackSectors - doneSectors);
@@ -611,14 +736,14 @@ namespace DiscImageChef.Commands
} }
if(!result) if(!result)
if(options.Force) if(force)
DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, continuing...", DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, continuing...",
outputFormat.ErrorMessage, doneSectors); outputFormat.ErrorMessage, doneSectors);
else else
{ {
DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, not continuing...", DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors); outputFormat.ErrorMessage, doneSectors);
return; return 24;
} }
doneSectors += sectorsToDo; doneSectors += sectorsToDo;
@@ -668,7 +793,8 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.WriteLine("Conversion done."); DicConsole.WriteLine("Conversion done.");
Core.Statistics.AddCommand("convert-image"); Statistics.AddCommand("convert-image");
return 0;
} }
} }
} }

View File

@@ -40,14 +40,79 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
using Schemas; using Schemas;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class CreateSidecar class CreateSidecarCommand : Command
{ {
internal static void DoSidecar(CreateSidecarOptions options) int blockSize;
string encodingName;
string inputFile;
bool showHelp;
bool tape;
public CreateSidecarCommand() : base("create-sidecar", "Creates CICM Metadata XML sidecar.")
{ {
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] input",
"",
Help,
{
"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.",
(int i) => blockSize = i
},
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
{
"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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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);
Sidecar.InitProgressEvent += Progress.InitProgress; Sidecar.InitProgressEvent += Progress.InitProgress;
Sidecar.UpdateProgressEvent += Progress.UpdateProgress; Sidecar.UpdateProgressEvent += Progress.UpdateProgress;
Sidecar.EndProgressEvent += Progress.EndProgress; Sidecar.EndProgressEvent += Progress.EndProgress;
@@ -58,33 +123,33 @@ namespace DiscImageChef.Commands
Encoding encoding = null; Encoding encoding = null;
if(options.EncodingName != null) if(encodingName != null)
try try
{ {
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName); encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
} }
catch(ArgumentException) catch(ArgumentException)
{ {
DicConsole.ErrorWriteLine("Specified encoding is not supported."); DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return; return 1;
} }
if(File.Exists(options.InputFile)) if(File.Exists(inputFile))
{ {
if(options.Tape) if(tape)
{ {
DicConsole.ErrorWriteLine("You cannot use --tape option when input is a file."); DicConsole.ErrorWriteLine("You cannot use --tape option when input is a file.");
return; return 2;
} }
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 3;
} }
try try
@@ -94,10 +159,10 @@ namespace DiscImageChef.Commands
if(imageFormat == null) if(imageFormat == null)
{ {
DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
return; return 4;
} }
if(options.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
imageFormat.Id); imageFormat.Id);
else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
@@ -108,7 +173,7 @@ namespace DiscImageChef.Commands
{ {
DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given"); DicConsole.WriteLine("No error given");
return; return 5;
} }
DicConsole.DebugWriteLine("Analyze command", "Correctly opened image file."); DicConsole.DebugWriteLine("Analyze command", "Correctly opened image file.");
@@ -117,26 +182,26 @@ namespace DiscImageChef.Commands
{ {
DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message); DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return; return 6;
} }
Core.Statistics.AddMediaFormat(imageFormat.Format); Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
CICMMetadataType sidecar = Sidecar.Create(imageFormat, options.InputFile, inputFilter.Id, encoding); CICMMetadataType sidecar = Sidecar.Create(imageFormat, inputFile, inputFilter.Id, encoding);
DicConsole.WriteLine("Writing metadata sidecar"); DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs = FileStream xmlFs =
new new
FileStream(Path.Combine(Path.GetDirectoryName(options.InputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(options.InputFile) + ".cicm.xml"), FileStream(Path.Combine(Path.GetDirectoryName(inputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(inputFile) + ".cicm.xml"),
FileMode.CreateNew); FileMode.CreateNew);
XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType)); XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
Core.Statistics.AddCommand("create-sidecar"); Statistics.AddCommand("create-sidecar");
} }
catch(Exception ex) catch(Exception ex)
{ {
@@ -144,37 +209,37 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Analyze command", ex.StackTrace); DicConsole.DebugWriteLine("Analyze command", ex.StackTrace);
} }
} }
else if(Directory.Exists(options.InputFile)) else if(Directory.Exists(inputFile))
{ {
if(!options.Tape) if(!tape)
{ {
DicConsole.ErrorWriteLine("Cannot create a sidecar from a directory."); DicConsole.ErrorWriteLine("Cannot create a sidecar from a directory.");
return; return 7;
} }
string[] contents = Directory.GetFiles(options.InputFile, "*", SearchOption.TopDirectoryOnly); string[] contents = Directory.GetFiles(inputFile, "*", SearchOption.TopDirectoryOnly);
List<string> files = contents.Where(file => new FileInfo(file).Length % options.BlockSize == 0) List<string> files = contents.Where(file => new FileInfo(file).Length % blockSize == 0).ToList();
.ToList();
files.Sort(StringComparer.CurrentCultureIgnoreCase); files.Sort(StringComparer.CurrentCultureIgnoreCase);
CICMMetadataType sidecar = CICMMetadataType sidecar = Sidecar.Create(Path.GetFileName(inputFile), files, blockSize);
Sidecar.Create(Path.GetFileName(options.InputFile), files, options.BlockSize);
DicConsole.WriteLine("Writing metadata sidecar"); DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs = FileStream xmlFs =
new new
FileStream(Path.Combine(Path.GetDirectoryName(options.InputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(options.InputFile) + ".cicm.xml"), FileStream(Path.Combine(Path.GetDirectoryName(inputFile) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(inputFile) + ".cicm.xml"),
FileMode.CreateNew); FileMode.CreateNew);
XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType)); XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
Core.Statistics.AddCommand("create-sidecar"); Statistics.AddCommand("create-sidecar");
} }
else DicConsole.ErrorWriteLine("The specified input file cannot be found."); else DicConsole.ErrorWriteLine("The specified input file cannot be found.");
return 0;
} }
} }
} }

View File

@@ -30,6 +30,7 @@
// Copyright © 2011-2019 Natalia Portillo // Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Interfaces;
@@ -38,28 +39,80 @@ using DiscImageChef.Core;
using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.CD; using DiscImageChef.Decoders.CD;
using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Decode class DecodeCommand : Command
{ {
internal static void DoDecode(DecodeOptions options) 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.")
{ {
DicConsole.DebugWriteLine("Decode command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Decode command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Decode command", "--input={0}", options.InputFile); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Decode command", "--start={0}", options.StartSector); $"{MainClass.AssemblyCopyright}",
DicConsole.DebugWriteLine("Decode command", "--length={0}", options.Length); "",
DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", options.DiskTags); $"usage: DiscImageChef {Name} [OPTIONS] imagefile",
DicConsole.DebugWriteLine("Decode command", "--sector-tags={0}", options.SectorTags); "",
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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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", "--sector-tags={0}", sectorTags);
DicConsole.DebugWriteLine("Decode command", "--start={0}", startSector);
DicConsole.DebugWriteLine("Decode command", "--verbose={0}", MainClass.Verbose);
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 1;
} }
IMediaImage inputFormat = ImageFormat.Detect(inputFilter); IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -67,15 +120,15 @@ namespace DiscImageChef.Commands
if(inputFormat == null) if(inputFormat == null)
{ {
DicConsole.ErrorWriteLine("Unable to recognize image format, not decoding"); DicConsole.ErrorWriteLine("Unable to recognize image format, not decoding");
return; return 2;
} }
inputFormat.Open(inputFilter); inputFormat.Open(inputFilter);
Core.Statistics.AddMediaFormat(inputFormat.Format); Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
if(options.DiskTags) if(diskTags)
if(inputFormat.Info.ReadableMediaTags.Count == 0) if(inputFormat.Info.ReadableMediaTags.Count == 0)
DicConsole.WriteLine("There are no disk tags in chosen disc image."); DicConsole.WriteLine("There are no disk tags in chosen disc image.");
else else
@@ -237,16 +290,16 @@ namespace DiscImageChef.Commands
break; break;
} }
if(options.SectorTags) if(sectorTags)
{ {
if(options.Length.ToLowerInvariant() == "all") { } if(length.ToLowerInvariant() == "all") { }
else else
{ {
if(!ulong.TryParse(options.Length, out ulong _)) if(!ulong.TryParse(length, out ulong _))
{ {
DicConsole.WriteLine("Value \"{0}\" is not a valid number for length.", options.Length); DicConsole.WriteLine("Value \"{0}\" is not a valid number for length.", length);
DicConsole.WriteLine("Not decoding sectors tags"); DicConsole.WriteLine("Not decoding sectors tags");
return; return 3;
} }
} }
@@ -265,7 +318,8 @@ namespace DiscImageChef.Commands
// TODO: Not implemented // TODO: Not implemented
} }
Core.Statistics.AddCommand("decode"); Statistics.AddCommand("decode");
return 0;
} }
} }
} }

View File

@@ -40,31 +40,78 @@ using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Decoders.SCSI.MMC; using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Decoders.SCSI.SSC; using DiscImageChef.Decoders.SCSI.SSC;
using DiscImageChef.Devices; using DiscImageChef.Devices;
using Mono.Options;
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class DeviceInfo class DeviceInfoCommand : Command
{ {
internal static void DoDeviceInfo(DeviceInfoOptions options) string devicePath;
string outputPrefix;
bool showHelp;
public DeviceInfoCommand() : base("device-info", "Gets information about a device.")
{ {
DicConsole.DebugWriteLine("Device-Info command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Device-Info command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Device-Info command", "--device={0}", options.DevicePath); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Device-Info command", "--output-prefix={0}", options.OutputPrefix); $"{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}
};
}
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' && public override int Invoke(IEnumerable<string> arguments)
char.IsLetter(options.DevicePath[0])) {
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':'; List<string> extra = Options.Parse(arguments);
Device dev = new Device(options.DevicePath); if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing device path.");
return 1;
}
devicePath = extra[0];
DicConsole.DebugWriteLine("Device-Info command", "--debug={0}", MainClass.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);
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
Device dev = new Device(devicePath);
if(dev.Error) if(dev.Error)
{ {
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError); DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return; return 1;
} }
Core.Statistics.AddDevice(dev); Statistics.AddDevice(dev);
if(dev.IsUsb) if(dev.IsUsb)
{ {
@@ -156,11 +203,11 @@ namespace DiscImageChef.Commands
else DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples"); else DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples");
} }
Core.Devices.Info.DeviceInfo devInfo = new Core.Devices.Info.DeviceInfo(dev); DeviceInfo devInfo = new DeviceInfo(dev);
if(devInfo.AtaIdentify != null) if(devInfo.AtaIdentify != null)
{ {
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_ata_identify.bin", "ATA IDENTIFY", DataFile.WriteTo("Device-Info command", outputPrefix, "_ata_identify.bin", "ATA IDENTIFY",
devInfo.AtaIdentify); devInfo.AtaIdentify);
DicConsole.WriteLine(Identify.Prettify(devInfo.AtaIdentify)); DicConsole.WriteLine(Identify.Prettify(devInfo.AtaIdentify));
@@ -202,7 +249,7 @@ namespace DiscImageChef.Commands
if(devInfo.AtapiIdentify != null) if(devInfo.AtapiIdentify != null)
{ {
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_atapi_identify.bin", "ATAPI IDENTIFY", DataFile.WriteTo("Device-Info command", outputPrefix, "_atapi_identify.bin", "ATAPI IDENTIFY",
devInfo.AtapiIdentify); devInfo.AtapiIdentify);
DicConsole.WriteLine(Identify.Prettify(devInfo.AtapiIdentify)); DicConsole.WriteLine(Identify.Prettify(devInfo.AtapiIdentify));
@@ -212,7 +259,7 @@ namespace DiscImageChef.Commands
{ {
if(dev.Type != DeviceType.ATAPI) DicConsole.WriteLine("SCSI device"); if(dev.Type != DeviceType.ATAPI) DicConsole.WriteLine("SCSI device");
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_scsi_inquiry.bin", "SCSI INQUIRY", DataFile.WriteTo("Device-Info command", outputPrefix, "_scsi_inquiry.bin", "SCSI INQUIRY",
devInfo.ScsiInquiryData); devInfo.ScsiInquiryData);
DicConsole.WriteLine(Inquiry.Prettify(devInfo.ScsiInquiry)); DicConsole.WriteLine(Inquiry.Prettify(devInfo.ScsiInquiry));
@@ -223,147 +270,129 @@ namespace DiscImageChef.Commands
{ {
DicConsole.WriteLine("ASCII Page {0:X2}h: {1}", page.Key, EVPD.DecodeASCIIPage(page.Value)); DicConsole.WriteLine("ASCII Page {0:X2}h: {1}", page.Key, EVPD.DecodeASCIIPage(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, page.Value); DataFile.WriteTo("Device-Info command", outputPrefix, page.Value);
} }
else if(page.Key == 0x80) else if(page.Key == 0x80)
{ {
DicConsole.WriteLine("Unit Serial Number: {0}", EVPD.DecodePage80(page.Value)); DicConsole.WriteLine("Unit Serial Number: {0}", EVPD.DecodePage80(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0x81) else if(page.Key == 0x81)
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_81(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_81(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0x82) else if(page.Key == 0x82)
{ {
DicConsole.WriteLine("ASCII implemented operating definitions: {0}", DicConsole.WriteLine("ASCII implemented operating definitions: {0}",
EVPD.DecodePage82(page.Value)); EVPD.DecodePage82(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0x83) else if(page.Key == 0x83)
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_83(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_83(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0x84) else if(page.Key == 0x84)
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_84(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_84(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0x85) else if(page.Key == 0x85)
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_85(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_85(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0x86) else if(page.Key == 0x86)
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_86(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_86(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0x89) else if(page.Key == 0x89)
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_89(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_89(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xB0) else if(page.Key == 0xB0)
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_B0(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_B0(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xB1) else if(page.Key == 0xB1)
{ {
DicConsole.WriteLine("Manufacturer-assigned Serial Number: {0}", DicConsole.WriteLine("Manufacturer-assigned Serial Number: {0}",
EVPD.DecodePageB1(page.Value)); EVPD.DecodePageB1(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xB2) else if(page.Key == 0xB2)
{ {
DicConsole.WriteLine("TapeAlert Supported Flags Bitmap: 0x{0:X16}", DicConsole.WriteLine("TapeAlert Supported Flags Bitmap: 0x{0:X16}",
EVPD.DecodePageB2(page.Value)); EVPD.DecodePageB2(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xB3) else if(page.Key == 0xB3)
{ {
DicConsole.WriteLine("Automation Device Serial Number: {0}", EVPD.DecodePageB3(page.Value)); DicConsole.WriteLine("Automation Device Serial Number: {0}", EVPD.DecodePageB3(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xB4) else if(page.Key == 0xB4)
{ {
DicConsole.WriteLine("Data Transfer Device Element Address: 0x{0}", DicConsole.WriteLine("Data Transfer Device Element Address: 0x{0}",
EVPD.DecodePageB4(page.Value)); EVPD.DecodePageB4(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xC0 && else if(page.Key == 0xC0 &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification) StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "quantum") .ToLowerInvariant().Trim() == "quantum")
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Quantum(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Quantum(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xC0 && else if(page.Key == 0xC0 &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification) StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "seagate") .ToLowerInvariant().Trim() == "seagate")
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Seagate(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Seagate(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xC0 && else if(page.Key == 0xC0 &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification) StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "ibm") .ToLowerInvariant().Trim() == "ibm")
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_IBM(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_IBM(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xC1 && else if(page.Key == 0xC1 &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification) StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "ibm") .ToLowerInvariant().Trim() == "ibm")
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C1_IBM(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C1_IBM(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if((page.Key == 0xC0 || page.Key == 0xC1) && else if((page.Key == 0xC0 || page.Key == 0xC1) &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification) StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "certance") .ToLowerInvariant().Trim() == "certance")
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_C1_Certance(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_C1_Certance(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if((page.Key == 0xC2 || page.Key == 0xC3 || page.Key == 0xC4 || page.Key == 0xC5 || else if((page.Key == 0xC2 || page.Key == 0xC3 || page.Key == 0xC4 || page.Key == 0xC5 ||
page.Key == 0xC6) && page.Key == 0xC6) &&
@@ -371,9 +400,8 @@ namespace DiscImageChef.Commands
.ToLowerInvariant().Trim() == "certance") .ToLowerInvariant().Trim() == "certance")
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if((page.Key == 0xC0 || page.Key == 0xC1 || page.Key == 0xC2 || page.Key == 0xC3 || else if((page.Key == 0xC0 || page.Key == 0xC1 || page.Key == 0xC2 || page.Key == 0xC3 ||
page.Key == 0xC4 || page.Key == 0xC5) && StringHandlers page.Key == 0xC4 || page.Key == 0xC5) && StringHandlers
@@ -382,18 +410,16 @@ namespace DiscImageChef.Commands
.ToLowerInvariant().Trim() == "hp") .ToLowerInvariant().Trim() == "hp")
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_to_C5_HP(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_to_C5_HP(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else if(page.Key == 0xDF && else if(page.Key == 0xDF &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification) StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "certance") .ToLowerInvariant().Trim() == "certance")
{ {
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_DF_Certance(page.Value)); DicConsole.WriteLine("{0}", EVPD.PrettifyPage_DF_Certance(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
else else
{ {
@@ -402,18 +428,17 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Device-Info command", "Found undecoded SCSI VPD page 0x{0:X2}", DicConsole.DebugWriteLine("Device-Info command", "Found undecoded SCSI VPD page 0x{0:X2}",
page.Key); page.Key);
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
page.Value);
} }
if(devInfo.ScsiModeSense6 != null) if(devInfo.ScsiModeSense6 != null)
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_scsi_modesense6.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_scsi_modesense6.bin", "SCSI MODE SENSE",
"SCSI MODE SENSE", devInfo.ScsiModeSense6); devInfo.ScsiModeSense6);
if(devInfo.ScsiModeSense10 != null) if(devInfo.ScsiModeSense10 != null)
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_scsi_modesense10.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_scsi_modesense10.bin", "SCSI MODE SENSE",
"SCSI MODE SENSE", devInfo.ScsiModeSense10); devInfo.ScsiModeSense10);
if(devInfo.ScsiMode.HasValue) if(devInfo.ScsiMode.HasValue)
PrintScsiModePages.Print(devInfo.ScsiMode.Value, PrintScsiModePages.Print(devInfo.ScsiMode.Value,
@@ -422,7 +447,7 @@ namespace DiscImageChef.Commands
if(devInfo.MmcConfiguration != null) if(devInfo.MmcConfiguration != null)
{ {
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_getconfiguration.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_getconfiguration.bin",
"MMC GET CONFIGURATION", devInfo.MmcConfiguration); "MMC GET CONFIGURATION", devInfo.MmcConfiguration);
Features.SeparatedFeatures ftr = Features.Separate(devInfo.MmcConfiguration); Features.SeparatedFeatures ftr = Features.Separate(devInfo.MmcConfiguration);
@@ -629,7 +654,7 @@ namespace DiscImageChef.Commands
{ {
if(devInfo.PlextorFeatures.Eeprom != null) if(devInfo.PlextorFeatures.Eeprom != null)
{ {
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_plextor_eeprom.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_plextor_eeprom.bin",
"PLEXTOR READ EEPROM", devInfo.PlextorFeatures.Eeprom); "PLEXTOR READ EEPROM", devInfo.PlextorFeatures.Eeprom);
DicConsole.WriteLine("Drive has loaded a total of {0} discs", devInfo.PlextorFeatures.Discs); DicConsole.WriteLine("Drive has loaded a total of {0} discs", devInfo.PlextorFeatures.Discs);
@@ -772,7 +797,7 @@ namespace DiscImageChef.Commands
if(devInfo.BlockLimits != null) if(devInfo.BlockLimits != null)
{ {
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_ssc_readblocklimits.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_ssc_readblocklimits.bin",
"SSC READ BLOCK LIMITS", devInfo.BlockLimits); "SSC READ BLOCK LIMITS", devInfo.BlockLimits);
DicConsole.WriteLine("Block limits for device:"); DicConsole.WriteLine("Block limits for device:");
DicConsole.WriteLine(BlockLimits.Prettify(devInfo.BlockLimits)); DicConsole.WriteLine(BlockLimits.Prettify(devInfo.BlockLimits));
@@ -780,7 +805,7 @@ namespace DiscImageChef.Commands
if(devInfo.DensitySupport != null) if(devInfo.DensitySupport != null)
{ {
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_ssc_reportdensitysupport.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_ssc_reportdensitysupport.bin",
"SSC REPORT DENSITY SUPPORT", devInfo.DensitySupport); "SSC REPORT DENSITY SUPPORT", devInfo.DensitySupport);
if(devInfo.DensitySupportHeader.HasValue) if(devInfo.DensitySupportHeader.HasValue)
{ {
@@ -791,9 +816,8 @@ namespace DiscImageChef.Commands
if(devInfo.MediumDensitySupport != null) if(devInfo.MediumDensitySupport != null)
{ {
DataFile.WriteTo("Device-Info command", options.OutputPrefix, DataFile.WriteTo("Device-Info command", outputPrefix, "_ssc_reportdensitysupport_medium.bin",
"_ssc_reportdensitysupport_medium.bin", "SSC REPORT DENSITY SUPPORT (MEDIUM)", "SSC REPORT DENSITY SUPPORT (MEDIUM)", devInfo.MediumDensitySupport);
devInfo.MediumDensitySupport);
if(devInfo.MediaTypeSupportHeader.HasValue) if(devInfo.MediaTypeSupportHeader.HasValue)
{ {
DicConsole.WriteLine("Medium types supported by device:"); DicConsole.WriteLine("Medium types supported by device:");
@@ -813,32 +837,29 @@ namespace DiscImageChef.Commands
if(devInfo.CID != null) if(devInfo.CID != null)
{ {
noInfo = false; noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_cid.bin", "MMC CID", DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_cid.bin", "MMC CID", devInfo.CID);
devInfo.CID);
DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyCID(devInfo.CID)); DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyCID(devInfo.CID));
} }
if(devInfo.CSD != null) if(devInfo.CSD != null)
{ {
noInfo = false; noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_csd.bin", "MMC CSD", DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_csd.bin", "MMC CSD", devInfo.CSD);
devInfo.CSD);
DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyCSD(devInfo.CSD)); DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyCSD(devInfo.CSD));
} }
if(devInfo.OCR != null) if(devInfo.OCR != null)
{ {
noInfo = false; noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_ocr.bin", "MMC OCR", DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_ocr.bin", "MMC OCR", devInfo.OCR);
devInfo.OCR);
DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyOCR(devInfo.OCR)); DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyOCR(devInfo.OCR));
} }
if(devInfo.ExtendedCSD != null) if(devInfo.ExtendedCSD != null)
{ {
noInfo = false; noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_ecsd.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_ecsd.bin", "MMC Extended CSD",
"MMC Extended CSD", devInfo.ExtendedCSD); devInfo.ExtendedCSD);
DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyExtendedCSD(devInfo.ExtendedCSD)); DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyExtendedCSD(devInfo.ExtendedCSD));
} }
@@ -852,32 +873,32 @@ namespace DiscImageChef.Commands
if(devInfo.CID != null) if(devInfo.CID != null)
{ {
noInfo = false; noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_sd_cid.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_sd_cid.bin", "SecureDigital CID",
"SecureDigital CID", devInfo.CID); devInfo.CID);
DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyCID(devInfo.CID)); DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyCID(devInfo.CID));
} }
if(devInfo.CSD != null) if(devInfo.CSD != null)
{ {
noInfo = false; noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_sd_csd.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_sd_csd.bin", "SecureDigital CSD",
"SecureDigital CSD", devInfo.CSD); devInfo.CSD);
DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyCSD(devInfo.CSD)); DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyCSD(devInfo.CSD));
} }
if(devInfo.OCR != null) if(devInfo.OCR != null)
{ {
noInfo = false; noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_sd_ocr.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_sd_ocr.bin", "SecureDigital OCR",
"SecureDigital OCR", devInfo.OCR); devInfo.OCR);
DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyOCR(devInfo.OCR)); DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyOCR(devInfo.OCR));
} }
if(devInfo.SCR != null) if(devInfo.SCR != null)
{ {
noInfo = false; noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_sd_scr.bin", DataFile.WriteTo("Device-Info command", outputPrefix, "_sd_scr.bin", "SecureDigital SCR",
"SecureDigital SCR", devInfo.SCR); devInfo.SCR);
DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifySCR(devInfo.SCR)); DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifySCR(devInfo.SCR));
} }
@@ -886,9 +907,11 @@ namespace DiscImageChef.Commands
break; break;
} }
Core.Statistics.AddCommand("device-info"); Statistics.AddCommand("device-info");
dev.Close(); dev.Close();
return 0;
} }
} }
} }

View File

@@ -43,40 +43,87 @@ using DiscImageChef.Database;
using DiscImageChef.Database.Models; using DiscImageChef.Database.Models;
using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI;
using Mono.Options;
using Newtonsoft.Json; using Newtonsoft.Json;
using Command = Mono.Options.Command;
using Device = DiscImageChef.Devices.Device; using Device = DiscImageChef.Devices.Device;
using DeviceReport = DiscImageChef.Core.Devices.Report.DeviceReport;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class DeviceReport class DeviceReportCommand : Command
{ {
internal static void DoDeviceReport(DeviceReportOptions options) string devicePath;
bool showHelp;
public DeviceReportCommand() : base("device-report",
"Tests the device capabilities and creates an JSON report of them.")
{ {
DicConsole.DebugWriteLine("Device-Report command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Device-Report command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Device-Report command", "--device={0}", options.DevicePath); $"{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)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing device path.");
return 1;
}
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(!DetectOS.IsAdmin) if(!DetectOS.IsAdmin)
{ {
DicConsole DicConsole
.ErrorWriteLine("Because of the commands sent to a device, device report must be run with administrative privileges."); .ErrorWriteLine("Because of the commands sent to a device, device report must be run with administrative privileges.");
DicConsole.ErrorWriteLine("Not continuing."); DicConsole.ErrorWriteLine("Not continuing.");
return; return 1;
} }
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' && if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
char.IsLetter(options.DevicePath[0])) devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':';
Device dev = new Device(options.DevicePath); Device dev = new Device(devicePath);
if(dev.Error) if(dev.Error)
{ {
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError); DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return; return 2;
} }
Core.Statistics.AddDevice(dev); Statistics.AddDevice(dev);
DeviceReportV2 report = new DeviceReportV2 DeviceReportV2 report = new DeviceReportV2
{ {
@@ -94,7 +141,7 @@ namespace DiscImageChef.Commands
jsonFile = jsonFile.Replace('\\', '_').Replace('/', '_').Replace('?', '_'); jsonFile = jsonFile.Replace('\\', '_').Replace('/', '_').Replace('?', '_');
Core.Devices.Report.DeviceReport reporter = new Core.Devices.Report.DeviceReport(dev, options.Debug); DeviceReport reporter = new DeviceReport(dev, MainClass.Debug);
ConsoleKeyInfo pressedKey; ConsoleKeyInfo pressedKey;
@@ -248,7 +295,7 @@ namespace DiscImageChef.Commands
dev.AtapiIdentify(out buffer, out _, dev.Timeout, out _); dev.AtapiIdentify(out buffer, out _, dev.Timeout, out _);
if(!Identify.Decode(buffer).HasValue) return; if(!Identify.Decode(buffer).HasValue) return 3;
report.ATAPI = new Ata {Identify = buffer}; report.ATAPI = new Ata {Identify = buffer};
@@ -448,7 +495,7 @@ namespace DiscImageChef.Commands
tryPioneer |= dev.Manufacturer.ToLowerInvariant() == "pioneer"; tryPioneer |= dev.Manufacturer.ToLowerInvariant() == "pioneer";
tryNec |= dev.Manufacturer.ToLowerInvariant() == "nec"; tryNec |= dev.Manufacturer.ToLowerInvariant() == "nec";
if(options.Debug) if(MainClass.Debug)
{ {
if(!tryPlextor) if(!tryPlextor)
{ {
@@ -614,7 +661,7 @@ namespace DiscImageChef.Commands
dev.Timeout, out _); dev.Timeout, out _);
if(!sense) if(!sense)
{ {
if(options.Debug) mediaTest.ReadLong10Data = buffer; if(MainClass.Debug) mediaTest.ReadLong10Data = buffer;
mediaTest.LongBlockSize = i; mediaTest.LongBlockSize = i;
break; break;
@@ -627,8 +674,8 @@ namespace DiscImageChef.Commands
} }
} }
if(options.Debug && mediaTest.SupportsReadLong == true && if(MainClass.Debug && mediaTest.SupportsReadLong == true &&
mediaTest.LongBlockSize != mediaTest.BlockSize) mediaTest.LongBlockSize != mediaTest.BlockSize)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
(ushort)mediaTest.LongBlockSize, dev.Timeout, out _); (ushort)mediaTest.LongBlockSize, dev.Timeout, out _);
@@ -844,8 +891,8 @@ namespace DiscImageChef.Commands
} }
} }
if(options.Debug && mediaTest.SupportsReadLong == true && if(MainClass.Debug && mediaTest.SupportsReadLong == true &&
mediaTest.LongBlockSize != mediaTest.BlockSize) mediaTest.LongBlockSize != mediaTest.BlockSize)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
(ushort)mediaTest.LongBlockSize, dev.Timeout, out _); (ushort)mediaTest.LongBlockSize, dev.Timeout, out _);
@@ -889,7 +936,8 @@ namespace DiscImageChef.Commands
dev.Timeout, out _); dev.Timeout, out _);
if(!sense) if(!sense)
{ {
if(options.Debug) report.SCSI.ReadCapabilities.ReadLong10Data = buffer; if(MainClass.Debug)
report.SCSI.ReadCapabilities.ReadLong10Data = buffer;
report.SCSI.ReadCapabilities.LongBlockSize = i; report.SCSI.ReadCapabilities.LongBlockSize = i;
break; break;
@@ -902,7 +950,7 @@ namespace DiscImageChef.Commands
} }
} }
if(options.Debug && report.SCSI.ReadCapabilities.SupportsReadLong == true && if(MainClass.Debug && report.SCSI.ReadCapabilities.SupportsReadLong == true &&
report.SCSI.ReadCapabilities.LongBlockSize != report.SCSI.ReadCapabilities.LongBlockSize !=
report.SCSI.ReadCapabilities.BlockSize) report.SCSI.ReadCapabilities.BlockSize)
{ {
@@ -931,7 +979,7 @@ namespace DiscImageChef.Commands
jsonSw.Close(); jsonSw.Close();
jsonFs.Close(); jsonFs.Close();
Core.Statistics.AddCommand("device-report"); Statistics.AddCommand("device-report");
using(DicContext ctx = DicContext.Create(Settings.Settings.LocalDbPath)) using(DicContext ctx = DicContext.Create(Settings.Settings.LocalDbPath))
{ {
@@ -941,6 +989,7 @@ namespace DiscImageChef.Commands
// TODO: // TODO:
if(Settings.Settings.Current.ShareReports) Remote.SubmitReport(report); if(Settings.Settings.Current.ShareReports) Remote.SubmitReport(report);
return 0;
} }
} }
} }

View File

@@ -45,16 +45,111 @@ using DiscImageChef.Core;
using DiscImageChef.Core.Devices.Dumping; using DiscImageChef.Core.Devices.Dumping;
using DiscImageChef.Core.Logging; using DiscImageChef.Core.Logging;
using DiscImageChef.Devices; using DiscImageChef.Devices;
using Mono.Options;
using Schemas; using Schemas;
using Ata = DiscImageChef.Core.Devices.Dumping.Ata; using Ata = DiscImageChef.Core.Devices.Dumping.Ata;
using Scsi = DiscImageChef.Core.Devices.Dumping.Scsi; using Scsi = DiscImageChef.Core.Devices.Dumping.Scsi;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class DumpMedia class DumpMediaCommand : Command
{ {
internal static void DoDumpMedia(DumpMediaOptions options) string cicmXml;
string devicePath;
bool doResume = true;
string encodingName;
bool firstTrackPregap;
bool force;
bool noMetadata;
bool noTrim;
string outputFile;
string outputOptions;
bool persistent;
// TODO: Disabled temporarily
bool raw = false;
ushort retryPasses = 5;
bool showHelp;
int skip = 512;
bool stopOnError;
string wanteOutputFormat;
public DumpMediaCommand() : base("dump-media", "Dumps the media inserted on a device to a media image.")
{ {
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] devicepath outputimage",
"",
Help,
{"cicm-xml|x=", "Take metadata from existing CICM XML sidecar.", s => cicmXml = s},
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
{
"first-pregap", "Try to read first track pregap. Only applicable to CD/DDCD/GD.",
b => firstTrackPregap = b != null
},
{"force|f", "Continue dump whatever happens.", b => force = b != null},
{
"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 => wanteOutputFormat = s
},
{"no-metadata", "Disables creating CICM XML sidecar.", b => noMetadata = b != null},
{"no-trim", "Disables trimming errored from skipped sectors.", b => noTrim = b != null},
{
"options|O=", "Comma separated name=value pairs of options to pass to output image plugin.",
s => outputOptions = s
},
{"persistent", "Try to recover partial or incorrect data.", b => persistent = b != null},
/* TODO: Disabled temporarily
{ "raw|r", "Dump sectors with tags included. For optical media, dump scrambled sectors.", (b) => Raw = b != null}, */
{
"resume|r", "Create/use resume mapfile.",
b => doResume = b != null
},
{"retry-passes|p=", "How many retry passes to do.", (ushort us) => retryPasses = us},
{"skip|k=", "When an unreadable sector is found skip this many sectors.", (int i) => skip = i},
{
"stop-on-error|s", "Stop media dump on first error.",
b => stopOnError = b != null
},
{
"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 0;
}
MainClass.PrintCopyright();
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(extra.Count > 2)
{
DicConsole.ErrorWriteLine("Too many arguments.");
return 1;
}
if(extra.Count <= 1)
{
DicConsole.ErrorWriteLine("Missing paths.");
return 1;
}
devicePath = extra[0];
outputFile = extra[1];
// TODO: Be able to cancel hashing // TODO: Be able to cancel hashing
Sidecar.InitProgressEvent += Progress.InitProgress; Sidecar.InitProgressEvent += Progress.InitProgress;
Sidecar.UpdateProgressEvent += Progress.UpdateProgress; Sidecar.UpdateProgressEvent += Progress.UpdateProgress;
@@ -64,65 +159,64 @@ namespace DiscImageChef.Commands
Sidecar.EndProgressEvent2 += Progress.EndProgress2; Sidecar.EndProgressEvent2 += Progress.EndProgress2;
Sidecar.UpdateStatusEvent += Progress.UpdateStatus; Sidecar.UpdateStatusEvent += Progress.UpdateStatus;
DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", options.Debug); DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", cicmXml);
DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", options.Verbose); DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", options.DevicePath); 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}", wanteOutputFormat);
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);
// TODO: Disabled temporarily // TODO: Disabled temporarily
//DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", options.Raw); //DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw);
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", options.StopOnError); DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", doResume);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force); DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", retryPasses);
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", options.RetryPasses); DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", skip);
DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", options.Persistent); DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", stopOnError);
DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", options.Resume); DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Dump-Media command", "--first-pregap={0}", options.FirstTrackPregap);
DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", options.EncodingName);
DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", options.OutputFile);
DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", options.OutputFormat);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force);
DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", options.Options);
DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", options.CicmXml);
DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", options.Skip);
DicConsole.DebugWriteLine("Dump-Media command", "--no-metadata={0}", options.NoMetadata);
Dictionary<string, string> parsedOptions = Options.Parse(options.Options); Dictionary<string, string> parsedOptions = Core.Options.Parse(outputOptions);
DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:"); DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions) foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Dump-Media command", "{0} = {1}", parsedOption.Key, parsedOption.Value); DicConsole.DebugWriteLine("Dump-Media command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
Encoding encoding = null; Encoding encoding = null;
if(options.EncodingName != null) if(encodingName != null)
try try
{ {
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName); encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
} }
catch(ArgumentException) catch(ArgumentException)
{ {
DicConsole.ErrorWriteLine("Specified encoding is not supported."); DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return; return 1;
} }
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' && if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
char.IsLetter(options.DevicePath[0])) devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':';
Device dev = new Device(options.DevicePath); Device dev = new Device(devicePath);
if(dev.Error) if(dev.Error)
{ {
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError); DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return; return 2;
} }
Core.Statistics.AddDevice(dev); Statistics.AddDevice(dev);
string outputPrefix = Path.Combine(Path.GetDirectoryName(options.OutputFile), string outputPrefix = Path.Combine(Path.GetDirectoryName(outputFile),
Path.GetFileNameWithoutExtension(options.OutputFile)); Path.GetFileNameWithoutExtension(outputFile));
Resume resume = null; Resume resume = null;
XmlSerializer xs = new XmlSerializer(typeof(Resume)); XmlSerializer xs = new XmlSerializer(typeof(Resume));
if(File.Exists(outputPrefix + ".resume.xml") && options.Resume) if(File.Exists(outputPrefix + ".resume.xml") && doResume)
try try
{ {
StreamReader sr = new StreamReader(outputPrefix + ".resume.xml"); StreamReader sr = new StreamReader(outputPrefix + ".resume.xml");
@@ -132,71 +226,70 @@ namespace DiscImageChef.Commands
catch catch
{ {
DicConsole.ErrorWriteLine("Incorrect resume file, not continuing..."); DicConsole.ErrorWriteLine("Incorrect resume file, not continuing...");
return; return 3;
} }
if(resume != null && resume.NextBlock > resume.LastBlock && resume.BadBlocks.Count == 0) if(resume != null && resume.NextBlock > resume.LastBlock && resume.BadBlocks.Count == 0)
{ {
DicConsole.WriteLine("Media already dumped correctly, not continuing..."); DicConsole.WriteLine("Media already dumped correctly, not continuing...");
return; return 4;
} }
CICMMetadataType sidecar = null; CICMMetadataType sidecar = null;
XmlSerializer sidecarXs = new XmlSerializer(typeof(CICMMetadataType)); XmlSerializer sidecarXs = new XmlSerializer(typeof(CICMMetadataType));
if(options.CicmXml != null) if(cicmXml != null)
if(File.Exists(options.CicmXml)) if(File.Exists(cicmXml))
try try
{ {
StreamReader sr = new StreamReader(options.CicmXml); StreamReader sr = new StreamReader(cicmXml);
sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr); sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
sr.Close(); sr.Close();
} }
catch catch
{ {
DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing..."); DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing...");
return; return 5;
} }
else else
{ {
DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing..."); DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing...");
return; return 6;
} }
PluginBase plugins = GetPluginBase.Instance; PluginBase plugins = GetPluginBase.Instance;
List<IWritableImage> candidates = new List<IWritableImage>(); List<IWritableImage> candidates = new List<IWritableImage>();
// Try extension // Try extension
if(string.IsNullOrEmpty(options.OutputFormat)) if(string.IsNullOrEmpty(wanteOutputFormat))
candidates.AddRange(plugins.WritableImages.Values.Where(t => candidates.AddRange(plugins.WritableImages.Values.Where(t =>
t.KnownExtensions t.KnownExtensions
.Contains(Path.GetExtension(options .Contains(Path.GetExtension(outputFile))));
.OutputFile))));
// Try Id // Try Id
else if(Guid.TryParse(options.OutputFormat, out Guid outId)) else if(Guid.TryParse(wanteOutputFormat, out Guid outId))
candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId))); candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId)));
// Try name // Try name
else else
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, options.OutputFormat, candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, wanteOutputFormat,
StringComparison StringComparison
.InvariantCultureIgnoreCase))); .InvariantCultureIgnoreCase)));
if(candidates.Count == 0) if(candidates.Count == 0)
{ {
DicConsole.WriteLine("No plugin supports requested extension."); DicConsole.WriteLine("No plugin supports requested extension.");
return; return 7;
} }
if(candidates.Count > 1) if(candidates.Count > 1)
{ {
DicConsole.WriteLine("More than one plugin supports requested extension."); DicConsole.WriteLine("More than one plugin supports requested extension.");
return; return 8;
} }
IWritableImage outputFormat = candidates[0]; IWritableImage outputFormat = candidates[0];
DumpLog dumpLog = new DumpLog(outputPrefix + ".log", dev); DumpLog dumpLog = new DumpLog(outputPrefix + ".log", dev);
if(options.Verbose) if(MainClass.Verbose)
{ {
dumpLog.WriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id); dumpLog.WriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id);
DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id); DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id);
@@ -209,41 +302,33 @@ namespace DiscImageChef.Commands
if(dev.IsUsb && dev.UsbVendorId == 0x054C && if(dev.IsUsb && dev.UsbVendorId == 0x054C &&
(dev.UsbProductId == 0x01C8 || dev.UsbProductId == 0x01C9 || dev.UsbProductId == 0x02D2)) (dev.UsbProductId == 0x01C8 || dev.UsbProductId == 0x01C9 || dev.UsbProductId == 0x02D2))
PlayStationPortable.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, PlayStationPortable.Dump(dev, devicePath, outputFormat, retryPasses, force, persistent, stopOnError,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, ref resume, ref dumpLog, encoding, outputPrefix, outputFile, parsedOptions,
outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, sidecar, (uint)skip, noMetadata, noTrim);
options.NoMetadata, options.NoTrim);
else else
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA:
Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, Ata.Dump(dev, devicePath, outputFormat, retryPasses, force, false, /*raw,*/
false, /*options.Raw,*/ persistent, stopOnError, ref resume, ref dumpLog, encoding, outputPrefix, outputFile,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, parsedOptions, sidecar, (uint)skip, noMetadata, noTrim);
outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
options.NoMetadata, options.NoTrim);
break; break;
case DeviceType.MMC: case DeviceType.MMC:
case DeviceType.SecureDigital: case DeviceType.SecureDigital:
SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, SecureDigital.Dump(dev, devicePath, outputFormat, retryPasses, force, false, /*raw,*/
false, /*options.Raw,*/ options.Persistent, options.StopOnError, ref resume, persistent, stopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
ref dumpLog, encoding, outputPrefix, options.OutputFile, parsedOptions, outputFile, parsedOptions, sidecar, (uint)skip, noMetadata, noTrim);
sidecar, (uint)options.Skip, options.NoMetadata, options.NoTrim);
break; break;
case DeviceType.NVMe: case DeviceType.NVMe:
NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, NvMe.Dump(dev, devicePath, outputFormat, retryPasses, force, false, /*raw,*/
false, /*options.Raw,*/ persistent, stopOnError, ref resume, ref dumpLog, encoding, outputPrefix, outputFile,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, parsedOptions, sidecar, (uint)skip, noMetadata, noTrim);
outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
options.NoMetadata, options.NoTrim);
break; break;
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI:
Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, Scsi.Dump(dev, devicePath, outputFormat, retryPasses, force, false, /*raw,*/
false, /*options.Raw,*/ persistent, stopOnError, ref resume, ref dumpLog, firstTrackPregap, encoding,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, outputPrefix, outputFile, parsedOptions, sidecar, (uint)skip, noMetadata, noTrim);
options.FirstTrackPregap, encoding, outputPrefix, options.OutputFile, parsedOptions,
sidecar, (uint)options.Skip, options.NoMetadata, options.NoTrim);
break; break;
default: default:
dumpLog.WriteLine("Unknown device type."); dumpLog.WriteLine("Unknown device type.");
@@ -251,7 +336,7 @@ namespace DiscImageChef.Commands
throw new NotSupportedException("Unknown device type."); throw new NotSupportedException("Unknown device type.");
} }
if(resume != null && options.Resume) if(resume != null && doResume)
{ {
resume.LastWriteDate = DateTime.UtcNow; resume.LastWriteDate = DateTime.UtcNow;
resume.BadBlocks.Sort(); resume.BadBlocks.Sort();
@@ -266,9 +351,10 @@ namespace DiscImageChef.Commands
dumpLog.Close(); dumpLog.Close();
Core.Statistics.AddCommand("dump-media"); Statistics.AddCommand("dump-media");
dev.Close(); dev.Close();
return 0;
} }
} }
} }

View File

@@ -30,31 +30,90 @@
// Copyright © 2011-2019 Natalia Portillo // Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Entropy class EntropyCommand : Command
{ {
internal static void DoEntropy(EntropyOptions options) 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.")
{ {
DicConsole.DebugWriteLine("Entropy command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Entropy command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Entropy command", "--separated-tracks={0}", options.SeparatedTracks); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Entropy command", "--whole-disc={0}", options.WholeDisc); $"{MainClass.AssemblyCopyright}",
DicConsole.DebugWriteLine("Entropy command", "--input={0}", options.InputFile); "",
DicConsole.DebugWriteLine("Entropy command", "--duplicated-sectors={0}", options.DuplicatedSectors); $"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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
inputFile = extra[0];
DicConsole.DebugWriteLine("Entropy command", "--debug={0}", MainClass.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);
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 1;
} }
IMediaImage inputFormat = ImageFormat.Detect(inputFilter); IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -62,15 +121,15 @@ namespace DiscImageChef.Commands
if(inputFormat == null) if(inputFormat == null)
{ {
DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming"); DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming");
return; return 2;
} }
inputFormat.Open(inputFilter); inputFormat.Open(inputFilter);
Core.Statistics.AddMediaFormat(inputFormat.Format); Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
Core.Entropy entropyCalculator = new Core.Entropy(options.Debug, options.Verbose, inputFormat); Entropy entropyCalculator = new Entropy(MainClass.Debug, MainClass.Verbose, inputFormat);
entropyCalculator.InitProgressEvent += Progress.InitProgress; entropyCalculator.InitProgressEvent += Progress.InitProgress;
entropyCalculator.InitProgress2Event += Progress.InitProgress2; entropyCalculator.InitProgress2Event += Progress.InitProgress2;
entropyCalculator.UpdateProgressEvent += Progress.UpdateProgress; entropyCalculator.UpdateProgressEvent += Progress.UpdateProgress;
@@ -78,9 +137,9 @@ namespace DiscImageChef.Commands
entropyCalculator.EndProgressEvent += Progress.EndProgress; entropyCalculator.EndProgressEvent += Progress.EndProgress;
entropyCalculator.EndProgress2Event += Progress.EndProgress2; entropyCalculator.EndProgress2Event += Progress.EndProgress2;
if(options.SeparatedTracks) if(separatedTracks)
{ {
EntropyResults[] tracksEntropy = entropyCalculator.CalculateTracksEntropy(options.DuplicatedSectors); EntropyResults[] tracksEntropy = entropyCalculator.CalculateTracksEntropy(duplicatedSectors);
foreach(EntropyResults trackEntropy in tracksEntropy) foreach(EntropyResults trackEntropy in tracksEntropy)
{ {
DicConsole.WriteLine("Entropy for track {0} is {1:F4}.", trackEntropy.Track, trackEntropy.Entropy); DicConsole.WriteLine("Entropy for track {0} is {1:F4}.", trackEntropy.Track, trackEntropy.Entropy);
@@ -91,20 +150,21 @@ namespace DiscImageChef.Commands
} }
} }
if(!options.WholeDisc) if(!wholeDisc)
{ {
Core.Statistics.AddCommand("entropy"); Statistics.AddCommand("entropy");
return; return 0;
} }
EntropyResults entropy = entropyCalculator.CalculateMediaEntropy(options.DuplicatedSectors); EntropyResults entropy = entropyCalculator.CalculateMediaEntropy(duplicatedSectors);
DicConsole.WriteLine("Entropy for disk is {0:F4}.", entropy.Entropy); DicConsole.WriteLine("Entropy for disk is {0:F4}.", entropy.Entropy);
if(entropy.UniqueSectors != null) if(entropy.UniqueSectors != null)
DicConsole.WriteLine("Disk has {0} unique sectors ({1:P3})", entropy.UniqueSectors, DicConsole.WriteLine("Disk has {0} unique sectors ({1:P3})", entropy.UniqueSectors,
(double)entropy.UniqueSectors / (double)entropy.Sectors); (double)entropy.UniqueSectors / (double)entropy.Sectors);
Core.Statistics.AddCommand("entropy"); Statistics.AddCommand("entropy");
return 0;
} }
} }
} }

View File

@@ -39,47 +39,106 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs; using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
// TODO: Rewrite this, has an insane amount of repeating code ;) class ExtractFilesCommand : Command
static class ExtractFiles
{ {
internal static void DoExtractFiles(ExtractFilesOptions options) string encodingName;
bool extractXattrs;
string inputFile;
string outputDir;
string pluginOptions;
bool showHelp;
public ExtractFilesCommand() : base("extract-files", "Extracts all files in disc image.")
{ {
DicConsole.DebugWriteLine("Extract-Files command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Extract-Files command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Extract-Files command", "--input={0}", options.InputFile); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Extract-Files command", "--xattrs={0}", options.Xattrs); $"{MainClass.AssemblyCopyright}",
DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", options.OutputDir); "",
$"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},
{"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 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
Dictionary<string, string> parsedOptions = Options.Parse(options.Options); Dictionary<string, string> parsedOptions = Core.Options.Parse(pluginOptions);
DicConsole.DebugWriteLine("Extract-Files command", "Parsed options:"); DicConsole.DebugWriteLine("Extract-Files command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions) foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Extract-Files command", "{0} = {1}", parsedOption.Key, parsedOption.Value); DicConsole.DebugWriteLine("Extract-Files command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
parsedOptions.Add("debug", options.Debug.ToString()); parsedOptions.Add("debug", MainClass.Debug.ToString());
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 0;
} }
Encoding encoding = null; Encoding encoding = null;
if(options.EncodingName != null) if(encodingName != null)
try try
{ {
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName); encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
} }
catch(ArgumentException) catch(ArgumentException)
{ {
DicConsole.ErrorWriteLine("Specified encoding is not supported."); DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return; return 1;
} }
PluginBase plugins = GetPluginBase.Instance; PluginBase plugins = GetPluginBase.Instance;
@@ -91,21 +150,21 @@ namespace DiscImageChef.Commands
if(imageFormat == null) if(imageFormat == null)
{ {
DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
return; return 2;
} }
if(options.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
imageFormat.Id); imageFormat.Id);
else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
if(Directory.Exists(options.OutputDir) || File.Exists(options.OutputDir)) if(Directory.Exists(outputDir) || File.Exists(outputDir))
{ {
DicConsole.ErrorWriteLine("Destination exists, aborting."); DicConsole.ErrorWriteLine("Destination exists, aborting.");
return; return 3;
} }
Directory.CreateDirectory(options.OutputDir); Directory.CreateDirectory(outputDir);
try try
{ {
@@ -113,7 +172,7 @@ namespace DiscImageChef.Commands
{ {
DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given"); DicConsole.WriteLine("No error given");
return; return 4;
} }
DicConsole.DebugWriteLine("Extract-Files command", "Correctly opened image file."); DicConsole.DebugWriteLine("Extract-Files command", "Correctly opened image file.");
@@ -124,15 +183,15 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Extract-Files command", "Image identifies disk type as {0}.", DicConsole.DebugWriteLine("Extract-Files command", "Image identifies disk type as {0}.",
imageFormat.Info.MediaType); imageFormat.Info.MediaType);
Core.Statistics.AddMediaFormat(imageFormat.Format); Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddMedia(imageFormat.Info.MediaType, false); Statistics.AddMedia(imageFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
} }
catch(Exception ex) catch(Exception ex)
{ {
DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message); DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return; return 5;
} }
List<Partition> partitions = Core.Partitions.GetAll(imageFormat); List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
@@ -185,7 +244,7 @@ namespace DiscImageChef.Commands
{ {
string outputPath; string outputPath;
FileStream outputFile; FileStream outputFile;
if(options.Xattrs) if(extractXattrs)
{ {
error = fs.ListXAttr(entry, out List<string> xattrs); error = fs.ListXAttr(entry, out List<string> xattrs);
if(error == Errno.NoError) if(error == Errno.NoError)
@@ -195,14 +254,15 @@ namespace DiscImageChef.Commands
error = fs.GetXattr(entry, xattr, ref xattrBuf); error = fs.GetXattr(entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue; if(error != Errno.NoError) continue;
Directory Directory.CreateDirectory(Path.Combine(outputDir,
.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFsType
fs.XmlFsType.Type, .Type,
volumeName, ".xattrs", volumeName,
xattr)); ".xattrs",
xattr));
outputPath = outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, Path.Combine(outputDir, fs.XmlFsType.Type,
volumeName, ".xattrs", xattr, entry); volumeName, ".xattrs", xattr, entry);
if(!File.Exists(outputPath)) if(!File.Exists(outputPath))
@@ -245,13 +305,11 @@ namespace DiscImageChef.Commands
} }
} }
Directory.CreateDirectory(Path.Combine(options.OutputDir, Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type,
fs.XmlFsType.Type,
volumeName)); volumeName));
outputPath = outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, entry);
entry);
if(!File.Exists(outputPath)) if(!File.Exists(outputPath))
{ {
@@ -304,7 +362,7 @@ namespace DiscImageChef.Commands
DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", DicConsole.ErrorWriteLine("Error {0} reading root directory {0}",
error.ToString()); error.ToString());
Core.Statistics.AddFilesystem(fs.XmlFsType.Type); Statistics.AddFilesystem(fs.XmlFsType.Type);
} }
else else
DicConsole.ErrorWriteLine("Unable to mount device, error {0}", DicConsole.ErrorWriteLine("Unable to mount device, error {0}",
@@ -335,7 +393,7 @@ namespace DiscImageChef.Commands
{ {
FileStream outputFile; FileStream outputFile;
string outputPath; string outputPath;
if(options.Xattrs) if(extractXattrs)
{ {
error = fs.ListXAttr(entry, out List<string> xattrs); error = fs.ListXAttr(entry, out List<string> xattrs);
if(error == Errno.NoError) if(error == Errno.NoError)
@@ -345,14 +403,14 @@ namespace DiscImageChef.Commands
error = fs.GetXattr(entry, xattr, ref xattrBuf); error = fs.GetXattr(entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue; if(error != Errno.NoError) continue;
Directory.CreateDirectory(Path.Combine(options.OutputDir, Directory.CreateDirectory(Path.Combine(outputDir,
fs.XmlFsType.Type, fs.XmlFsType.Type,
volumeName, ".xattrs", volumeName, ".xattrs",
xattr)); xattr));
outputPath = outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, Path.Combine(outputDir, fs.XmlFsType.Type, volumeName,
volumeName, ".xattrs", xattr, entry); ".xattrs", xattr, entry);
if(!File.Exists(outputPath)) if(!File.Exists(outputPath))
{ {
@@ -392,11 +450,10 @@ namespace DiscImageChef.Commands
} }
} }
Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFsType.Type, Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type,
volumeName)); volumeName));
outputPath = outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, entry);
Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry);
if(!File.Exists(outputPath)) if(!File.Exists(outputPath))
{ {
@@ -447,7 +504,7 @@ namespace DiscImageChef.Commands
else else
DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
Core.Statistics.AddFilesystem(fs.XmlFsType.Type); 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());
} }
@@ -491,7 +548,7 @@ namespace DiscImageChef.Commands
{ {
FileStream outputFile; FileStream outputFile;
string outputPath; string outputPath;
if(options.Xattrs) if(extractXattrs)
{ {
error = fs.ListXAttr(entry, out List<string> xattrs); error = fs.ListXAttr(entry, out List<string> xattrs);
if(error == Errno.NoError) if(error == Errno.NoError)
@@ -501,14 +558,14 @@ namespace DiscImageChef.Commands
error = fs.GetXattr(entry, xattr, ref xattrBuf); error = fs.GetXattr(entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue; if(error != Errno.NoError) continue;
Directory.CreateDirectory(Path.Combine(options.OutputDir, Directory.CreateDirectory(Path.Combine(outputDir,
fs.XmlFsType.Type, fs.XmlFsType.Type,
volumeName, ".xattrs", volumeName, ".xattrs",
xattr)); xattr));
outputPath = outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, Path.Combine(outputDir, fs.XmlFsType.Type, volumeName,
volumeName, ".xattrs", xattr, entry); ".xattrs", xattr, entry);
if(!File.Exists(outputPath)) if(!File.Exists(outputPath))
{ {
@@ -548,11 +605,10 @@ namespace DiscImageChef.Commands
} }
} }
Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFsType.Type, Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type,
volumeName)); volumeName));
outputPath = outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, entry);
Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry);
if(!File.Exists(outputPath)) if(!File.Exists(outputPath))
{ {
@@ -603,7 +659,7 @@ namespace DiscImageChef.Commands
else else
DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
Core.Statistics.AddFilesystem(fs.XmlFsType.Type); 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());
} }
@@ -630,7 +686,7 @@ namespace DiscImageChef.Commands
{ {
string outputPath; string outputPath;
FileStream outputFile; FileStream outputFile;
if(options.Xattrs) if(extractXattrs)
{ {
error = fs.ListXAttr(entry, out List<string> xattrs); error = fs.ListXAttr(entry, out List<string> xattrs);
if(error == Errno.NoError) if(error == Errno.NoError)
@@ -640,13 +696,12 @@ namespace DiscImageChef.Commands
error = fs.GetXattr(entry, xattr, ref xattrBuf); error = fs.GetXattr(entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue; if(error != Errno.NoError) continue;
Directory.CreateDirectory(Path.Combine(options.OutputDir, Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type,
fs.XmlFsType.Type, volumeName, volumeName, ".xattrs", xattr));
".xattrs", xattr));
outputPath = outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, ".xattrs",
".xattrs", xattr, entry); xattr, entry);
if(!File.Exists(outputPath)) if(!File.Exists(outputPath))
{ {
@@ -686,10 +741,9 @@ namespace DiscImageChef.Commands
} }
} }
Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFsType.Type, Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type, volumeName));
volumeName));
outputPath = Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry); outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, entry);
if(!File.Exists(outputPath)) if(!File.Exists(outputPath))
{ {
@@ -734,7 +788,7 @@ namespace DiscImageChef.Commands
} }
else DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); else DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
Core.Statistics.AddFilesystem(fs.XmlFsType.Type); 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());
} }
@@ -745,7 +799,8 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Extract-Files command", ex.StackTrace); DicConsole.DebugWriteLine("Extract-Files command", ex.StackTrace);
} }
Core.Statistics.AddCommand("extract-files"); Statistics.AddCommand("extract-files");
return 0;
} }
} }
} }

View File

@@ -37,20 +37,59 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using DiscImageChef.Partitions; using DiscImageChef.Partitions;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Formats class FormatsCommand : Command
{ {
internal static void ListFormats(FormatsOptions formatsOptions) bool showHelp;
public FormatsCommand() : base("formats",
"Lists all supported disc images, partition schemes and file systems.")
{ {
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 0;
}
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 1;
}
DicConsole.DebugWriteLine("Formats command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Formats command", "--verbose={0}", MainClass.Verbose);
PluginBase plugins = GetPluginBase.Instance; PluginBase plugins = GetPluginBase.Instance;
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
DicConsole.WriteLine("Supported filters ({0}):", filtersList.Filters.Count); DicConsole.WriteLine("Supported filters ({0}):", filtersList.Filters.Count);
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tFilter"); if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tFilter");
foreach(KeyValuePair<string, IFilter> kvp in filtersList.Filters) foreach(KeyValuePair<string, IFilter> kvp in filtersList.Filters)
if(formatsOptions.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else else
DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(kvp.Value.Name);
@@ -59,22 +98,22 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Read-only media image formats ({0}):", DicConsole.WriteLine("Read-only media image formats ({0}):",
plugins.ImagePluginsList.Count(t => !t.Value.GetType().GetInterfaces() plugins.ImagePluginsList.Count(t => !t.Value.GetType().GetInterfaces()
.Contains(typeof(IWritableImage)))); .Contains(typeof(IWritableImage))));
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IMediaImage> kvp in plugins.ImagePluginsList.Where(t => !t.Value.GetType() foreach(KeyValuePair<string, IMediaImage> kvp in plugins.ImagePluginsList.Where(t => !t.Value.GetType()
.GetInterfaces() .GetInterfaces()
.Contains(typeof( .Contains(typeof(
IWritableImage IWritableImage
)))) ))))
if(formatsOptions.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else else
DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.WriteLine("Read/write media image formats ({0}):", plugins.WritableImages.Count); DicConsole.WriteLine("Read/write media image formats ({0}):", plugins.WritableImages.Count);
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IWritableImage> kvp in plugins.WritableImages) foreach(KeyValuePair<string, IWritableImage> kvp in plugins.WritableImages)
if(formatsOptions.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else else
DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(kvp.Value.Name);
@@ -83,13 +122,13 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Supported filesystems for identification and information only ({0}):", DicConsole.WriteLine("Supported filesystems for identification and information only ({0}):",
plugins.PluginsList.Count(t => !t.Value.GetType().GetInterfaces() plugins.PluginsList.Count(t => !t.Value.GetType().GetInterfaces()
.Contains(typeof(IReadOnlyFilesystem)))); .Contains(typeof(IReadOnlyFilesystem))));
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IFilesystem> kvp in plugins.PluginsList.Where(t => !t.Value.GetType() foreach(KeyValuePair<string, IFilesystem> kvp in plugins.PluginsList.Where(t => !t.Value.GetType()
.GetInterfaces() .GetInterfaces()
.Contains(typeof( .Contains(typeof(
IReadOnlyFilesystem IReadOnlyFilesystem
)))) ))))
if(formatsOptions.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else else
DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(kvp.Value.Name);
@@ -97,23 +136,24 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.WriteLine("Supported filesystems that can read their contents ({0}):", DicConsole.WriteLine("Supported filesystems that can read their contents ({0}):",
plugins.ReadOnlyFilesystems.Count); plugins.ReadOnlyFilesystems.Count);
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IReadOnlyFilesystem> kvp in plugins.ReadOnlyFilesystems) foreach(KeyValuePair<string, IReadOnlyFilesystem> kvp in plugins.ReadOnlyFilesystems)
if(formatsOptions.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else else
DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.WriteLine("Supported partitioning schemes ({0}):", plugins.PartPluginsList.Count); DicConsole.WriteLine("Supported partitioning schemes ({0}):", plugins.PartPluginsList.Count);
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); if(MainClass.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, IPartition> kvp in plugins.PartPluginsList) foreach(KeyValuePair<string, IPartition> kvp in plugins.PartPluginsList)
if(formatsOptions.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name); DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else else
DicConsole.WriteLine(kvp.Value.Name); DicConsole.WriteLine(kvp.Value.Name);
Core.Statistics.AddCommand("formats"); Statistics.AddCommand("formats");
return 0;
} }
} }
} }

View File

@@ -0,0 +1,83 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : Gui.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Verbs.
//
// --[ Description ] ----------------------------------------------------------
//
// Implements the 'gui' verb.
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.Console;
using DiscImageChef.Gui.Forms;
using Eto;
using Eto.Forms;
using Mono.Options;
using Command = Mono.Options.Command;
namespace DiscImageChef.Commands
{
class GuiCommand : Command
{
bool showHelp;
public GuiCommand() : base("gui", "Opens the in-progress GUI.")
{
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 0;
}
if(extra.Count > 0)
{
MainClass.PrintCopyright();
DicConsole.ErrorWriteLine("Too many arguments.");
return 1;
}
new Application(Platform.Detect).Run(new frmMain(MainClass.Debug, MainClass.Verbose));
return 0;
}
}
}

View File

@@ -31,28 +31,75 @@
// ****************************************************************************/ // ****************************************************************************/
using System; using System;
using System.Collections.Generic;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class ImageInfo class ImageInfoCommand : Command
{ {
internal static void GetImageInfo(ImageInfoOptions options) string inputFile;
bool showHelp;
public ImageInfoCommand() : base("image-info",
"Opens a media image and shows information about the media it represents and metadata.")
{ {
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Analyze command", "--input={0}", options.InputFile); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} imagefile",
"",
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 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 1;
} }
try try
@@ -62,7 +109,7 @@ namespace DiscImageChef.Commands
if(imageFormat == null) if(imageFormat == null)
{ {
DicConsole.WriteLine("Image format not identified."); DicConsole.WriteLine("Image format not identified.");
return; return 2;
} }
DicConsole.WriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); DicConsole.WriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id);
@@ -74,14 +121,14 @@ namespace DiscImageChef.Commands
{ {
DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given"); DicConsole.WriteLine("No error given");
return; return 3;
} }
Core.ImageInfo.PrintImageInfo(imageFormat); ImageInfo.PrintImageInfo(imageFormat);
Core.Statistics.AddMediaFormat(imageFormat.Format); Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddMedia(imageFormat.Info.MediaType, false); Statistics.AddMedia(imageFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
} }
catch(Exception ex) catch(Exception ex)
{ {
@@ -96,7 +143,8 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Image-info command", ex.StackTrace); DicConsole.DebugWriteLine("Image-info command", ex.StackTrace);
} }
Core.Statistics.AddCommand("image-info"); Statistics.AddCommand("image-info");
return 0;
} }
} }
} }

View File

@@ -30,20 +30,57 @@
// Copyright © 2011-2019 Natalia Portillo // Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
using System.Collections.Generic;
using System.Linq; using System.Linq;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Devices; using DiscImageChef.Devices;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class ListDevices class ListDevicesCommand : Command
{ {
internal static void DoListDevices(ListDevicesOptions options) bool showHelp;
{
DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", options.Debug);
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.Verbose);
Devices.DeviceInfo[] devices = Device.ListDevices(); public ListDevicesCommand() : base("list-devices", "Lists all connected devices.")
{
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 0;
}
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 1;
}
DicConsole.DebugWriteLine("List-Devices command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("List-Devices command", "--verbose={0}", MainClass.Verbose);
DeviceInfo[] devices = Device.ListDevices();
if(devices == null || devices.Length == 0) DicConsole.WriteLine("No known devices attached."); if(devices == null || devices.Length == 0) DicConsole.WriteLine("No known devices attached.");
else else
@@ -55,12 +92,13 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("{0,-22}+{1,-16}+{2,-24}+{3,-24}+{4,-10}+{5,-10}", "----------------------", DicConsole.WriteLine("{0,-22}+{1,-16}+{2,-24}+{3,-24}+{4,-10}+{5,-10}", "----------------------",
"----------------", "------------------------", "------------------------", "----------------", "------------------------", "------------------------",
"----------", "----------"); "----------", "----------");
foreach(Devices.DeviceInfo dev in devices) foreach(DeviceInfo dev in devices)
DicConsole.WriteLine("{0,-22}|{1,-16}|{2,-24}|{3,-24}|{4,-10}|{5,-10}", dev.Path, dev.Vendor, DicConsole.WriteLine("{0,-22}|{1,-16}|{2,-24}|{3,-24}|{4,-10}|{5,-10}", dev.Path, dev.Vendor,
dev.Model, dev.Serial, dev.Bus, dev.Supported); dev.Model, dev.Serial, dev.Bus, dev.Supported);
} }
Core.Statistics.AddCommand("list-devices"); Statistics.AddCommand("list-devices");
return 0;
} }
} }
} }

View File

@@ -34,13 +34,52 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class ListEncodings class ListEncodingsCommand : Command
{ {
internal static void DoList() bool showHelp;
public ListEncodingsCommand() : base("list-encodings", "Lists all supported text encodings and code pages.")
{ {
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 0;
}
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 1;
}
DicConsole.DebugWriteLine("List-Encodings command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("List-Encodings command", "--verbose={0}", MainClass.Verbose);
List<CommonEncodingInfo> encodings = Encoding List<CommonEncodingInfo> encodings = Encoding
.GetEncodings().Select(info => new CommonEncodingInfo .GetEncodings().Select(info => new CommonEncodingInfo
{ {
@@ -59,7 +98,8 @@ namespace DiscImageChef.Commands
foreach(CommonEncodingInfo info in encodings.OrderBy(t => t.DisplayName)) foreach(CommonEncodingInfo info in encodings.OrderBy(t => t.DisplayName))
DicConsole.WriteLine("{0,-16} {1,-8}", info.Name, info.DisplayName); DicConsole.WriteLine("{0,-16} {1,-8}", info.Name, info.DisplayName);
Core.Statistics.AddCommand("list-encodings"); Statistics.AddCommand("list-encodings");
return 0;
} }
struct CommonEncodingInfo struct CommonEncodingInfo

View File

@@ -37,13 +37,52 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class ListOptions class ListOptionsCommand : Command
{ {
internal static void DoList() bool showHelp;
public ListOptionsCommand() : base("list-options",
"Lists all options supported by read-only filesystems and writable media images.")
{ {
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 0;
}
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 1;
}
DicConsole.DebugWriteLine("List-Options command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("List-Options command", "--verbose={0}", MainClass.Verbose);
PluginBase plugins = GetPluginBase.Instance; PluginBase plugins = GetPluginBase.Instance;
DicConsole.WriteLine("Read-only filesystems options:"); DicConsole.WriteLine("Read-only filesystems options:");
@@ -77,6 +116,8 @@ namespace DiscImageChef.Commands
option.@default, option.description); option.@default, option.description);
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
return 0;
} }
static string TypeToString(Type type) static string TypeToString(Type type)

View File

@@ -38,44 +38,99 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs; using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Ls class LsCommand : Command
{ {
internal static void DoLs(LsOptions options) string encodingName;
string inputFile;
bool longFormat;
string pluginOptions;
bool showHelp;
public LsCommand() : base("ls", "Lists files in disc image.")
{ {
DicConsole.DebugWriteLine("Ls command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Ls command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Ls command", "--input={0}", options.InputFile); $"{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},
{
"options|O=", "Comma separated name=value pairs of options to pass to filesystem plugin.",
s => pluginOptions = s
},
{"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 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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);
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
Dictionary<string, string> parsedOptions = Options.Parse(options.Options); Dictionary<string, string> parsedOptions = Core.Options.Parse(pluginOptions);
DicConsole.DebugWriteLine("Ls command", "Parsed options:"); DicConsole.DebugWriteLine("Ls command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions) foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Ls command", "{0} = {1}", parsedOption.Key, parsedOption.Value); DicConsole.DebugWriteLine("Ls command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
parsedOptions.Add("debug", options.Debug.ToString()); parsedOptions.Add("debug", MainClass.Debug.ToString());
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 1;
} }
Encoding encoding = null; Encoding encoding = null;
if(options.EncodingName != null) if(encodingName != null)
try try
{ {
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName); encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
} }
catch(ArgumentException) catch(ArgumentException)
{ {
DicConsole.ErrorWriteLine("Specified encoding is not supported."); DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return; return 2;
} }
PluginBase plugins = GetPluginBase.Instance; PluginBase plugins = GetPluginBase.Instance;
@@ -87,10 +142,10 @@ namespace DiscImageChef.Commands
if(imageFormat == null) if(imageFormat == null)
{ {
DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
return; return 3;
} }
if(options.Verbose) if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
imageFormat.Id); imageFormat.Id);
else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); else DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
@@ -101,7 +156,7 @@ namespace DiscImageChef.Commands
{ {
DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given"); DicConsole.WriteLine("No error given");
return; return 4;
} }
DicConsole.DebugWriteLine("Ls command", "Correctly opened image file."); DicConsole.DebugWriteLine("Ls command", "Correctly opened image file.");
@@ -111,15 +166,15 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.", DicConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.",
imageFormat.Info.MediaType); imageFormat.Info.MediaType);
Core.Statistics.AddMediaFormat(imageFormat.Format); Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddMedia(imageFormat.Info.MediaType, false); Statistics.AddMedia(imageFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
} }
catch(Exception ex) catch(Exception ex)
{ {
DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message); DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return; return 3;
} }
List<Partition> partitions = Core.Partitions.GetAll(imageFormat); List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
@@ -168,7 +223,7 @@ namespace DiscImageChef.Commands
DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", DicConsole.ErrorWriteLine("Error {0} reading root directory {0}",
error.ToString()); error.ToString());
Core.Statistics.AddFilesystem(fs.XmlFsType.Type); Statistics.AddFilesystem(fs.XmlFsType.Type);
} }
else else
DicConsole.ErrorWriteLine("Unable to mount device, error {0}", DicConsole.ErrorWriteLine("Unable to mount device, error {0}",
@@ -196,7 +251,7 @@ namespace DiscImageChef.Commands
else else
DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
Core.Statistics.AddFilesystem(fs.XmlFsType.Type); 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());
} }
@@ -235,7 +290,7 @@ namespace DiscImageChef.Commands
else else
DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
Core.Statistics.AddFilesystem(fs.XmlFsType.Type); 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());
} }
@@ -257,7 +312,7 @@ namespace DiscImageChef.Commands
error = fs.ReadDir("/", out List<string> rootDir); error = fs.ReadDir("/", out List<string> rootDir);
if(error == Errno.NoError) if(error == Errno.NoError)
foreach(string entry in rootDir) foreach(string entry in rootDir)
if(options.Long) if(longFormat)
{ {
error = fs.Stat(entry, out FileEntryInfo stat); error = fs.Stat(entry, out FileEntryInfo stat);
if(error == Errno.NoError) if(error == Errno.NoError)
@@ -284,7 +339,7 @@ namespace DiscImageChef.Commands
else else
DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
Core.Statistics.AddFilesystem(fs.XmlFsType.Type); 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());
} }
@@ -297,7 +352,8 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Ls command", ex.StackTrace); DicConsole.DebugWriteLine("Ls command", ex.StackTrace);
} }
Core.Statistics.AddCommand("ls"); Statistics.AddCommand("ls");
return 0;
} }
} }
} }

View File

@@ -44,6 +44,7 @@ using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Decoders.SCSI.SSC; using DiscImageChef.Decoders.SCSI.SSC;
using DiscImageChef.Decoders.Xbox; using DiscImageChef.Decoders.Xbox;
using DiscImageChef.Devices; using DiscImageChef.Devices;
using Mono.Options;
using BCA = DiscImageChef.Decoders.Bluray.BCA; using BCA = DiscImageChef.Decoders.Bluray.BCA;
using Cartridge = DiscImageChef.Decoders.DVD.Cartridge; using Cartridge = DiscImageChef.Decoders.DVD.Cartridge;
using DDS = DiscImageChef.Decoders.DVD.DDS; using DDS = DiscImageChef.Decoders.DVD.DDS;
@@ -52,28 +53,75 @@ using Spare = DiscImageChef.Decoders.DVD.Spare;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class MediaInfo class MediaInfoCommand : Command
{ {
internal static void DoMediaInfo(MediaInfoOptions options) string devicePath;
string outputPrefix;
bool showHelp;
public MediaInfoCommand() : base("media-info", "Gets information about the media inserted on a device.")
{ {
DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Media-Info command", "--device={0}", options.DevicePath); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Media-Info command", "--output-prefix={0}", options.OutputPrefix); $"{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
}
};
}
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' && public override int Invoke(IEnumerable<string> arguments)
char.IsLetter(options.DevicePath[0])) {
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':'; List<string> extra = Options.Parse(arguments);
Device dev = new Device(options.DevicePath); if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing device path.");
return 1;
}
devicePath = extra[0];
DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", MainClass.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);
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
Device dev = new Device(devicePath);
if(dev.Error) if(dev.Error)
{ {
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError); DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return; return 1;
} }
Core.Statistics.AddDevice(dev); Statistics.AddDevice(dev);
switch(dev.Type) switch(dev.Type)
{ {
@@ -85,16 +133,18 @@ namespace DiscImageChef.Commands
DoSdMediaInfo(); DoSdMediaInfo();
break; break;
case DeviceType.NVMe: case DeviceType.NVMe:
DoNvmeMediaInfo(options.OutputPrefix, dev); DoNvmeMediaInfo(outputPrefix, dev);
break; break;
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI:
DoScsiMediaInfo(options.OutputPrefix, dev); DoScsiMediaInfo(outputPrefix, dev);
break; break;
default: throw new NotSupportedException("Unknown device type."); default: throw new NotSupportedException("Unknown device type.");
} }
Core.Statistics.AddCommand("media-info"); Statistics.AddCommand("media-info");
return 0;
} }
static void DoAtaMediaInfo() static void DoAtaMediaInfo()
@@ -451,7 +501,7 @@ namespace DiscImageChef.Commands
} }
DicConsole.WriteLine("Media identified as {0}", scsiInfo.MediaType); DicConsole.WriteLine("Media identified as {0}", scsiInfo.MediaType);
Core.Statistics.AddMedia(scsiInfo.MediaType, true); Statistics.AddMedia(scsiInfo.MediaType, true);
dev.Close(); dev.Close();
} }

View File

@@ -31,54 +31,103 @@
// ****************************************************************************/ // ****************************************************************************/
using System; using System;
using System.Collections.Generic;
using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Core.Devices.Scanning; using DiscImageChef.Core.Devices.Scanning;
using DiscImageChef.Devices; using DiscImageChef.Devices;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class MediaScan class MediaScanCommand : Command
{ {
internal static void DoMediaScan(MediaScanOptions options) string devicePath;
string ibgLogPath;
string mhddLogPath;
bool showHelp;
public MediaScanCommand() : base("media-scan", "Scans the media inserted on a device.")
{ {
DicConsole.DebugWriteLine("Media-Scan command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Media-Scan command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Media-Scan command", "--device={0}", options.DevicePath); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Media-Scan command", "--mhdd-log={0}", options.MhddLogPath); $"{MainClass.AssemblyCopyright}",
DicConsole.DebugWriteLine("Media-Scan command", "--ibg-log={0}", options.IbgLogPath); "",
$"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}
};
}
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' && public override int Invoke(IEnumerable<string> arguments)
char.IsLetter(options.DevicePath[0])) {
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':'; List<string> extra = Options.Parse(arguments);
Device dev = new Device(options.DevicePath); if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing device path.");
return 1;
}
devicePath = extra[0];
DicConsole.DebugWriteLine("Media-Scan command", "--debug={0}", MainClass.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);
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
Device dev = new Device(devicePath);
if(dev.Error) if(dev.Error)
{ {
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError); DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return; return 1;
} }
Core.Statistics.AddDevice(dev); Statistics.AddDevice(dev);
ScanResults results; ScanResults results;
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA:
results = Ata.Scan(options.MhddLogPath, options.IbgLogPath, options.DevicePath, dev); results = Ata.Scan(mhddLogPath, ibgLogPath, devicePath, dev);
break; break;
case DeviceType.MMC: case DeviceType.MMC:
case DeviceType.SecureDigital: case DeviceType.SecureDigital:
results = SecureDigital.Scan(options.MhddLogPath, options.IbgLogPath, options.DevicePath, dev); results = SecureDigital.Scan(mhddLogPath, ibgLogPath, devicePath, dev);
break; break;
case DeviceType.NVMe: case DeviceType.NVMe:
results = Nvme.Scan(options.MhddLogPath, options.IbgLogPath, options.DevicePath, dev); results = Nvme.Scan(mhddLogPath, ibgLogPath, devicePath, dev);
break; break;
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI:
results = Scsi.Scan(options.MhddLogPath, options.IbgLogPath, options.DevicePath, dev); results = Scsi.Scan(mhddLogPath, ibgLogPath, devicePath, dev);
break; break;
default: throw new NotSupportedException("Unknown device type."); default: throw new NotSupportedException("Unknown device type.");
} }
@@ -109,9 +158,10 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Testing {0} seeks, longest seek took {1:F3} ms, fastest one took {2:F3} ms. ({3:F3} ms average)", 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); results.SeekTimes, results.SeekMax, results.SeekMin, results.SeekTotal / 1000);
Core.Statistics.AddCommand("media-scan"); Statistics.AddCommand("media-scan");
dev.Close(); dev.Close();
return 0;
} }
} }
} }

View File

@@ -30,32 +30,91 @@
// Copyright © 2011-2019 Natalia Portillo // Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class PrintHex class PrintHexCommand : Command
{ {
internal static void DoPrintHex(PrintHexOptions options) 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.")
{ {
DicConsole.DebugWriteLine("PrintHex command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("PrintHex command", "--input={0}", options.InputFile); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("PrintHex command", "--start={0}", options.StartSector); $"{MainClass.AssemblyCopyright}",
DicConsole.DebugWriteLine("PrintHex command", "--length={0}", options.Length); "",
DicConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", options.LongSectors); $"usage: DiscImageChef {Name} [OPTIONS] imagefile",
DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", options.WidthBytes); "",
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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
if(startSector is null)
{
DicConsole.ErrorWriteLine("Missing starting sector.");
return 1;
}
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", "--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);
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 1;
} }
IMediaImage inputFormat = ImageFormat.Detect(inputFilter); IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -63,20 +122,20 @@ namespace DiscImageChef.Commands
if(inputFormat == null) if(inputFormat == null)
{ {
DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying"); DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying");
return; return 2;
} }
inputFormat.Open(inputFilter); inputFormat.Open(inputFilter);
for(ulong i = 0; i < options.Length; i++) for(ulong i = 0; i < length; i++)
{ {
DicConsole.WriteLine("Sector {0}", options.StartSector + i); DicConsole.WriteLine("Sector {0}", startSector + i);
if(inputFormat.Info.ReadableSectorTags == null) if(inputFormat.Info.ReadableSectorTags == null)
{ {
DicConsole DicConsole
.WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
options.LongSectors = false; longSectors = false;
} }
else else
{ {
@@ -84,18 +143,19 @@ namespace DiscImageChef.Commands
{ {
DicConsole DicConsole
.WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data."); .WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
options.LongSectors = false; longSectors = false;
} }
} }
byte[] sector = options.LongSectors byte[] sector = longSectors
? inputFormat.ReadSectorLong(options.StartSector + i) ? inputFormat.ReadSectorLong(startSector.Value + i)
: inputFormat.ReadSector(options.StartSector + i); : inputFormat.ReadSector(startSector.Value + i);
DiscImageChef.PrintHex.PrintHexArray(sector, options.WidthBytes); PrintHex.PrintHexArray(sector, widthBytes);
} }
Core.Statistics.AddCommand("print-hex"); Statistics.AddCommand("print-hex");
return 0;
} }
} }
} }

View File

@@ -30,24 +30,61 @@
// Copyright © 2011-2019 Natalia Portillo // Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
using System.Collections.Generic;
using System.Linq; using System.Linq;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Database; using DiscImageChef.Database;
using DiscImageChef.Database.Models; using DiscImageChef.Database.Models;
using Mono.Options;
using Command = Mono.Options.Command;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Statistics class StatisticsCommand : Command
{ {
internal static void ShowStats() bool showHelp;
public StatisticsCommand() : base("stats", "Shows statistics.")
{ {
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 0;
}
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 1;
}
DicContext ctx = DicContext.Create(Settings.Settings.LocalDbPath); DicContext ctx = DicContext.Create(Settings.Settings.LocalDbPath);
if(!ctx.Commands.Any() && !ctx.Filesystems.Any() && !ctx.Filters.Any() && !ctx.MediaFormats.Any() && if(!ctx.Commands.Any() && !ctx.Filesystems.Any() && !ctx.Filters.Any() && !ctx.MediaFormats.Any() &&
!ctx.Medias.Any() && !ctx.Partitions.Any() && !ctx.SeenDevices.Any()) !ctx.Medias.Any() && !ctx.Partitions.Any() && !ctx.SeenDevices.Any())
{ {
DicConsole.WriteLine("There are no statistics."); DicConsole.WriteLine("There are no statistics.");
return; return 1;
} }
bool thereAreStats = false; bool thereAreStats = false;
@@ -198,6 +235,7 @@ namespace DiscImageChef.Commands
} }
if(!thereAreStats) DicConsole.WriteLine("There are no statistics."); if(!thereAreStats) DicConsole.WriteLine("There are no statistics.");
return 0;
} }
} }
} }

View File

@@ -30,25 +30,67 @@
// Copyright © 2011-2019 Natalia Portillo // Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Update class UpdateCommand : Command
{ {
internal static void DoUpdate(UpdateOptions options) readonly bool masterDbUpdate;
bool showHelp;
public UpdateCommand(bool masterDbUpdate) : base("update", "Updates the database.")
{ {
DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", options.Debug); this.masterDbUpdate = masterDbUpdate;
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.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)
{
if(masterDbUpdate) return 0;
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
DicConsole.DebugWriteLine("Update command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Update command", "--verbose={0}", MainClass.Verbose);
DoUpdate(false); DoUpdate(false);
return 0;
} }
internal static void DoUpdate(bool create) internal static void DoUpdate(bool create)
{ {
Remote.UpdateMasterDatabase(create); Remote.UpdateMasterDatabase(create);
Core.Statistics.AddCommand("update"); Statistics.AddCommand("update");
} }
} }
} }

View File

@@ -37,26 +37,74 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs; using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core; using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
static class Verify class VerifyCommand : Command
{ {
internal static void DoVerify(VerifyOptions options) string inputFile;
bool showHelp;
bool verifyDisc = true;
bool verifySectors = true;
public VerifyCommand() : base("verify", "Verifies a disc image integrity, and if supported, sector integrity.")
{ {
DicConsole.DebugWriteLine("Verify command", "--debug={0}", options.Debug); Options = new OptionSet
DicConsole.DebugWriteLine("Verify command", "--verbose={0}", options.Verbose); {
DicConsole.DebugWriteLine("Verify command", "--input={0}", options.InputFile); $"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
DicConsole.DebugWriteLine("Verify command", "--verify-disc={0}", options.VerifyDisc); $"{MainClass.AssemblyCopyright}",
DicConsole.DebugWriteLine("Verify command", "--verify-sectors={0}", options.VerifySectors); "",
$"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}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
List<string> extra = Options.Parse(arguments);
if(showHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
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 1;
}
if(extra.Count == 0)
{
DicConsole.ErrorWriteLine("Missing input image.");
return 1;
}
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", "--verify-sectors={0}", verifySectors);
FiltersList filtersList = new FiltersList(); FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile); IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null) if(inputFilter == null)
{ {
DicConsole.ErrorWriteLine("Cannot open specified file."); DicConsole.ErrorWriteLine("Cannot open specified file.");
return; return 1;
} }
IMediaImage inputFormat = ImageFormat.Detect(inputFilter); IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -64,13 +112,13 @@ namespace DiscImageChef.Commands
if(inputFormat == null) if(inputFormat == null)
{ {
DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying"); DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying");
return; return 2;
} }
inputFormat.Open(inputFilter); inputFormat.Open(inputFilter);
Core.Statistics.AddMediaFormat(inputFormat.Format); Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name); Statistics.AddFilter(inputFilter.Name);
bool? correctDisc = null; bool? correctDisc = null;
long totalSectors = 0; long totalSectors = 0;
@@ -78,7 +126,7 @@ namespace DiscImageChef.Commands
long correctSectors = 0; long correctSectors = 0;
long unknownSectors = 0; long unknownSectors = 0;
if(options.VerifyDisc) if(verifyDisc)
{ {
DateTime startCheck = DateTime.UtcNow; DateTime startCheck = DateTime.UtcNow;
bool? discCheckStatus = inputFormat.VerifyMediaImage(); bool? discCheckStatus = inputFormat.VerifyMediaImage();
@@ -103,7 +151,7 @@ namespace DiscImageChef.Commands
DicConsole.VerboseWriteLine("Checking disc image checksums took {0} seconds", checkTime.TotalSeconds); DicConsole.VerboseWriteLine("Checking disc image checksums took {0} seconds", checkTime.TotalSeconds);
} }
if(options.VerifySectors) if(verifySectors)
{ {
bool formatHasTracks; bool formatHasTracks;
try try
@@ -215,7 +263,7 @@ namespace DiscImageChef.Commands
DicConsole.VerboseWriteLine("Checking sector checksums took {0} seconds", checkTime.TotalSeconds); DicConsole.VerboseWriteLine("Checking sector checksums took {0} seconds", checkTime.TotalSeconds);
if(options.Verbose) if(MainClass.Verbose)
{ {
DicConsole.VerboseWriteLine("LBAs with error:"); DicConsole.VerboseWriteLine("LBAs with error:");
if(failingLbas.Count == (int)inputFormat.Info.Sectors) if(failingLbas.Count == (int)inputFormat.Info.Sectors)
@@ -243,7 +291,8 @@ namespace DiscImageChef.Commands
correctSectors = totalSectors - errorSectors - unknownSectors; correctSectors = totalSectors - errorSectors - unknownSectors;
} }
Core.Statistics.AddCommand("verify"); Statistics.AddCommand("verify");
return 0;
} }
} }
} }

View File

@@ -53,11 +53,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Commands\ConvertImage.cs" /> <Compile Include="Commands\ConvertImage.cs" />
<Compile Include="Commands\Gui.cs" />
<Compile Include="Commands\ImageInfo.cs" /> <Compile Include="Commands\ImageInfo.cs" />
<Compile Include="Commands\ListOptions.cs" /> <Compile Include="Commands\ListOptions.cs" />
<Compile Include="Commands\Update.cs" /> <Compile Include="Commands\Update.cs" />
<Compile Include="Main.cs" /> <Compile Include="Main.cs" />
<Compile Include="Options.cs" />
<Compile Include="Commands\Formats.cs" /> <Compile Include="Commands\Formats.cs" />
<Compile Include="Commands\Analyze.cs" /> <Compile Include="Commands\Analyze.cs" />
<Compile Include="Commands\Compare.cs" /> <Compile Include="Commands\Compare.cs" />
@@ -262,11 +262,12 @@
<Content Include="..\.github\PULL_REQUEST_TEMPLATE.md" /> <Content Include="..\.github\PULL_REQUEST_TEMPLATE.md" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.3.0" /> <PackageReference Include="Eto.Forms" Version="2.4.1" />
<PackageReference Include="Eto.Platform.Gtk" Version="2.4.1" /> <PackageReference Include="Eto.Platform.Gtk" Version="2.4.1" />
<PackageReference Include="Eto.Platform.Mac64" Version="2.4.1" /> <PackageReference Include="Eto.Platform.Mac64" Version="2.4.1" />
<PackageReference Include="Eto.Platform.Wpf" Version="2.4.1" /> <PackageReference Include="Eto.Platform.Wpf" Version="2.4.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.0" />
<PackageReference Include="Mono.Options" Version="5.3.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.2.5" /> <PackageReference Include="Unclassified.NetRevisionTask" Version="0.2.5" />

View File

@@ -34,24 +34,35 @@ using System;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommandLine;
using DiscImageChef.Commands; using DiscImageChef.Commands;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Database; using DiscImageChef.Database;
using DiscImageChef.Gui.Forms;
using DiscImageChef.Settings; using DiscImageChef.Settings;
using Eto;
using Eto.Forms;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Statistics = DiscImageChef.Core.Statistics; using Mono.Options;
namespace DiscImageChef namespace DiscImageChef
{ {
class MainClass class MainClass
{ {
internal static bool Verbose;
internal static bool Debug;
internal static string AssemblyCopyright;
internal static string AssemblyTitle;
internal static AssemblyInformationalVersionAttribute AssemblyVersion;
[STAThread] [STAThread]
public static void Main(string[] args) public static int Main(string[] args)
{ {
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.WriteLineEvent += System.Console.WriteLine;
DicConsole.WriteEvent += System.Console.Write; DicConsole.WriteEvent += System.Console.Write;
DicConsole.ErrorWriteLineEvent += System.Console.Error.WriteLine; DicConsole.ErrorWriteLineEvent += System.Console.Error.WriteLine;
@@ -66,7 +77,7 @@ namespace DiscImageChef
if(!File.Exists(Settings.Settings.MasterDbPath)) if(!File.Exists(Settings.Settings.MasterDbPath))
{ {
masterDbUpdate = true; masterDbUpdate = true;
Update.DoUpdate(masterDbUpdate); UpdateCommand.DoUpdate(masterDbUpdate);
} }
DicContext mctx = DicContext.Create(Settings.Settings.MasterDbPath); DicContext mctx = DicContext.Create(Settings.Settings.MasterDbPath);
@@ -74,193 +85,63 @@ namespace DiscImageChef
mctx.SaveChanges(); mctx.SaveChanges();
if((args.Length < 1 || args[0].ToLowerInvariant() != "gui") && if((args.Length < 1 || args[0].ToLowerInvariant() != "gui") &&
Settings.Settings.Current.GdprCompliance < DicSettings.GdprLevel) Configure.DoConfigure(true); Settings.Settings.Current.GdprCompliance < DicSettings.GdprLevel)
new ConfigureCommand(true).Invoke(args);
Statistics.LoadStats(); Statistics.LoadStats();
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.ShareStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.ShareStats)
Task.Run(() => { Statistics.SubmitStats(); }); Task.Run(() => { Statistics.SubmitStats(); });
Parser.Default.ParseArguments(args, typeof(AnalyzeOptions), typeof(BenchmarkOptions), CommandSet commands = new CommandSet("DiscImageChef")
typeof(ChecksumOptions), typeof(CompareOptions), typeof(ConfigureOptions),
typeof(ConvertImageOptions), typeof(CreateSidecarOptions),
typeof(DecodeOptions), typeof(DeviceInfoOptions), typeof(DeviceReportOptions),
typeof(DumpMediaOptions), typeof(EntropyOptions), typeof(ExtractFilesOptions),
typeof(FormatsOptions), typeof(ImageInfoOptions), typeof(ListDevicesOptions),
typeof(ListEncodingsOptions), typeof(ListOptionsOptions), typeof(LsOptions),
typeof(MediaInfoOptions), typeof(MediaScanOptions), typeof(PrintHexOptions),
typeof(StatsOptions), typeof(VerifyOptions), typeof(GuiOptions),
typeof(UpdateOptions)).WithParsed<AnalyzeOptions>(opts =>
{ {
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; $"{AssemblyTitle} {AssemblyVersion?.InformationalVersion}",
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; $"{AssemblyCopyright}",
PrintCopyright(); "",
Analyze.DoAnalyze(opts); "usage: DiscImageChef COMMAND [OPTIONS]",
}).WithParsed<CompareOptions>(opts => "",
{ "Global options:",
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; {"verbose|v", "Shows verbose output.", b => Verbose = b != null},
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; {"debug|d", "Shows debug output from plugins.", b => Debug = b != null},
PrintCopyright(); "",
Compare.DoCompare(opts); "Available commands:",
}).WithParsed<ChecksumOptions>(opts => new AnalyzeCommand(),
{ new BenchmarkCommand(),
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; new ChecksumCommand(),
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; new CompareCommand(),
PrintCopyright(); new ConfigureCommand(false),
Checksum.DoChecksum(opts); new ConvertImageCommand(),
}).WithParsed<EntropyOptions>(opts => new CreateSidecarCommand(),
{ new DecodeCommand(),
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; new DeviceInfoCommand(),
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; new DeviceReportCommand(),
PrintCopyright(); new DumpMediaCommand(),
Entropy.DoEntropy(opts); new EntropyCommand(),
}).WithParsed<VerifyOptions>(opts => new ExtractFilesCommand(),
{ new FormatsCommand(),
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; new GuiCommand(),
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; new ImageInfoCommand(),
PrintCopyright(); new ListDevicesCommand(),
Verify.DoVerify(opts); new ListEncodingsCommand(),
}).WithParsed<PrintHexOptions>(opts => new ListOptionsCommand(),
{ new LsCommand(),
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; new MediaInfoCommand(),
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; new MediaScanCommand(),
PrintCopyright(); new PrintHexCommand(),
Commands.PrintHex.DoPrintHex(opts); new StatisticsCommand(),
}).WithParsed<DecodeOptions>(opts => new UpdateCommand(masterDbUpdate),
{ new VerifyCommand()
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; };
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Decode.DoDecode(opts);
}).WithParsed<DeviceInfoOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
DeviceInfo.DoDeviceInfo(opts);
}).WithParsed<MediaInfoOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
MediaInfo.DoMediaInfo(opts);
}).WithParsed<MediaScanOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
MediaScan.DoMediaScan(opts);
}).WithParsed<FormatsOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Formats.ListFormats(opts);
}).WithParsed<BenchmarkOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Benchmark.DoBenchmark(opts);
}).WithParsed<CreateSidecarOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
CreateSidecar.DoSidecar(opts);
}).WithParsed<DumpMediaOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
DumpMedia.DoDumpMedia(opts);
}).WithParsed<DeviceReportOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
DeviceReport.DoDeviceReport(opts);
}).WithParsed<LsOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Ls.DoLs(opts);
}).WithParsed<ExtractFilesOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
ExtractFiles.DoExtractFiles(opts);
}).WithParsed<ListDevicesOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
ListDevices.DoListDevices(opts);
}).WithParsed<ListEncodingsOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
ListEncodings.DoList();
}).WithParsed<ListOptionsOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
ListOptions.DoList();
}).WithParsed<ConvertImageOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
ConvertImage.DoConvert(opts);
}).WithParsed<ImageInfoOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
ImageInfo.GetImageInfo(opts);
}).WithParsed<ConfigureOptions>(opts =>
{
PrintCopyright();
Configure.DoConfigure(false);
}).WithParsed<StatsOptions>(opts =>
{
PrintCopyright();
Commands.Statistics.ShowStats();
}).WithParsed<GuiOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
new Application(Platform.Detect).Run(new frmMain(opts.Debug, opts.Verbose)); int ret = commands.Run(args);
}).WithParsed<UpdateOptions>(opts =>
{
if(!masterDbUpdate)
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
Update.DoUpdate(opts);
}
}).WithNotParsed(errs => Environment.Exit(1));
Statistics.SaveStats(); Statistics.SaveStats();
return ret;
} }
static void PrintCopyright() internal static void PrintCopyright()
{ {
object[] attributes = DicConsole.WriteLine("{0} {1}", AssemblyTitle, AssemblyVersion?.InformationalVersion);
typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); DicConsole.WriteLine("{0}", AssemblyCopyright);
string assemblyTitle = ((AssemblyTitleAttribute)attributes[0]).Title;
attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
AssemblyInformationalVersionAttribute assemblyVersion =
Attribute.GetCustomAttribute(typeof(MainClass).Assembly, typeof(AssemblyInformationalVersionAttribute))
as AssemblyInformationalVersionAttribute;
string assemblyCopyright = ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
DicConsole.WriteLine("{0} {1}", assemblyTitle, assemblyVersion?.InformationalVersion);
DicConsole.WriteLine("{0}", assemblyCopyright);
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
} }

View File

@@ -1,465 +0,0 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : Options.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Main program loop.
//
// --[ Description ] ----------------------------------------------------------
//
// Defines verbs and options.
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General public License for more details.
//
// You should have received a copy of the GNU General public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using CommandLine;
// ReSharper disable MemberCanBeInternal
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace DiscImageChef
{
public abstract class CommonOptions
{
[Option('v', "verbose", Default = false, HelpText = "Shows verbose output")]
public bool Verbose { get; set; }
[Option('d', "debug", Default = false, HelpText = "Shows debug output from plugins")]
public bool Debug { get; set; }
}
[Verb("analyze", HelpText = "Analyzes a disc image and searches for partitions and/or filesystems.")]
public class AnalyzeOptions : CommonOptions
{
[Option('p', "partitions", Default = true, HelpText = "Searches and interprets partitions.")]
public bool SearchForPartitions { get; set; }
[Option('f', "filesystems", Default = true, HelpText = "Searches and interprets partitions.")]
public bool SearchForFilesystems { get; set; }
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
[Option('e', "encoding", Default = null, HelpText = "Name of character encoding to use.")]
public string EncodingName { get; set; }
}
[Verb("compare", HelpText = "Compares two disc images.")]
public class CompareOptions : CommonOptions
{
[Option("input1", Required = true, HelpText = "First disc image.")]
public string InputFile1 { get; set; }
[Option("input2", Required = true, HelpText = "Second disc image.")]
public string InputFile2 { get; set; }
}
[Verb("checksum", HelpText = "Checksums an image.")]
public class ChecksumOptions : CommonOptions
{
[Option('t', "separated-tracks", Default = true, HelpText = "Checksums each track separately.")]
public bool SeparatedTracks { get; set; }
[Option('w', "whole-disc", Default = true, HelpText = "Checksums the whole disc.")]
public bool WholeDisc { get; set; }
[Option('a', "adler32", Default = true, HelpText = "Calculates Adler-32.")]
public bool DoAdler32 { get; set; }
[Option("crc16", Default = true, HelpText = "Calculates CRC16.")]
public bool DoCrc16 { get; set; }
[Option('c', "crc32", Default = true, HelpText = "Calculates CRC32.")]
public bool DoCrc32 { get; set; }
[Option("crc64", Default = false, HelpText = "Calculates CRC64 (ECMA).")]
public bool DoCrc64 { get; set; }
[Option("fletcher16", Default = false, HelpText = "Calculates Fletcher-16.")]
public bool DoFletcher16 { get; set; }
[Option("fletcher32", Default = false, HelpText = "Calculates Fletcher-32.")]
public bool DoFletcher32 { get; set; }
[Option('m', "md5", Default = true, HelpText = "Calculates MD5.")]
public bool DoMd5 { get; set; }
[Option("ripemd160", Default = false, HelpText = "Calculates RIPEMD160.")]
public bool DoRipemd160 { get; set; }
[Option('s', "sha1", Default = true, HelpText = "Calculates SHA1.")]
public bool DoSha1 { get; set; }
[Option("sha256", Default = false, HelpText = "Calculates SHA256.")]
public bool DoSha256 { get; set; }
[Option("sha384", Default = false, HelpText = "Calculates SHA384.")]
public bool DoSha384 { get; set; }
[Option("sha512", Default = false, HelpText = "Calculates SHA512.")]
public bool DoSha512 { get; set; }
[Option('f', "spamsum", Default = true, HelpText = "Calculates SpamSum fuzzy hash.")]
public bool DoSpamSum { get; set; }
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
}
[Verb("entropy", HelpText = "Calculates entropy and/or duplicated sectors of an image.")]
public class EntropyOptions : CommonOptions
{
[Option('p', "duplicated-sectors", Default = true,
HelpText =
"Calculates how many sectors are duplicated (have same exact data in user area).")]
public bool DuplicatedSectors { get; set; }
[Option('t', "separated-tracks", Default = true, HelpText = "Calculates entropy for each track separately.")]
public bool SeparatedTracks { get; set; }
[Option('w', "whole-disc", Default = true, HelpText = "Calculates entropy for the whole disc.")]
public bool WholeDisc { get; set; }
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
}
[Verb("verify", HelpText = "Verifies a disc image integrity, and if supported, sector integrity.")]
public class VerifyOptions : CommonOptions
{
[Option('w', "verify-disc", Default = true, HelpText = "Verify disc image if supported.")]
public bool VerifyDisc { get; set; }
[Option('s', "verify-sectors", Default = true, HelpText = "Verify all sectors if supported.")]
public bool VerifySectors { get; set; }
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
}
[Verb("printhex", HelpText = "Prints a sector, in hexadecimal values, to the console.")]
public class PrintHexOptions : CommonOptions
{
[Option('s', "start", Required = true, HelpText = "Start sector.")]
public ulong StartSector { get; set; }
[Option('l', "length", Default = (ulong)1, HelpText = "How many sectors to print.")]
public ulong Length { get; set; }
[Option('r', "long-sectors", Default = false, HelpText = "Print sectors with tags included.")]
public bool LongSectors { get; set; }
[Option('w', "width", Default = (ushort)32, HelpText = "How many bytes to print per line.")]
public ushort WidthBytes { get; set; }
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
}
[Verb("decode", HelpText = "Decodes and pretty prints disk and/or sector tags.")]
public class DecodeOptions : CommonOptions
{
[Option('s', "start", Default = (ulong)0, HelpText = "Start sector.")]
public ulong StartSector { get; set; }
[Option('l', "length", Default = "all", HelpText = "How many sectors to decode, or \"all\".")]
public string Length { get; set; }
[Option('k', "disk-tags", Default = true, HelpText = "Decode disk tags.")]
public bool DiskTags { get; set; }
[Option('t', "sector-tags", Default = true, HelpText = "Decode sector tags.")]
public bool SectorTags { get; set; }
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
}
[Verb("device-info", HelpText = "Gets information about a device.")]
public class DeviceInfoOptions : CommonOptions
{
[Option('i', "device", Required = true, HelpText = "Device path.")]
public string DevicePath { get; set; }
[Option('w', "output-prefix", Required = false, Default = "",
HelpText = "Write binary responses from device with that prefix.")]
public string OutputPrefix { get; set; }
}
[Verb("media-info", HelpText = "Gets information about the media inserted on a device.")]
public class MediaInfoOptions : CommonOptions
{
[Option('i', "device", Required = true, HelpText = "Device path.")]
public string DevicePath { get; set; }
[Option('w', "output-prefix", Required = false, Default = "",
HelpText = "Write binary responses from device with that prefix.")]
public string OutputPrefix { get; set; }
}
[Verb("media-scan", HelpText = "Scans the media inserted on a device.")]
public class MediaScanOptions : CommonOptions
{
[Option('i', "device", Required = true, HelpText = "Device path.")]
public string DevicePath { get; set; }
[Option('m', "mhdd-log", Required = false, Default = "",
HelpText = "Write a log of the scan in the format used by MHDD.")]
public string MhddLogPath { get; set; }
[Option('b', "ibg-log", Required = false, Default = "",
HelpText = "Write a log of the scan in the format used by ImgBurn.")]
public string IbgLogPath { get; set; }
}
[Verb("formats", HelpText = "Lists all supported disc images, partition schemes and file systems.")]
public class FormatsOptions : CommonOptions { }
[Verb("benchmark", HelpText = "Benchmarks hashing and entropy calculation.")]
public class BenchmarkOptions : CommonOptions
{
[Option('b', "block-size", Required = false, Default = 512, HelpText = "Block size.")]
public int BlockSize { get; set; }
[Option('s', "buffer-size", Required = false, Default = 128, HelpText = "Buffer size in mebibytes.")]
public int BufferSize { get; set; }
}
[Verb("create-sidecar", HelpText = "Creates CICM Metadata XML sidecar.")]
public class CreateSidecarOptions : CommonOptions
{
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
[Option('t', "tape", Required = false, Default = false,
HelpText =
"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).")]
public bool Tape { get; set; }
[Option('b', "block-size", Required = false, Default = 512,
HelpText =
"Only used for tapes, indicates block size. Files in the folder whose size is not a multiple of this value will simply be ignored.")]
public int BlockSize { get; set; }
[Option('e', "encoding", Default = null, HelpText = "Name of character encoding to use.")]
public string EncodingName { get; set; }
}
[Verb("dump-media", HelpText = "Dumps the media inserted on a device to a media image.")]
public class DumpMediaOptions : CommonOptions
{
[Option('i', "device", Required = true, HelpText = "Device path.")]
public string DevicePath { get; set; }
// TODO: Disabled temporarily
/* [Option('r', "raw", Default = false,
HelpText = "Dump sectors with tags included. For optical media, dump scrambled sectors")]
public bool Raw { get; set; }*/
[Option('s', "stop-on-error", Default = false, HelpText = "Stop media dump on first error.")]
public bool StopOnError { get; set; }
[Option('f', "force", Default = false, HelpText = "Continue dump whatever happens.")]
public bool Force { get; set; }
[Option('p', "retry-passes", Default = (ushort)5, HelpText = "How many retry passes to do.")]
public ushort RetryPasses { get; set; }
[Option("persistent", Default = false, HelpText = "Try to recover partial or incorrect data.")]
public bool Persistent { get; set; }
[Option('m', "resume", Default = true, HelpText = "Create/use resume mapfile.")]
public bool Resume { get; set; }
[Option("first-pregap", Default = false,
HelpText = "Try to read first track pregap. Only applicable to CD/DDCD/GD.")]
public bool FirstTrackPregap { get; set; }
[Option('e', "encoding", Default = null, HelpText = "Name of character encoding to use.")]
public string EncodingName { get; set; }
[Option('o', "output", Required = true, HelpText = "Output image.")]
public string OutputFile { get; set; }
[Option('t', "format", Default = null,
HelpText =
"Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.")]
public string OutputFormat { get; set; }
[Option('O', "options", Default = null,
HelpText = "Comma separated name=value pairs of options to pass to output image plugin")]
public string Options { get; set; }
[Option('x', "cicm-xml", Default = null, HelpText = "Take metadata from existing CICM XML sidecar.")]
public string CicmXml { get; set; }
[Option('k', "skip", Default = 512, HelpText = "When an unreadable sector is found skip this many sectors.")]
public int Skip { get; set; }
[Option("no-metadata", Default = false, HelpText = "Disables creating CICM XML sidecar.")]
public bool NoMetadata { get; set; }
[Option("no-trim", Default = false, HelpText = "Disables trimming errored from skipped sectors.")]
public bool NoTrim { get; set; }
}
[Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")]
public class DeviceReportOptions : CommonOptions
{
[Option('i', "device", Required = true, HelpText = "Device path.")]
public string DevicePath { get; set; }
}
[Verb("configure", HelpText = "Configures user settings and statistics.")]
public class ConfigureOptions { }
[Verb("stats", HelpText = "Shows statistics.")]
public class StatsOptions { }
[Verb("ls", HelpText = "Lists files in disc image.")]
public class LsOptions : CommonOptions
{
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
[Option('l', "long", Default = false, HelpText = "Uses long format.")]
public bool Long { get; set; }
[Option('e', "encoding", Default = null, HelpText = "Name of character encoding to use.")]
public string EncodingName { get; set; }
[Option('O', "options", Default = null,
HelpText = "Comma separated name=value pairs of options to pass to filesystem plugin")]
public string Options { get; set; }
}
[Verb("extract-files", HelpText = "Extracts all files in disc image.")]
public class ExtractFilesOptions : CommonOptions
{
[Option('i', "input", Required = true, HelpText = "Disc image.")]
public string InputFile { get; set; }
[Option('o', "output", Required = true,
HelpText = "Directory where extracted files will be created. Will abort if it exists.")]
public string OutputDir { get; set; }
[Option('x', "xattrs", Default = false, HelpText = "Extract extended attributes if present.")]
public bool Xattrs { get; set; }
[Option('e', "encoding", Default = null, HelpText = "Name of character encoding to use.")]
public string EncodingName { get; set; }
[Option('O', "options", Default = null,
HelpText = "Comma separated name=value pairs of options to pass to filesystem plugin")]
public string Options { get; set; }
}
[Verb("list-devices", HelpText = "Lists all connected devices.")]
public class ListDevicesOptions : CommonOptions { }
[Verb("list-encodings", HelpText = "Lists all supported text encodings and code pages.")]
public class ListEncodingsOptions : CommonOptions { }
[Verb("list-options", HelpText = "Lists all options supported by read-only filesystems and writable media images.")]
public class ListOptionsOptions : CommonOptions { }
[Verb("convert-image", HelpText = "Converts one image to another format.")]
public class ConvertImageOptions : CommonOptions
{
[Option('i', "input", Required = true, HelpText = "Input image.")]
public string InputFile { get; set; }
[Option('o', "output", Required = true, HelpText = "Output image.")]
public string OutputFile { get; set; }
[Option('p', "format", Default = null,
HelpText =
"Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.")]
public string OutputFormat { get; set; }
[Option('c', "count", Default = 64, HelpText = "How many sectors to convert at once.")]
public int Count { get; set; }
[Option('f', "force", Default = false,
HelpText =
"Continue conversion even if sector or media tags will be lost in the process.")]
public bool Force { get; set; }
[Option("creator", Default = null, HelpText = "Who (person) created the image?")]
public string Creator { get; set; }
[Option("media-title", Default = null, HelpText = "Title of the media represented by the image")]
public string MediaTitle { get; set; }
[Option("comments", Default = null, HelpText = "Image comments")]
public string Comments { get; set; }
[Option("media-manufacturer", Default = null, HelpText = "Manufacturer of the media represented by the image")]
public string MediaManufacturer { get; set; }
[Option("media-model", Default = null, HelpText = "Model of the media represented by the image")]
public string MediaModel { get; set; }
[Option("media-serial", Default = null, HelpText = "Serial number of the media represented by the image")]
public string MediaSerialNumber { get; set; }
[Option("media-barcode", Default = null, HelpText = "Barcode of the media represented by the image")]
public string MediaBarcode { get; set; }
[Option("media-partnumber", Default = null, HelpText = "Part number of the media represented by the image")]
public string MediaPartNumber { get; set; }
[Option("media-sequence", Default = 0, HelpText = "Number in sequence for the media represented by the image")]
public int MediaSequence { get; set; }
[Option("media-lastsequence", Default = 0,
HelpText =
"Last media of the sequence the media represented by the image corresponds to")]
public int LastMediaSequence { get; set; }
[Option("drive-manufacturer", Default = null,
HelpText =
"Manufacturer of the drive used to read the media represented by the image")]
public string DriveManufacturer { get; set; }
[Option("drive-model", Default = null,
HelpText = "Model of the drive used to read the media represented by the image")]
public string DriveModel { get; set; }
[Option("drive-serial", Default = null,
HelpText = "Serial number of the drive used to read the media represented by the image")]
public string DriveSerialNumber { get; set; }
[Option("drive-revision", Default = null,
HelpText =
"Firmware revision of the drive used to read the media represented by the image")]
public string DriveFirmwareRevision { get; set; }
[Option('O', "options", Default = null,
HelpText = "Comma separated name=value pairs of options to pass to output image plugin")]
public string Options { get; set; }
[Option('x', "cicm-xml", Default = null, HelpText = "Take metadata from existing CICM XML sidecar.")]
public string CicmXml { get; set; }
[Option('r', "resume-file", Default = null, HelpText = "Take list of dump hardware from existing resume file.")]
public string ResumeFile { get; set; }
}
[Verb("image-info", HelpText =
"Opens a media image and shows information about the media it represents and metadata.")]
public class ImageInfoOptions : CommonOptions
{
[Option('i', "input", Required = true, HelpText = "Media image.")]
public string InputFile { get; set; }
}
[Verb("gui", HelpText = "Opens the in-progress GUI.")]
public class GuiOptions : CommonOptions { }
[Verb("update", HelpText = "Updates the database.")]
public class UpdateOptions : CommonOptions { }
}