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

View File

@@ -37,41 +37,92 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
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);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("Analyze command", "--filesystems={0}", options.SearchForFilesystems);
DicConsole.DebugWriteLine("Analyze command", "--partitions={0}", options.SearchForPartitions);
DicConsole.DebugWriteLine("Analyze command", "--encoding={0}", options.EncodingName);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
{"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();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 2;
}
Encoding encoding = null;
if(options.EncodingName != null)
if(encodingName != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
}
catch(ArgumentException)
{
DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return;
return 5;
}
PluginBase plugins = GetPluginBase.Instance;
@@ -85,10 +136,10 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
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,
imageFormat.Id);
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("No error given");
return;
return 4;
}
if(options.Verbose)
if(MainClass.Verbose)
{
Core.ImageInfo.PrintImageInfo(imageFormat);
ImageInfo.PrintImageInfo(imageFormat);
DicConsole.WriteLine();
}
Core.Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddMedia(imageFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(imageFormat.Format);
Statistics.AddMedia(imageFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
}
catch(Exception ex)
{
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
DicConsole.DebugWriteLine("Analyze command", "Stack trace: {0}", ex.StackTrace);
return;
return -1;
}
List<string> idPlugins;
IFilesystem plugin;
string information;
if(options.SearchForPartitions)
if(searchForPartitions)
{
List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
Core.Partitions.AddSchemesToStats(partitions);
@@ -132,10 +183,10 @@ namespace DiscImageChef.Commands
if(partitions.Count == 0)
{
DicConsole.DebugWriteLine("Analyze command", "No partitions found");
if(!options.SearchForFilesystems)
if(!searchForFilesystems)
{
DicConsole.WriteLine("No partitions founds, not searching for filesystems");
return;
return -2;
}
checkraw = true;
@@ -158,7 +209,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Partition description:");
DicConsole.WriteLine(partitions[i].Description);
if(!options.SearchForFilesystems) continue;
if(!searchForFilesystems) continue;
DicConsole.WriteLine("Identifying filesystem on partition");
@@ -174,7 +225,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine($"As identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, partitions[i], out information, encoding);
DicConsole.Write(information);
Core.Statistics.AddFilesystem(plugin.XmlFsType.Type);
Statistics.AddFilesystem(plugin.XmlFsType.Type);
}
}
else
@@ -185,7 +236,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine($"Identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, partitions[i], out information, encoding);
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}.");
plugin.GetInformation(imageFormat, wholePart, out information, encoding);
DicConsole.Write(information);
Core.Statistics.AddFilesystem(plugin.XmlFsType.Type);
Statistics.AddFilesystem(plugin.XmlFsType.Type);
}
}
else
@@ -223,7 +274,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine($"Identified by {plugin.Name}.");
plugin.GetInformation(imageFormat, wholePart, out information, encoding);
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);
}
Core.Statistics.AddCommand("analyze");
Statistics.AddCommand("analyze");
return 0;
}
}
}

View File

@@ -33,19 +33,60 @@
using System.Collections.Generic;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
static class Benchmark
class BenchmarkCommand : Command
{
internal static void DoBenchmark(BenchmarkOptions options)
{
Dictionary<string, double> checksumTimes = new Dictionary<string, double>();
Core.Benchmark.InitProgressEvent += Progress.InitProgress;
Core.Benchmark.UpdateProgressEvent += Progress.UpdateProgress;
Core.Benchmark.EndProgressEvent += Progress.EndProgress;
int blockSize = 512;
int bufferSize = 128;
bool showHelp;
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,
results.FillSpeed);
@@ -55,11 +96,8 @@ namespace DiscImageChef.Commands
results.EntropySpeed);
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,
entry.Value.Speed);
}
DicConsole.WriteLine("Took {0} seconds to do all algorithms at the same time, {1:F3} MiB/sec.",
results.TotalTime, results.TotalSpeed);
@@ -70,7 +108,8 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Max memory used is {0} bytes", results.MaxMemory);
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.Console;
using DiscImageChef.Core;
using Mono.Options;
using Schemas;
namespace DiscImageChef.Commands
{
static class Checksum
class ChecksumCommand : Command
{
// How many sectors to read at once
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);
DicConsole.DebugWriteLine("Checksum command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Checksum command", "--separated-tracks={0}", options.SeparatedTracks);
DicConsole.DebugWriteLine("Checksum command", "--whole-disc={0}", options.WholeDisc);
DicConsole.DebugWriteLine("Checksum command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("Checksum command", "--adler32={0}", options.DoAdler32);
DicConsole.DebugWriteLine("Checksum command", "--crc16={0}", options.DoCrc16);
DicConsole.DebugWriteLine("Checksum command", "--crc32={0}", options.DoCrc32);
DicConsole.DebugWriteLine("Checksum command", "--crc64={0}", options.DoCrc64);
DicConsole.DebugWriteLine("Checksum command", "--md5={0}", options.DoMd5);
DicConsole.DebugWriteLine("Checksum command", "--ripemd160={0}", options.DoRipemd160);
DicConsole.DebugWriteLine("Checksum command", "--sha1={0}", options.DoSha1);
DicConsole.DebugWriteLine("Checksum command", "--sha256={0}", options.DoSha256);
DicConsole.DebugWriteLine("Checksum command", "--sha384={0}", options.DoSha384);
DicConsole.DebugWriteLine("Checksum command", "--sha512={0}", options.DoSha512);
DicConsole.DebugWriteLine("Checksum command", "--spamsum={0}", options.DoSpamSum);
DicConsole.DebugWriteLine("Checksum command", "--fletcher16={0}", options.DoFletcher16);
DicConsole.DebugWriteLine("Checksum command", "--fletcher32={0}", options.DoFletcher32);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"adler32|a", "Calculates Adler-32.", b => doAdler32 = b != null},
{"crc16", "Calculates CRC16.", b => doCrc16 = b != null},
{"crc32|c", "Calculates CRC32.", b => doCrc32 = b != null},
{"crc64", "Calculates CRC64 (ECMA).", b => doCrc64 = b != null},
{"fletcher16", "Calculates Fletcher-16.", b => doFletcher16 = b != null},
{"fletcher32", "Calculates Fletcher-32.", b => doFletcher32 = b != null},
{"md5|m", "Calculates MD5.", b => doMd5 = b != null},
{"ripemd160", "Calculates RIPEMD160.", b => doRipemd160 = b != null},
{"separated-tracks|t", "Checksums each track separately.", b => separatedTracks = b != null},
{"sha1|s", "Calculates SHA1.", b => doSha1 = b != null},
{"sha256", "Calculates SHA256.", b => doSha256 = b != null},
{"sha384", "Calculates SHA384.", b => doSha384 = b != null},
{"sha512", "Calculates SHA512.", b => doSha512 = b != null},
{"spamsum|f", "Calculates SpamSum fuzzy hash.", b => doSpamSum = b != null},
{"whole-disc|w", "Checksums the whole disc.", b => wholeDisc = b != null},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
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();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 1;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -81,44 +155,44 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming");
return;
return 2;
}
inputFormat.Open(inputFilter);
Core.Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(inputFormat.Format);
Statistics.AddMedia(inputFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
EnableChecksum enabledChecksums = new EnableChecksum();
if(options.DoAdler32) enabledChecksums |= EnableChecksum.Adler32;
if(options.DoCrc16) enabledChecksums |= EnableChecksum.Crc16;
if(options.DoCrc32) enabledChecksums |= EnableChecksum.Crc32;
if(options.DoCrc64) enabledChecksums |= EnableChecksum.Crc64;
if(options.DoMd5) enabledChecksums |= EnableChecksum.Md5;
if(options.DoRipemd160) enabledChecksums |= EnableChecksum.Ripemd160;
if(options.DoSha1) enabledChecksums |= EnableChecksum.Sha1;
if(options.DoSha256) enabledChecksums |= EnableChecksum.Sha256;
if(options.DoSha384) enabledChecksums |= EnableChecksum.Sha384;
if(options.DoSha512) enabledChecksums |= EnableChecksum.Sha512;
if(options.DoSpamSum) enabledChecksums |= EnableChecksum.SpamSum;
if(options.DoFletcher16) enabledChecksums |= EnableChecksum.Fletcher16;
if(options.DoFletcher32) enabledChecksums |= EnableChecksum.Fletcher32;
if(doAdler32) enabledChecksums |= EnableChecksum.Adler32;
if(doCrc16) enabledChecksums |= EnableChecksum.Crc16;
if(doCrc32) enabledChecksums |= EnableChecksum.Crc32;
if(doCrc64) enabledChecksums |= EnableChecksum.Crc64;
if(doMd5) enabledChecksums |= EnableChecksum.Md5;
if(doRipemd160) enabledChecksums |= EnableChecksum.Ripemd160;
if(doSha1) enabledChecksums |= EnableChecksum.Sha1;
if(doSha256) enabledChecksums |= EnableChecksum.Sha256;
if(doSha384) enabledChecksums |= EnableChecksum.Sha384;
if(doSha512) enabledChecksums |= EnableChecksum.Sha512;
if(doSpamSum) enabledChecksums |= EnableChecksum.SpamSum;
if(doFletcher16) enabledChecksums |= EnableChecksum.Fletcher16;
if(doFletcher32) enabledChecksums |= EnableChecksum.Fletcher32;
Core.Checksum mediaChecksum = null;
Checksum mediaChecksum = null;
if(inputFormat.Info.HasPartitions)
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;
List<Track> inputTracks = inputFormat.Tracks;
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++)
{
DicConsole.Write("\rHashing track-less sector {0}", i);
@@ -133,7 +207,7 @@ namespace DiscImageChef.Commands
currentTrack.TrackSequence, currentTrack.TrackStartSector,
currentTrack.TrackEndSector);
if(options.SeparatedTracks) trackChecksum = new Core.Checksum(enabledChecksums);
if(separatedTracks) trackChecksum = new Checksum(enabledChecksums);
ulong sectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector + 1;
ulong doneSectors = 0;
@@ -160,14 +234,14 @@ namespace DiscImageChef.Commands
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();
if(options.SeparatedTracks)
if(separatedTracks)
if(trackChecksum != null)
foreach(ChecksumType chk in trackChecksum.End())
DicConsole.WriteLine("Track {0}'s {1}: {2}", currentTrack.TrackSequence, chk.type,
@@ -176,7 +250,7 @@ namespace DiscImageChef.Commands
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++)
{
DicConsole.Write("\rHashing track-less sector {0}", i);
@@ -185,19 +259,19 @@ namespace DiscImageChef.Commands
mediaChecksum?.Update(hiddenSector);
}
if(options.WholeDisc)
if(wholeDisc)
if(mediaChecksum != null)
foreach(ChecksumType chk in mediaChecksum.End())
DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value);
}
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
{
mediaChecksum = new Core.Checksum(enabledChecksums);
mediaChecksum = new Checksum(enabledChecksums);
ulong sectors = inputFormat.Info.Sectors;
DicConsole.WriteLine("Sectors {0}", sectors);
@@ -230,7 +304,8 @@ namespace DiscImageChef.Commands
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.Console;
using DiscImageChef.Core;
using Mono.Options;
using ImageInfo = DiscImageChef.CommonTypes.Structs.ImageInfo;
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);
DicConsole.DebugWriteLine("Compare command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Compare command", "--input1={0}", options.InputFile1);
DicConsole.DebugWriteLine("Compare command", "--input2={0}", options.InputFile2);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{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();
IFilter inputFilter1 = filtersList.GetFilter(options.InputFile1);
IFilter inputFilter1 = filtersList.GetFilter(InputFile1);
filtersList = new FiltersList();
IFilter inputFilter2 = filtersList.GetFilter(options.InputFile2);
IFilter inputFilter2 = filtersList.GetFilter(InputFile2);
if(inputFilter1 == null)
{
DicConsole.ErrorWriteLine("Cannot open input file 1");
return;
return 1;
}
if(inputFilter2 == null)
{
DicConsole.ErrorWriteLine("Cannot open input file 2");
return;
return 2;
}
IMediaImage input1Format = ImageFormat.Detect(inputFilter1);
@@ -74,10 +121,10 @@ namespace DiscImageChef.Commands
if(input1Format == null)
{
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,
input1Format.Id);
else DicConsole.WriteLine("Input file 1 format identified by {0}.", input1Format.Name);
@@ -85,10 +132,10 @@ namespace DiscImageChef.Commands
if(input2Format == null)
{
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,
input2Format.Id);
else DicConsole.WriteLine("Input file 2 format identified by {0}.", input2Format.Name);
@@ -96,32 +143,32 @@ namespace DiscImageChef.Commands
input1Format.Open(inputFilter1);
input2Format.Open(inputFilter2);
Core.Statistics.AddMediaFormat(input1Format.Format);
Core.Statistics.AddMediaFormat(input2Format.Format);
Core.Statistics.AddMedia(input1Format.Info.MediaType, false);
Core.Statistics.AddMedia(input2Format.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter1.Name);
Core.Statistics.AddFilter(inputFilter2.Name);
Statistics.AddMediaFormat(input1Format.Format);
Statistics.AddMediaFormat(input2Format.Format);
Statistics.AddMedia(input1Format.Info.MediaType, false);
Statistics.AddMedia(input2Format.Info.MediaType, false);
Statistics.AddFilter(inputFilter1.Name);
Statistics.AddFilter(inputFilter2.Name);
StringBuilder sb = new StringBuilder();
if(options.Verbose)
if(MainClass.Verbose)
{
sb.AppendLine("\tDisc image 1\tDisc image 2");
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();
}
else
{
sb.AppendFormat("Disc image 1: {0}", options.InputFile1).AppendLine();
sb.AppendFormat("Disc image 2: {0}", options.InputFile2).AppendLine();
sb.AppendFormat("Disc image 1: {0}", InputFile1).AppendLine();
sb.AppendFormat("Disc image 2: {0}", InputFile2).AppendLine();
}
bool imagesDiffer = false;
CommonTypes.Structs.ImageInfo image1Info = new CommonTypes.Structs.ImageInfo();
CommonTypes.Structs.ImageInfo image2Info = new CommonTypes.Structs.ImageInfo();
ImageInfo image1Info = new ImageInfo();
ImageInfo image2Info = new ImageInfo();
List<Session> image1Sessions = new List<Session>();
List<Session> image2Sessions = new List<Session>();
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
}
if(options.Verbose)
if(MainClass.Verbose)
{
sb.AppendFormat("Has partitions?\t{0}\t{1}", image1Info.HasPartitions, image2Info.HasPartitions)
.AppendLine();
@@ -272,31 +319,31 @@ namespace DiscImageChef.Commands
if(image1Info.HasPartitions != image2Info.HasPartitions)
{
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)
{
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)
{
imagesDiffer = true;
if(!options.Verbose) sb.AppendLine("Image sectors differ");
if(!MainClass.Verbose) sb.AppendLine("Image sectors differ");
}
if(image1Info.SectorSize != image2Info.SectorSize)
{
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)
{
imagesDiffer = true;
if(!options.Verbose) sb.AppendLine("Disk type differ");
if(!MainClass.Verbose) sb.AppendLine("Disk type differ");
}
ulong leastSectors;
@@ -304,13 +351,13 @@ namespace DiscImageChef.Commands
{
imagesDiffer = true;
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)
{
imagesDiffer = true;
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;
@@ -351,7 +398,8 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine(sb.ToString());
Core.Statistics.AddCommand("compare");
Statistics.AddCommand("compare");
return 0;
}
}
}

View File

@@ -31,15 +31,59 @@
// ****************************************************************************/
using System;
using System.Collections.Generic;
using DiscImageChef.Console;
using DiscImageChef.Settings;
using Mono.Options;
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)
{
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.SaveSettings();
return 0;
}
}
}

View File

@@ -42,107 +42,234 @@ using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
using Schemas;
using ImageInfo = DiscImageChef.CommonTypes.Structs.ImageInfo;
using Version = DiscImageChef.CommonTypes.Interop.Version;
namespace DiscImageChef.Commands
{
public static class ConvertImage
class ConvertImageCommand : Command
{
public static void DoConvert(ConvertImageOptions options)
{
DicConsole.DebugWriteLine("Analyze command", "--debug={0}", options.Debug);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("Analyze command", "--output={0}", options.OutputFile);
DicConsole.DebugWriteLine("Analyze command", "--format={0}", options.OutputFormat);
DicConsole.DebugWriteLine("Analyze command", "--count={0}", options.Count);
DicConsole.DebugWriteLine("Analyze command", "--force={0}", options.Force);
DicConsole.DebugWriteLine("Analyze command", "--creator={0}", options.Creator);
DicConsole.DebugWriteLine("Analyze command", "--media-title={0}", options.MediaTitle);
DicConsole.DebugWriteLine("Analyze command", "--comments={0}", options.Comments);
DicConsole.DebugWriteLine("Analyze command", "--media-manufacturer={0}", options.MediaManufacturer);
DicConsole.DebugWriteLine("Analyze command", "--media-model={0}", options.MediaModel);
DicConsole.DebugWriteLine("Analyze command", "--media-serial={0}", options.MediaSerialNumber);
DicConsole.DebugWriteLine("Analyze command", "--media-barcode={0}", options.MediaBarcode);
DicConsole.DebugWriteLine("Analyze command", "--media-partnumber={0}", options.MediaPartNumber);
DicConsole.DebugWriteLine("Analyze command", "--media-sequence={0}", options.MediaSequence);
DicConsole.DebugWriteLine("Analyze command", "--media-lastsequence={0}", options.LastMediaSequence);
DicConsole.DebugWriteLine("Analyze command", "--drive-manufacturer={0}", options.DriveManufacturer);
DicConsole.DebugWriteLine("Analyze command", "--drive-model={0}", options.DriveModel);
DicConsole.DebugWriteLine("Analyze command", "--drive-serial={0}", options.DriveSerialNumber);
DicConsole.DebugWriteLine("Analyze command", "--drive-revision={0}", options.DriveFirmwareRevision);
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);
string cicmXml;
string comments;
int count = 64;
string creator;
string driveFirmwareRevision;
string driveManufacturer;
string driveModel;
string driveSerialNumber;
bool force;
string inputFile;
int lastMediaSequence;
string mediaBarcode;
string mediaManufacturer;
string mediaModel;
string mediaPartNumber;
int mediaSequence;
string mediaSerialNumber;
string mediaTitle;
string outputFile;
string outputOptions;
string resumeFile;
bool showHelp;
string wantedOutputFormat;
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:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
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");
return;
return 1;
}
Resume resume = null;
CICMMetadataType sidecar = null;
XmlSerializer xs = new XmlSerializer(typeof(CICMMetadataType));
if(options.CicmXml != null)
if(File.Exists(options.CicmXml))
if(cicmXml != null)
if(File.Exists(cicmXml))
try
{
StreamReader sr = new StreamReader(options.CicmXml);
StreamReader sr = new StreamReader(cicmXml);
sidecar = (CICMMetadataType)xs.Deserialize(sr);
sr.Close();
}
catch
{
DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing...");
return;
return 2;
}
else
{
DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing...");
return;
return 3;
}
xs = new XmlSerializer(typeof(Resume));
if(options.ResumeFile != null)
if(File.Exists(options.ResumeFile))
if(resumeFile != null)
if(File.Exists(resumeFile))
try
{
StreamReader sr = new StreamReader(options.ResumeFile);
StreamReader sr = new StreamReader(resumeFile);
resume = (Resume)xs.Deserialize(sr);
sr.Close();
}
catch
{
DicConsole.ErrorWriteLine("Incorrect resume file, not continuing...");
return;
return 4;
}
else
{
DicConsole.ErrorWriteLine("Could not find resume file, not continuing...");
return;
return 5;
}
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
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.");
return;
return 8;
}
PluginBase plugins = GetPluginBase.Instance;
@@ -151,10 +278,10 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
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,
inputFormat.Id);
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("No error given");
return;
return 9;
}
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}.",
inputFormat.Info.MediaType);
Core.Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(inputFormat.Format);
Statistics.AddMedia(inputFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
}
catch(Exception ex)
{
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
DicConsole.DebugWriteLine("Convert-image command", "Stack trace: {0}", ex.StackTrace);
return;
return 10;
}
List<IWritableImage> candidates = new List<IWritableImage>();
// Try extension
if(string.IsNullOrEmpty(options.OutputFormat))
if(string.IsNullOrEmpty(wantedOutputFormat))
candidates.AddRange(plugins.WritableImages.Values.Where(t =>
t.KnownExtensions
.Contains(Path.GetExtension(options
.OutputFile))));
.Contains(Path.GetExtension(outputFile))));
// 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)));
// Try name
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
.InvariantCultureIgnoreCase)));
if(candidates.Count == 0)
{
DicConsole.WriteLine("No plugin supports requested extension.");
return;
return 11;
}
if(candidates.Count > 1)
{
DicConsole.WriteLine("More than one plugin supports requested extension.");
return;
return 12;
}
IWritableImage outputFormat = candidates[0];
if(options.Verbose)
if(MainClass.Verbose)
DicConsole.VerboseWriteLine("Output image format: {0} ({1}).", outputFormat.Name, outputFormat.Id);
else DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name);
if(!outputFormat.SupportedMediaTypes.Contains(inputFormat.Info.MediaType))
{
DicConsole.ErrorWriteLine("Output format does not support media type, cannot continue...");
return;
return 13;
}
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("If you don't care, use force option.");
return;
return 14;
}
bool useLong = inputFormat.Info.ReadableSectorTags.Count != 0;
@@ -243,7 +369,7 @@ namespace DiscImageChef.Commands
{
if(outputFormat.SupportedSectorTags.Contains(sectorTag)) continue;
if(options.Force)
if(force)
{
if(sectorTag != SectorTagType.CdTrackFlags && sectorTag != SectorTagType.CdTrackIsrc &&
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("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,
inputFormat.Info.Sectors, inputFormat.Info.SectorSize))
if(!outputFormat.Create(outputFile, inputFormat.Info.MediaType, parsedOptions, inputFormat.Info.Sectors,
inputFormat.Info.SectorSize))
{
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",
ApplicationVersion = Version.GetVersion(),
Comments = options.Comments ?? inputFormat.Info.Comments,
Creator = options.Creator ?? inputFormat.Info.Creator,
DriveFirmwareRevision = options.DriveFirmwareRevision ?? inputFormat.Info.DriveFirmwareRevision,
DriveManufacturer = options.DriveManufacturer ?? inputFormat.Info.DriveManufacturer,
DriveModel = options.DriveModel ?? inputFormat.Info.DriveModel,
DriveSerialNumber = options.DriveSerialNumber ?? inputFormat.Info.DriveSerialNumber,
LastMediaSequence =
options.LastMediaSequence != 0 ? options.LastMediaSequence : inputFormat.Info.LastMediaSequence,
MediaBarcode = options.MediaBarcode ?? inputFormat.Info.MediaBarcode,
MediaManufacturer = options.MediaManufacturer ?? inputFormat.Info.MediaManufacturer,
MediaModel = options.MediaModel ?? inputFormat.Info.MediaModel,
MediaPartNumber = options.MediaPartNumber ?? inputFormat.Info.MediaPartNumber,
MediaSequence = options.MediaSequence != 0 ? options.MediaSequence : inputFormat.Info.MediaSequence,
MediaSerialNumber = options.MediaSerialNumber ?? inputFormat.Info.MediaSerialNumber,
MediaTitle = options.MediaTitle ?? inputFormat.Info.MediaTitle
Comments = comments ?? inputFormat.Info.Comments,
Creator = creator ?? inputFormat.Info.Creator,
DriveFirmwareRevision = driveFirmwareRevision ?? inputFormat.Info.DriveFirmwareRevision,
DriveManufacturer = driveManufacturer ?? inputFormat.Info.DriveManufacturer,
DriveModel = driveModel ?? inputFormat.Info.DriveModel,
DriveSerialNumber = driveSerialNumber ?? inputFormat.Info.DriveSerialNumber,
LastMediaSequence = lastMediaSequence != 0 ? lastMediaSequence : inputFormat.Info.LastMediaSequence,
MediaBarcode = mediaBarcode ?? inputFormat.Info.MediaBarcode,
MediaManufacturer = mediaManufacturer ?? inputFormat.Info.MediaManufacturer,
MediaModel = mediaModel ?? inputFormat.Info.MediaModel,
MediaPartNumber = mediaPartNumber ?? inputFormat.Info.MediaPartNumber,
MediaSequence = mediaSequence != 0 ? mediaSequence : inputFormat.Info.MediaSequence,
MediaSerialNumber = mediaSerialNumber ?? inputFormat.Info.MediaSerialNumber,
MediaTitle = mediaTitle ?? inputFormat.Info.MediaTitle
};
if(!outputFormat.SetMetadata(metadata))
{
DicConsole.ErrorWrite("Error {0} setting metadata, ", outputFormat.ErrorMessage);
if(!options.Force)
if(!force)
{
DicConsole.ErrorWriteLine("not continuing...");
return;
return 17;
}
DicConsole.ErrorWriteLine("continuing...");
@@ -309,24 +434,24 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Error {0} sending tracks list to output image.",
outputFormat.ErrorMessage);
return;
return 18;
}
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);
byte[] tag = inputFormat.ReadDiskTag(mediaTag);
if(outputFormat.WriteMediaTag(tag, mediaTag)) continue;
if(options.Force)
if(force)
DicConsole.ErrorWriteLine("Error {0} writing media tag, continuing...", outputFormat.ErrorMessage);
else
{
DicConsole.ErrorWriteLine("Error {0} writing media tag, not continuing...",
outputFormat.ErrorMessage);
return;
return 19;
}
}
@@ -348,9 +473,10 @@ namespace DiscImageChef.Commands
byte[] sector;
uint sectorsToDo;
if(inputFormat.Info.Sectors - doneSectors >= (ulong)options.Count)
sectorsToDo = (uint)options.Count;
else sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors);
if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
else
sectorsToDo =
(uint)(inputFormat.Info.Sectors - doneSectors);
DicConsole.Write("\rConverting sectors {0} to {1} ({2:P2} done)", doneSectors,
doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors);
@@ -382,14 +508,14 @@ namespace DiscImageChef.Commands
}
if(!result)
if(options.Force)
if(force)
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...",
outputFormat.ErrorMessage, doneSectors);
else
{
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors);
return;
return 20;
}
doneSectors += sectorsToDo;
@@ -417,7 +543,7 @@ namespace DiscImageChef.Commands
continue;
}
if(options.Force && !outputFormat.SupportedSectorTags.Contains(tag)) continue;
if(force && !outputFormat.SupportedSectorTags.Contains(tag)) continue;
doneSectors = 0;
while(doneSectors < inputFormat.Info.Sectors)
@@ -425,9 +551,10 @@ namespace DiscImageChef.Commands
byte[] sector;
uint sectorsToDo;
if(inputFormat.Info.Sectors - doneSectors >= (ulong)options.Count)
sectorsToDo = (uint)options.Count;
else sectorsToDo = (uint)(inputFormat.Info.Sectors - doneSectors);
if(inputFormat.Info.Sectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
else
sectorsToDo =
(uint)(inputFormat.Info.Sectors - doneSectors);
DicConsole.Write("\rConverting tag {2} for sectors {0} to {1} ({2:P2} done)", doneSectors,
doneSectors + sectorsToDo, doneSectors / (double)inputFormat.Info.Sectors,
@@ -446,14 +573,14 @@ namespace DiscImageChef.Commands
}
if(!result)
if(options.Force)
if(force)
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...",
outputFormat.ErrorMessage, doneSectors);
else
{
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors);
return;
return 21;
}
doneSectors += sectorsToDo;
@@ -476,10 +603,8 @@ namespace DiscImageChef.Commands
byte[] sector;
uint sectorsToDo;
if(trackSectors - doneSectors >= (ulong)options.Count) sectorsToDo = (uint)options.Count;
else
sectorsToDo =
(uint)(trackSectors - doneSectors);
if(trackSectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
else sectorsToDo = (uint)(trackSectors - doneSectors);
DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)",
doneSectors + track.TrackStartSector,
@@ -516,14 +641,14 @@ namespace DiscImageChef.Commands
}
if(!result)
if(options.Force)
if(force)
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, continuing...",
outputFormat.ErrorMessage, doneSectors);
else
{
DicConsole.ErrorWriteLine("Error {0} writing sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors);
return;
return 22;
}
doneSectors += sectorsToDo;
@@ -552,7 +677,7 @@ namespace DiscImageChef.Commands
continue;
}
if(options.Force && !outputFormat.SupportedSectorTags.Contains(tag)) continue;
if(force && !outputFormat.SupportedSectorTags.Contains(tag)) continue;
foreach(Track track in tracks)
{
@@ -570,14 +695,14 @@ namespace DiscImageChef.Commands
sector = inputFormat.ReadSectorTag(track.TrackStartSector, tag);
result = outputFormat.WriteSectorTag(sector, track.TrackStartSector, tag);
if(!result)
if(options.Force)
if(force)
DicConsole.ErrorWriteLine("Error {0} writing tag, continuing...",
outputFormat.ErrorMessage);
else
{
DicConsole.ErrorWriteLine("Error {0} writing tag, not continuing...",
outputFormat.ErrorMessage);
return;
return 23;
}
continue;
@@ -586,7 +711,7 @@ namespace DiscImageChef.Commands
while(doneSectors < trackSectors)
{
uint sectorsToDo;
if(trackSectors - doneSectors >= (ulong)options.Count) sectorsToDo = (uint)options.Count;
if(trackSectors - doneSectors >= (ulong)count) sectorsToDo = (uint)count;
else
sectorsToDo =
(uint)(trackSectors - doneSectors);
@@ -611,14 +736,14 @@ namespace DiscImageChef.Commands
}
if(!result)
if(options.Force)
if(force)
DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, continuing...",
outputFormat.ErrorMessage, doneSectors);
else
{
DicConsole.ErrorWriteLine("Error {0} writing tag for sector {1}, not continuing...",
outputFormat.ErrorMessage, doneSectors);
return;
return 24;
}
doneSectors += sectorsToDo;
@@ -668,7 +793,8 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine();
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.Console;
using DiscImageChef.Core;
using Mono.Options;
using Schemas;
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.UpdateProgressEvent += Progress.UpdateProgress;
Sidecar.EndProgressEvent += Progress.EndProgress;
@@ -58,33 +123,33 @@ namespace DiscImageChef.Commands
Encoding encoding = null;
if(options.EncodingName != null)
if(encodingName != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
}
catch(ArgumentException)
{
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.");
return;
return 2;
}
FiltersList filtersList = new FiltersList();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 3;
}
try
@@ -94,10 +159,10 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
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,
imageFormat.Id);
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("No error given");
return;
return 5;
}
DicConsole.DebugWriteLine("Analyze command", "Correctly opened image file.");
@@ -117,26 +182,26 @@ namespace DiscImageChef.Commands
{
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return;
return 6;
}
Core.Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(imageFormat.Format);
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");
FileStream xmlFs =
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);
XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close();
Core.Statistics.AddCommand("create-sidecar");
Statistics.AddCommand("create-sidecar");
}
catch(Exception ex)
{
@@ -144,37 +209,37 @@ namespace DiscImageChef.Commands
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.");
return;
return 7;
}
string[] contents = Directory.GetFiles(options.InputFile, "*", SearchOption.TopDirectoryOnly);
List<string> files = contents.Where(file => new FileInfo(file).Length % options.BlockSize == 0)
.ToList();
string[] contents = Directory.GetFiles(inputFile, "*", SearchOption.TopDirectoryOnly);
List<string> files = contents.Where(file => new FileInfo(file).Length % blockSize == 0).ToList();
files.Sort(StringComparer.CurrentCultureIgnoreCase);
CICMMetadataType sidecar =
Sidecar.Create(Path.GetFileName(options.InputFile), files, options.BlockSize);
CICMMetadataType sidecar = Sidecar.Create(Path.GetFileName(inputFile), files, blockSize);
DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs =
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);
XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close();
Core.Statistics.AddCommand("create-sidecar");
Statistics.AddCommand("create-sidecar");
}
else DicConsole.ErrorWriteLine("The specified input file cannot be found.");
return 0;
}
}
}

View File

@@ -30,6 +30,7 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Interfaces;
@@ -38,28 +39,80 @@ using DiscImageChef.Core;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.CD;
using DiscImageChef.Decoders.SCSI;
using Mono.Options;
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);
DicConsole.DebugWriteLine("Decode command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Decode command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("Decode command", "--start={0}", options.StartSector);
DicConsole.DebugWriteLine("Decode command", "--length={0}", options.Length);
DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", options.DiskTags);
DicConsole.DebugWriteLine("Decode command", "--sector-tags={0}", options.SectorTags);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"disk-tags|f", "Decode disk tags.", b => diskTags = b != null},
{"length|l=", "How many sectors to decode, or \"all\".", s => length = s},
{"sector-tags|p", "Decode sector tags.", b => sectorTags = b != null},
{"start|s=", "Name of character encoding to use.", (ulong ul) => startSector = ul},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
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();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 1;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -67,15 +120,15 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not decoding");
return;
return 2;
}
inputFormat.Open(inputFilter);
Core.Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(inputFormat.Format);
Statistics.AddMedia(inputFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
if(options.DiskTags)
if(diskTags)
if(inputFormat.Info.ReadableMediaTags.Count == 0)
DicConsole.WriteLine("There are no disk tags in chosen disc image.");
else
@@ -237,16 +290,16 @@ namespace DiscImageChef.Commands
break;
}
if(options.SectorTags)
if(sectorTags)
{
if(options.Length.ToLowerInvariant() == "all") { }
if(length.ToLowerInvariant() == "all") { }
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");
return;
return 3;
}
}
@@ -265,7 +318,8 @@ namespace DiscImageChef.Commands
// 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.SSC;
using DiscImageChef.Devices;
using Mono.Options;
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
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);
DicConsole.DebugWriteLine("Device-Info command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Device-Info command", "--device={0}", options.DevicePath);
DicConsole.DebugWriteLine("Device-Info command", "--output-prefix={0}", options.OutputPrefix);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] devicepath",
"",
Help,
{"output-prefix|w=", "Name of character encoding to use.", s => outputPrefix = s},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' &&
char.IsLetter(options.DevicePath[0]))
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':';
public override int Invoke(IEnumerable<string> arguments)
{
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)
{
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return;
return 1;
}
Core.Statistics.AddDevice(dev);
Statistics.AddDevice(dev);
if(dev.IsUsb)
{
@@ -156,11 +203,11 @@ namespace DiscImageChef.Commands
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)
{
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);
DicConsole.WriteLine(Identify.Prettify(devInfo.AtaIdentify));
@@ -202,7 +249,7 @@ namespace DiscImageChef.Commands
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);
DicConsole.WriteLine(Identify.Prettify(devInfo.AtapiIdentify));
@@ -212,7 +259,7 @@ namespace DiscImageChef.Commands
{
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);
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));
DataFile.WriteTo("Device-Info command", options.OutputPrefix, page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, page.Value);
}
else if(page.Key == 0x80)
{
DicConsole.WriteLine("Unit Serial Number: {0}", EVPD.DecodePage80(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0x81)
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_81(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0x82)
{
DicConsole.WriteLine("ASCII implemented operating definitions: {0}",
EVPD.DecodePage82(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0x83)
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_83(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0x84)
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_84(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0x85)
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_85(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0x86)
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_86(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0x89)
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_89(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xB0)
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_B0(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xB1)
{
DicConsole.WriteLine("Manufacturer-assigned Serial Number: {0}",
EVPD.DecodePageB1(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xB2)
{
DicConsole.WriteLine("TapeAlert Supported Flags Bitmap: 0x{0:X16}",
EVPD.DecodePageB2(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xB3)
{
DicConsole.WriteLine("Automation Device Serial Number: {0}", EVPD.DecodePageB3(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xB4)
{
DicConsole.WriteLine("Data Transfer Device Element Address: 0x{0}",
EVPD.DecodePageB4(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xC0 &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "quantum")
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Quantum(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xC0 &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "seagate")
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Seagate(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xC0 &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "ibm")
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_IBM(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xC1 &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "ibm")
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C1_IBM(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if((page.Key == 0xC0 || page.Key == 0xC1) &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "certance")
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_C1_Certance(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if((page.Key == 0xC2 || page.Key == 0xC3 || page.Key == 0xC4 || page.Key == 0xC5 ||
page.Key == 0xC6) &&
@@ -371,9 +400,8 @@ namespace DiscImageChef.Commands
.ToLowerInvariant().Trim() == "certance")
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if((page.Key == 0xC0 || page.Key == 0xC1 || page.Key == 0xC2 || page.Key == 0xC3 ||
page.Key == 0xC4 || page.Key == 0xC5) && StringHandlers
@@ -382,18 +410,16 @@ namespace DiscImageChef.Commands
.ToLowerInvariant().Trim() == "hp")
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_to_C5_HP(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else if(page.Key == 0xDF &&
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification)
.ToLowerInvariant().Trim() == "certance")
{
DicConsole.WriteLine("{0}", EVPD.PrettifyPage_DF_Certance(page.Value));
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
else
{
@@ -402,18 +428,17 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Device-Info command", "Found undecoded SCSI VPD page 0x{0:X2}",
page.Key);
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
$"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h",
page.Value);
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
}
if(devInfo.ScsiModeSense6 != null)
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_scsi_modesense6.bin",
"SCSI MODE SENSE", devInfo.ScsiModeSense6);
DataFile.WriteTo("Device-Info command", outputPrefix, "_scsi_modesense6.bin", "SCSI MODE SENSE",
devInfo.ScsiModeSense6);
if(devInfo.ScsiModeSense10 != null)
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_scsi_modesense10.bin",
"SCSI MODE SENSE", devInfo.ScsiModeSense10);
DataFile.WriteTo("Device-Info command", outputPrefix, "_scsi_modesense10.bin", "SCSI MODE SENSE",
devInfo.ScsiModeSense10);
if(devInfo.ScsiMode.HasValue)
PrintScsiModePages.Print(devInfo.ScsiMode.Value,
@@ -422,7 +447,7 @@ namespace DiscImageChef.Commands
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);
Features.SeparatedFeatures ftr = Features.Separate(devInfo.MmcConfiguration);
@@ -629,7 +654,7 @@ namespace DiscImageChef.Commands
{
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);
DicConsole.WriteLine("Drive has loaded a total of {0} discs", devInfo.PlextorFeatures.Discs);
@@ -772,7 +797,7 @@ namespace DiscImageChef.Commands
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);
DicConsole.WriteLine("Block limits for device:");
DicConsole.WriteLine(BlockLimits.Prettify(devInfo.BlockLimits));
@@ -780,7 +805,7 @@ namespace DiscImageChef.Commands
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);
if(devInfo.DensitySupportHeader.HasValue)
{
@@ -791,9 +816,8 @@ namespace DiscImageChef.Commands
if(devInfo.MediumDensitySupport != null)
{
DataFile.WriteTo("Device-Info command", options.OutputPrefix,
"_ssc_reportdensitysupport_medium.bin", "SSC REPORT DENSITY SUPPORT (MEDIUM)",
devInfo.MediumDensitySupport);
DataFile.WriteTo("Device-Info command", outputPrefix, "_ssc_reportdensitysupport_medium.bin",
"SSC REPORT DENSITY SUPPORT (MEDIUM)", devInfo.MediumDensitySupport);
if(devInfo.MediaTypeSupportHeader.HasValue)
{
DicConsole.WriteLine("Medium types supported by device:");
@@ -813,32 +837,29 @@ namespace DiscImageChef.Commands
if(devInfo.CID != null)
{
noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_cid.bin", "MMC CID",
devInfo.CID);
DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_cid.bin", "MMC CID", devInfo.CID);
DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyCID(devInfo.CID));
}
if(devInfo.CSD != null)
{
noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_csd.bin", "MMC CSD",
devInfo.CSD);
DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_csd.bin", "MMC CSD", devInfo.CSD);
DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyCSD(devInfo.CSD));
}
if(devInfo.OCR != null)
{
noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_ocr.bin", "MMC OCR",
devInfo.OCR);
DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_ocr.bin", "MMC OCR", devInfo.OCR);
DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyOCR(devInfo.OCR));
}
if(devInfo.ExtendedCSD != null)
{
noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_mmc_ecsd.bin",
"MMC Extended CSD", devInfo.ExtendedCSD);
DataFile.WriteTo("Device-Info command", outputPrefix, "_mmc_ecsd.bin", "MMC Extended CSD",
devInfo.ExtendedCSD);
DicConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyExtendedCSD(devInfo.ExtendedCSD));
}
@@ -852,32 +873,32 @@ namespace DiscImageChef.Commands
if(devInfo.CID != null)
{
noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_sd_cid.bin",
"SecureDigital CID", devInfo.CID);
DataFile.WriteTo("Device-Info command", outputPrefix, "_sd_cid.bin", "SecureDigital CID",
devInfo.CID);
DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyCID(devInfo.CID));
}
if(devInfo.CSD != null)
{
noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_sd_csd.bin",
"SecureDigital CSD", devInfo.CSD);
DataFile.WriteTo("Device-Info command", outputPrefix, "_sd_csd.bin", "SecureDigital CSD",
devInfo.CSD);
DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyCSD(devInfo.CSD));
}
if(devInfo.OCR != null)
{
noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_sd_ocr.bin",
"SecureDigital OCR", devInfo.OCR);
DataFile.WriteTo("Device-Info command", outputPrefix, "_sd_ocr.bin", "SecureDigital OCR",
devInfo.OCR);
DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifyOCR(devInfo.OCR));
}
if(devInfo.SCR != null)
{
noInfo = false;
DataFile.WriteTo("Device-Info command", options.OutputPrefix, "_sd_scr.bin",
"SecureDigital SCR", devInfo.SCR);
DataFile.WriteTo("Device-Info command", outputPrefix, "_sd_scr.bin", "SecureDigital SCR",
devInfo.SCR);
DicConsole.WriteLine("{0}", Decoders.SecureDigital.Decoders.PrettifySCR(devInfo.SCR));
}
@@ -886,9 +907,11 @@ namespace DiscImageChef.Commands
break;
}
Core.Statistics.AddCommand("device-info");
Statistics.AddCommand("device-info");
dev.Close();
return 0;
}
}
}

View File

@@ -43,40 +43,87 @@ using DiscImageChef.Database;
using DiscImageChef.Database.Models;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.SCSI;
using Mono.Options;
using Newtonsoft.Json;
using Command = Mono.Options.Command;
using Device = DiscImageChef.Devices.Device;
using DeviceReport = DiscImageChef.Core.Devices.Report.DeviceReport;
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);
DicConsole.DebugWriteLine("Device-Report command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Device-Report command", "--device={0}", options.DevicePath);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} devicepath",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
public override int Invoke(IEnumerable<string> arguments)
{
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)
{
DicConsole
.ErrorWriteLine("Because of the commands sent to a device, device report must be run with administrative privileges.");
DicConsole.ErrorWriteLine("Not continuing.");
return;
return 1;
}
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' &&
char.IsLetter(options.DevicePath[0]))
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':';
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
Device dev = new Device(options.DevicePath);
Device dev = new Device(devicePath);
if(dev.Error)
{
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return;
return 2;
}
Core.Statistics.AddDevice(dev);
Statistics.AddDevice(dev);
DeviceReportV2 report = new DeviceReportV2
{
@@ -94,7 +141,7 @@ namespace DiscImageChef.Commands
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;
@@ -248,7 +295,7 @@ namespace DiscImageChef.Commands
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};
@@ -448,7 +495,7 @@ namespace DiscImageChef.Commands
tryPioneer |= dev.Manufacturer.ToLowerInvariant() == "pioneer";
tryNec |= dev.Manufacturer.ToLowerInvariant() == "nec";
if(options.Debug)
if(MainClass.Debug)
{
if(!tryPlextor)
{
@@ -614,7 +661,7 @@ namespace DiscImageChef.Commands
dev.Timeout, out _);
if(!sense)
{
if(options.Debug) mediaTest.ReadLong10Data = buffer;
if(MainClass.Debug) mediaTest.ReadLong10Data = buffer;
mediaTest.LongBlockSize = i;
break;
@@ -627,7 +674,7 @@ namespace DiscImageChef.Commands
}
}
if(options.Debug && mediaTest.SupportsReadLong == true &&
if(MainClass.Debug && mediaTest.SupportsReadLong == true &&
mediaTest.LongBlockSize != mediaTest.BlockSize)
{
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
@@ -844,7 +891,7 @@ namespace DiscImageChef.Commands
}
}
if(options.Debug && mediaTest.SupportsReadLong == true &&
if(MainClass.Debug && mediaTest.SupportsReadLong == true &&
mediaTest.LongBlockSize != mediaTest.BlockSize)
{
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
@@ -889,7 +936,8 @@ namespace DiscImageChef.Commands
dev.Timeout, out _);
if(!sense)
{
if(options.Debug) report.SCSI.ReadCapabilities.ReadLong10Data = buffer;
if(MainClass.Debug)
report.SCSI.ReadCapabilities.ReadLong10Data = buffer;
report.SCSI.ReadCapabilities.LongBlockSize = i;
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.BlockSize)
{
@@ -931,7 +979,7 @@ namespace DiscImageChef.Commands
jsonSw.Close();
jsonFs.Close();
Core.Statistics.AddCommand("device-report");
Statistics.AddCommand("device-report");
using(DicContext ctx = DicContext.Create(Settings.Settings.LocalDbPath))
{
@@ -941,6 +989,7 @@ namespace DiscImageChef.Commands
// TODO:
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.Logging;
using DiscImageChef.Devices;
using Mono.Options;
using Schemas;
using Ata = DiscImageChef.Core.Devices.Dumping.Ata;
using Scsi = DiscImageChef.Core.Devices.Dumping.Scsi;
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
Sidecar.InitProgressEvent += Progress.InitProgress;
Sidecar.UpdateProgressEvent += Progress.UpdateProgress;
@@ -64,65 +159,64 @@ namespace DiscImageChef.Commands
Sidecar.EndProgressEvent2 += Progress.EndProgress2;
Sidecar.UpdateStatusEvent += Progress.UpdateStatus;
DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", options.Debug);
DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", options.DevicePath);
DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", cicmXml);
DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", MainClass.Debug);
DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", devicePath);
DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", encodingName);
DicConsole.DebugWriteLine("Dump-Media command", "--first-pregap={0}", firstTrackPregap);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", force);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", force);
DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", 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
//DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", options.Raw);
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", options.StopOnError);
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force);
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", options.RetryPasses);
DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", options.Persistent);
DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", options.Resume);
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);
//DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw);
DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", doResume);
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", retryPasses);
DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", skip);
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", stopOnError);
DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose);
Dictionary<string, string> parsedOptions = Options.Parse(options.Options);
Dictionary<string, string> parsedOptions = Core.Options.Parse(outputOptions);
DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
DicConsole.DebugWriteLine("Dump-Media command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
Encoding encoding = null;
if(options.EncodingName != null)
if(encodingName != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
}
catch(ArgumentException)
{
DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return;
return 1;
}
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' &&
char.IsLetter(options.DevicePath[0]))
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':';
if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
Device dev = new Device(options.DevicePath);
Device dev = new Device(devicePath);
if(dev.Error)
{
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),
Path.GetFileNameWithoutExtension(options.OutputFile));
string outputPrefix = Path.Combine(Path.GetDirectoryName(outputFile),
Path.GetFileNameWithoutExtension(outputFile));
Resume resume = null;
XmlSerializer xs = new XmlSerializer(typeof(Resume));
if(File.Exists(outputPrefix + ".resume.xml") && options.Resume)
if(File.Exists(outputPrefix + ".resume.xml") && doResume)
try
{
StreamReader sr = new StreamReader(outputPrefix + ".resume.xml");
@@ -132,71 +226,70 @@ namespace DiscImageChef.Commands
catch
{
DicConsole.ErrorWriteLine("Incorrect resume file, not continuing...");
return;
return 3;
}
if(resume != null && resume.NextBlock > resume.LastBlock && resume.BadBlocks.Count == 0)
{
DicConsole.WriteLine("Media already dumped correctly, not continuing...");
return;
return 4;
}
CICMMetadataType sidecar = null;
XmlSerializer sidecarXs = new XmlSerializer(typeof(CICMMetadataType));
if(options.CicmXml != null)
if(File.Exists(options.CicmXml))
if(cicmXml != null)
if(File.Exists(cicmXml))
try
{
StreamReader sr = new StreamReader(options.CicmXml);
StreamReader sr = new StreamReader(cicmXml);
sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
sr.Close();
}
catch
{
DicConsole.ErrorWriteLine("Incorrect metadata sidecar file, not continuing...");
return;
return 5;
}
else
{
DicConsole.ErrorWriteLine("Could not find metadata sidecar, not continuing...");
return;
return 6;
}
PluginBase plugins = GetPluginBase.Instance;
List<IWritableImage> candidates = new List<IWritableImage>();
// Try extension
if(string.IsNullOrEmpty(options.OutputFormat))
if(string.IsNullOrEmpty(wanteOutputFormat))
candidates.AddRange(plugins.WritableImages.Values.Where(t =>
t.KnownExtensions
.Contains(Path.GetExtension(options
.OutputFile))));
.Contains(Path.GetExtension(outputFile))));
// 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)));
// Try name
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
.InvariantCultureIgnoreCase)));
if(candidates.Count == 0)
{
DicConsole.WriteLine("No plugin supports requested extension.");
return;
return 7;
}
if(candidates.Count > 1)
{
DicConsole.WriteLine("More than one plugin supports requested extension.");
return;
return 8;
}
IWritableImage outputFormat = candidates[0];
DumpLog dumpLog = new DumpLog(outputPrefix + ".log", dev);
if(options.Verbose)
if(MainClass.Verbose)
{
dumpLog.WriteLine("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 &&
(dev.UsbProductId == 0x01C8 || dev.UsbProductId == 0x01C9 || dev.UsbProductId == 0x02D2))
PlayStationPortable.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding,
outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
options.NoMetadata, options.NoTrim);
PlayStationPortable.Dump(dev, devicePath, outputFormat, retryPasses, force, persistent, stopOnError,
ref resume, ref dumpLog, encoding, outputPrefix, outputFile, parsedOptions,
sidecar, (uint)skip, noMetadata, noTrim);
else
switch(dev.Type)
{
case DeviceType.ATA:
Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
false, /*options.Raw,*/
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding,
outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
options.NoMetadata, options.NoTrim);
Ata.Dump(dev, devicePath, outputFormat, retryPasses, force, false, /*raw,*/
persistent, stopOnError, ref resume, ref dumpLog, encoding, outputPrefix, outputFile,
parsedOptions, sidecar, (uint)skip, noMetadata, noTrim);
break;
case DeviceType.MMC:
case DeviceType.SecureDigital:
SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
false, /*options.Raw,*/ options.Persistent, options.StopOnError, ref resume,
ref dumpLog, encoding, outputPrefix, options.OutputFile, parsedOptions,
sidecar, (uint)options.Skip, options.NoMetadata, options.NoTrim);
SecureDigital.Dump(dev, devicePath, outputFormat, retryPasses, force, false, /*raw,*/
persistent, stopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
outputFile, parsedOptions, sidecar, (uint)skip, noMetadata, noTrim);
break;
case DeviceType.NVMe:
NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
false, /*options.Raw,*/
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding,
outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
options.NoMetadata, options.NoTrim);
NvMe.Dump(dev, devicePath, outputFormat, retryPasses, force, false, /*raw,*/
persistent, stopOnError, ref resume, ref dumpLog, encoding, outputPrefix, outputFile,
parsedOptions, sidecar, (uint)skip, noMetadata, noTrim);
break;
case DeviceType.ATAPI:
case DeviceType.SCSI:
Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
false, /*options.Raw,*/
options.Persistent, options.StopOnError, ref resume, ref dumpLog,
options.FirstTrackPregap, encoding, outputPrefix, options.OutputFile, parsedOptions,
sidecar, (uint)options.Skip, options.NoMetadata, options.NoTrim);
Scsi.Dump(dev, devicePath, outputFormat, retryPasses, force, false, /*raw,*/
persistent, stopOnError, ref resume, ref dumpLog, firstTrackPregap, encoding,
outputPrefix, outputFile, parsedOptions, sidecar, (uint)skip, noMetadata, noTrim);
break;
default:
dumpLog.WriteLine("Unknown device type.");
@@ -251,7 +336,7 @@ namespace DiscImageChef.Commands
throw new NotSupportedException("Unknown device type.");
}
if(resume != null && options.Resume)
if(resume != null && doResume)
{
resume.LastWriteDate = DateTime.UtcNow;
resume.BadBlocks.Sort();
@@ -266,9 +351,10 @@ namespace DiscImageChef.Commands
dumpLog.Close();
Core.Statistics.AddCommand("dump-media");
Statistics.AddCommand("dump-media");
dev.Close();
return 0;
}
}
}

View File

@@ -30,31 +30,90 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
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);
DicConsole.DebugWriteLine("Entropy command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Entropy command", "--separated-tracks={0}", options.SeparatedTracks);
DicConsole.DebugWriteLine("Entropy command", "--whole-disc={0}", options.WholeDisc);
DicConsole.DebugWriteLine("Entropy command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("Entropy command", "--duplicated-sectors={0}", options.DuplicatedSectors);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{
"duplicated-sectors|p",
"Calculates how many sectors are duplicated (have same exact data in user area).",
b => duplicatedSectors = b != null
},
{
"separated-tracks|t", "Calculates entropy for each track separately.",
b => separatedTracks = b != null
},
{"whole-disc|w", "Calculates entropy for the whole disc.", b => wholeDisc = b != null},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
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();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 1;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -62,15 +121,15 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming");
return;
return 2;
}
inputFormat.Open(inputFilter);
Core.Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(inputFormat.Format);
Statistics.AddMedia(inputFormat.Info.MediaType, false);
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.InitProgress2Event += Progress.InitProgress2;
entropyCalculator.UpdateProgressEvent += Progress.UpdateProgress;
@@ -78,9 +137,9 @@ namespace DiscImageChef.Commands
entropyCalculator.EndProgressEvent += Progress.EndProgress;
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)
{
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");
return;
Statistics.AddCommand("entropy");
return 0;
}
EntropyResults entropy = entropyCalculator.CalculateMediaEntropy(options.DuplicatedSectors);
EntropyResults entropy = entropyCalculator.CalculateMediaEntropy(duplicatedSectors);
DicConsole.WriteLine("Entropy for disk is {0:F4}.", entropy.Entropy);
if(entropy.UniqueSectors != null)
DicConsole.WriteLine("Disk has {0} unique sectors ({1:P3})", entropy.UniqueSectors,
(double)entropy.UniqueSectors / (double)entropy.Sectors);
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.Console;
using DiscImageChef.Core;
using Mono.Options;
namespace DiscImageChef.Commands
{
// TODO: Rewrite this, has an insane amount of repeating code ;)
static class ExtractFiles
class ExtractFilesCommand : Command
{
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);
DicConsole.DebugWriteLine("Extract-Files command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Extract-Files command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("Extract-Files command", "--xattrs={0}", options.Xattrs);
DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", options.OutputDir);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
{
"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();
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:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
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)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 0;
}
Encoding encoding = null;
if(options.EncodingName != null)
if(encodingName != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
}
catch(ArgumentException)
{
DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return;
return 1;
}
PluginBase plugins = GetPluginBase.Instance;
@@ -91,21 +150,21 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
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,
imageFormat.Id);
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.");
return;
return 3;
}
Directory.CreateDirectory(options.OutputDir);
Directory.CreateDirectory(outputDir);
try
{
@@ -113,7 +172,7 @@ namespace DiscImageChef.Commands
{
DicConsole.WriteLine("Unable to open image format");
DicConsole.WriteLine("No error given");
return;
return 4;
}
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}.",
imageFormat.Info.MediaType);
Core.Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddMedia(imageFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(imageFormat.Format);
Statistics.AddMedia(imageFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
}
catch(Exception ex)
{
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return;
return 5;
}
List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
@@ -185,7 +244,7 @@ namespace DiscImageChef.Commands
{
string outputPath;
FileStream outputFile;
if(options.Xattrs)
if(extractXattrs)
{
error = fs.ListXAttr(entry, out List<string> xattrs);
if(error == Errno.NoError)
@@ -195,14 +254,15 @@ namespace DiscImageChef.Commands
error = fs.GetXattr(entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue;
Directory
.CreateDirectory(Path.Combine(options.OutputDir,
fs.XmlFsType.Type,
volumeName, ".xattrs",
Directory.CreateDirectory(Path.Combine(outputDir,
fs.XmlFsType
.Type,
volumeName,
".xattrs",
xattr));
outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type,
Path.Combine(outputDir, fs.XmlFsType.Type,
volumeName, ".xattrs", xattr, entry);
if(!File.Exists(outputPath))
@@ -245,13 +305,11 @@ namespace DiscImageChef.Commands
}
}
Directory.CreateDirectory(Path.Combine(options.OutputDir,
fs.XmlFsType.Type,
Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type,
volumeName));
outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName,
entry);
Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, entry);
if(!File.Exists(outputPath))
{
@@ -304,7 +362,7 @@ namespace DiscImageChef.Commands
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}",
@@ -335,7 +393,7 @@ namespace DiscImageChef.Commands
{
FileStream outputFile;
string outputPath;
if(options.Xattrs)
if(extractXattrs)
{
error = fs.ListXAttr(entry, out List<string> xattrs);
if(error == Errno.NoError)
@@ -345,14 +403,14 @@ namespace DiscImageChef.Commands
error = fs.GetXattr(entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue;
Directory.CreateDirectory(Path.Combine(options.OutputDir,
Directory.CreateDirectory(Path.Combine(outputDir,
fs.XmlFsType.Type,
volumeName, ".xattrs",
xattr));
outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type,
volumeName, ".xattrs", xattr, entry);
Path.Combine(outputDir, fs.XmlFsType.Type, volumeName,
".xattrs", xattr, entry);
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));
outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry);
outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, entry);
if(!File.Exists(outputPath))
{
@@ -447,7 +504,7 @@ namespace DiscImageChef.Commands
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());
}
@@ -491,7 +548,7 @@ namespace DiscImageChef.Commands
{
FileStream outputFile;
string outputPath;
if(options.Xattrs)
if(extractXattrs)
{
error = fs.ListXAttr(entry, out List<string> xattrs);
if(error == Errno.NoError)
@@ -501,14 +558,14 @@ namespace DiscImageChef.Commands
error = fs.GetXattr(entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue;
Directory.CreateDirectory(Path.Combine(options.OutputDir,
Directory.CreateDirectory(Path.Combine(outputDir,
fs.XmlFsType.Type,
volumeName, ".xattrs",
xattr));
outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type,
volumeName, ".xattrs", xattr, entry);
Path.Combine(outputDir, fs.XmlFsType.Type, volumeName,
".xattrs", xattr, entry);
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));
outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry);
outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, entry);
if(!File.Exists(outputPath))
{
@@ -603,7 +659,7 @@ namespace DiscImageChef.Commands
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());
}
@@ -630,7 +686,7 @@ namespace DiscImageChef.Commands
{
string outputPath;
FileStream outputFile;
if(options.Xattrs)
if(extractXattrs)
{
error = fs.ListXAttr(entry, out List<string> xattrs);
if(error == Errno.NoError)
@@ -640,13 +696,12 @@ namespace DiscImageChef.Commands
error = fs.GetXattr(entry, xattr, ref xattrBuf);
if(error != Errno.NoError) continue;
Directory.CreateDirectory(Path.Combine(options.OutputDir,
fs.XmlFsType.Type, volumeName,
".xattrs", xattr));
Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type,
volumeName, ".xattrs", xattr));
outputPath =
Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName,
".xattrs", xattr, entry);
Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, ".xattrs",
xattr, entry);
if(!File.Exists(outputPath))
{
@@ -686,10 +741,9 @@ namespace DiscImageChef.Commands
}
}
Directory.CreateDirectory(Path.Combine(options.OutputDir, fs.XmlFsType.Type,
volumeName));
Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type, volumeName));
outputPath = Path.Combine(options.OutputDir, fs.XmlFsType.Type, volumeName, entry);
outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, entry);
if(!File.Exists(outputPath))
{
@@ -734,7 +788,7 @@ namespace DiscImageChef.Commands
}
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());
}
@@ -745,7 +799,8 @@ namespace DiscImageChef.Commands
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.Core;
using DiscImageChef.Partitions;
using Mono.Options;
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;
FiltersList filtersList = new FiltersList();
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)
if(formatsOptions.Verbose)
if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
@@ -59,22 +98,22 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Read-only media image formats ({0}):",
plugins.ImagePluginsList.Count(t => !t.Value.GetType().GetInterfaces()
.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()
.GetInterfaces()
.Contains(typeof(
IWritableImage
))))
if(formatsOptions.Verbose)
if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine();
DicConsole.WriteLine("Read/write media image formats ({0}):", plugins.WritableImages.Count);
if(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)
if(formatsOptions.Verbose)
if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
@@ -83,13 +122,13 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Supported filesystems for identification and information only ({0}):",
plugins.PluginsList.Count(t => !t.Value.GetType().GetInterfaces()
.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()
.GetInterfaces()
.Contains(typeof(
IReadOnlyFilesystem
))))
if(formatsOptions.Verbose)
if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
@@ -97,23 +136,24 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine();
DicConsole.WriteLine("Supported filesystems that can read their contents ({0}):",
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)
if(formatsOptions.Verbose)
if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine();
DicConsole.WriteLine("Supported partitioning schemes ({0}):", plugins.PartPluginsList.Count);
if(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)
if(formatsOptions.Verbose)
if(MainClass.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.Id, kvp.Value.Name);
else
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.Collections.Generic;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
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);
DicConsole.DebugWriteLine("Analyze command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Analyze command", "--input={0}", options.InputFile);
Options = new OptionSet
{
$"{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();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 1;
}
try
@@ -62,7 +109,7 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
DicConsole.WriteLine("Image format not identified.");
return;
return 2;
}
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("No error given");
return;
return 3;
}
Core.ImageInfo.PrintImageInfo(imageFormat);
ImageInfo.PrintImageInfo(imageFormat);
Core.Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddMedia(imageFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(imageFormat.Format);
Statistics.AddMedia(imageFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
}
catch(Exception ex)
{
@@ -96,7 +143,8 @@ namespace DiscImageChef.Commands
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
// ****************************************************************************/
using System.Collections.Generic;
using System.Linq;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Devices;
using Mono.Options;
namespace DiscImageChef.Commands
{
static class ListDevices
class ListDevicesCommand : Command
{
internal static void DoListDevices(ListDevicesOptions options)
{
DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", options.Debug);
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.Verbose);
bool showHelp;
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.");
else
@@ -55,12 +92,13 @@ namespace DiscImageChef.Commands
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,
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.Text;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
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
.GetEncodings().Select(info => new CommonEncodingInfo
{
@@ -59,7 +98,8 @@ namespace DiscImageChef.Commands
foreach(CommonEncodingInfo info in encodings.OrderBy(t => t.DisplayName))
DicConsole.WriteLine("{0,-16} {1,-8}", info.Name, info.DisplayName);
Core.Statistics.AddCommand("list-encodings");
Statistics.AddCommand("list-encodings");
return 0;
}
struct CommonEncodingInfo

View File

@@ -37,13 +37,52 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
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;
DicConsole.WriteLine("Read-only filesystems options:");
@@ -77,6 +116,8 @@ namespace DiscImageChef.Commands
option.@default, option.description);
DicConsole.WriteLine();
}
return 0;
}
static string TypeToString(Type type)

View File

@@ -38,44 +38,99 @@ using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
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);
DicConsole.DebugWriteLine("Ls command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Ls command", "--input={0}", options.InputFile);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"encoding|e=", "Name of character encoding to use.", s => encodingName = s},
{"long|l", "Uses long format.", b => longFormat = b != null},
{
"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();
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:");
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
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)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 1;
}
Encoding encoding = null;
if(options.EncodingName != null)
if(encodingName != null)
try
{
encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName);
if(options.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
if(MainClass.Verbose) DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
}
catch(ArgumentException)
{
DicConsole.ErrorWriteLine("Specified encoding is not supported.");
return;
return 2;
}
PluginBase plugins = GetPluginBase.Instance;
@@ -87,10 +142,10 @@ namespace DiscImageChef.Commands
if(imageFormat == null)
{
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,
imageFormat.Id);
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("No error given");
return;
return 4;
}
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}.",
imageFormat.Info.MediaType);
Core.Statistics.AddMediaFormat(imageFormat.Format);
Core.Statistics.AddMedia(imageFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(imageFormat.Format);
Statistics.AddMedia(imageFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
}
catch(Exception ex)
{
DicConsole.ErrorWriteLine("Unable to open image format");
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
return;
return 3;
}
List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
@@ -168,7 +223,7 @@ namespace DiscImageChef.Commands
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}",
@@ -196,7 +251,7 @@ namespace DiscImageChef.Commands
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());
}
@@ -235,7 +290,7 @@ namespace DiscImageChef.Commands
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());
}
@@ -257,7 +312,7 @@ namespace DiscImageChef.Commands
error = fs.ReadDir("/", out List<string> rootDir);
if(error == Errno.NoError)
foreach(string entry in rootDir)
if(options.Long)
if(longFormat)
{
error = fs.Stat(entry, out FileEntryInfo stat);
if(error == Errno.NoError)
@@ -284,7 +339,7 @@ namespace DiscImageChef.Commands
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());
}
@@ -297,7 +352,8 @@ namespace DiscImageChef.Commands
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.Xbox;
using DiscImageChef.Devices;
using Mono.Options;
using BCA = DiscImageChef.Decoders.Bluray.BCA;
using Cartridge = DiscImageChef.Decoders.DVD.Cartridge;
using DDS = DiscImageChef.Decoders.DVD.DDS;
@@ -52,28 +53,75 @@ using Spare = DiscImageChef.Decoders.DVD.Spare;
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);
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Media-Info command", "--device={0}", options.DevicePath);
DicConsole.DebugWriteLine("Media-Info command", "--output-prefix={0}", options.OutputPrefix);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] devicepath",
"",
Help,
{"output-prefix|w=", "Write binary responses from device with that prefix.", s => outputPrefix = s},
{
"help|h|?", "Show this message and exit.",
v => showHelp = v != null
}
};
}
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' &&
char.IsLetter(options.DevicePath[0]))
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':';
public override int Invoke(IEnumerable<string> arguments)
{
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)
{
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return;
return 1;
}
Core.Statistics.AddDevice(dev);
Statistics.AddDevice(dev);
switch(dev.Type)
{
@@ -85,16 +133,18 @@ namespace DiscImageChef.Commands
DoSdMediaInfo();
break;
case DeviceType.NVMe:
DoNvmeMediaInfo(options.OutputPrefix, dev);
DoNvmeMediaInfo(outputPrefix, dev);
break;
case DeviceType.ATAPI:
case DeviceType.SCSI:
DoScsiMediaInfo(options.OutputPrefix, dev);
DoScsiMediaInfo(outputPrefix, dev);
break;
default: throw new NotSupportedException("Unknown device type.");
}
Core.Statistics.AddCommand("media-info");
Statistics.AddCommand("media-info");
return 0;
}
static void DoAtaMediaInfo()
@@ -451,7 +501,7 @@ namespace DiscImageChef.Commands
}
DicConsole.WriteLine("Media identified as {0}", scsiInfo.MediaType);
Core.Statistics.AddMedia(scsiInfo.MediaType, true);
Statistics.AddMedia(scsiInfo.MediaType, true);
dev.Close();
}

View File

@@ -31,54 +31,103 @@
// ****************************************************************************/
using System;
using System.Collections.Generic;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Core.Devices.Scanning;
using DiscImageChef.Devices;
using Mono.Options;
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);
DicConsole.DebugWriteLine("Media-Scan command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Media-Scan command", "--device={0}", options.DevicePath);
DicConsole.DebugWriteLine("Media-Scan command", "--mhdd-log={0}", options.MhddLogPath);
DicConsole.DebugWriteLine("Media-Scan command", "--ibg-log={0}", options.IbgLogPath);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] devicepath",
"",
Help,
{"mhdd-log|mw=", "Write a log of the scan in the format used by MHDD.", s => mhddLogPath = s},
{"ibg-log|b=", "Write a log of the scan in the format used by ImgBurn.", s => ibgLogPath = s},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' &&
char.IsLetter(options.DevicePath[0]))
options.DevicePath = "\\\\.\\" + char.ToUpper(options.DevicePath[0]) + ':';
public override int Invoke(IEnumerable<string> arguments)
{
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)
{
DicConsole.ErrorWriteLine("Error {0} opening device.", dev.LastError);
return;
return 1;
}
Core.Statistics.AddDevice(dev);
Statistics.AddDevice(dev);
ScanResults results;
switch(dev.Type)
{
case DeviceType.ATA:
results = Ata.Scan(options.MhddLogPath, options.IbgLogPath, options.DevicePath, dev);
results = Ata.Scan(mhddLogPath, ibgLogPath, devicePath, dev);
break;
case DeviceType.MMC:
case DeviceType.SecureDigital:
results = SecureDigital.Scan(options.MhddLogPath, options.IbgLogPath, options.DevicePath, dev);
results = SecureDigital.Scan(mhddLogPath, ibgLogPath, devicePath, dev);
break;
case DeviceType.NVMe:
results = Nvme.Scan(options.MhddLogPath, options.IbgLogPath, options.DevicePath, dev);
results = Nvme.Scan(mhddLogPath, ibgLogPath, devicePath, dev);
break;
case DeviceType.ATAPI:
case DeviceType.SCSI:
results = Scsi.Scan(options.MhddLogPath, options.IbgLogPath, options.DevicePath, dev);
results = Scsi.Scan(mhddLogPath, ibgLogPath, devicePath, dev);
break;
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)",
results.SeekTimes, results.SeekMax, results.SeekMin, results.SeekTotal / 1000);
Core.Statistics.AddCommand("media-scan");
Statistics.AddCommand("media-scan");
dev.Close();
return 0;
}
}
}

View File

@@ -30,32 +30,91 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Interfaces;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
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);
DicConsole.DebugWriteLine("PrintHex command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("PrintHex command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("PrintHex command", "--start={0}", options.StartSector);
DicConsole.DebugWriteLine("PrintHex command", "--length={0}", options.Length);
DicConsole.DebugWriteLine("PrintHex command", "--long-sectors={0}", options.LongSectors);
DicConsole.DebugWriteLine("PrintHex command", "--WidthBytes={0}", options.WidthBytes);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"length|l=", "How many sectors to print.", (ulong ul) => length = ul},
{"long-sectors|r", "Print sectors with tags included.", b => longSectors = b != null},
{"start|s=", "Name of character encoding to use.", (ulong ul) => startSector = ul},
{"width|w=", "How many bytes to print per line.", (ushort us) => widthBytes = us},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
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();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 1;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -63,20 +122,20 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying");
return;
return 2;
}
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)
{
DicConsole
.WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
options.LongSectors = false;
longSectors = false;
}
else
{
@@ -84,18 +143,19 @@ namespace DiscImageChef.Commands
{
DicConsole
.WriteLine("Requested sectors with tags, unsupported by underlying image format, printing only user data.");
options.LongSectors = false;
longSectors = false;
}
}
byte[] sector = options.LongSectors
? inputFormat.ReadSectorLong(options.StartSector + i)
: inputFormat.ReadSector(options.StartSector + i);
byte[] sector = longSectors
? inputFormat.ReadSectorLong(startSector.Value + 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
// ****************************************************************************/
using System.Collections.Generic;
using System.Linq;
using DiscImageChef.Console;
using DiscImageChef.Database;
using DiscImageChef.Database.Models;
using Mono.Options;
using Command = Mono.Options.Command;
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);
if(!ctx.Commands.Any() && !ctx.Filesystems.Any() && !ctx.Filters.Any() && !ctx.MediaFormats.Any() &&
!ctx.Medias.Any() && !ctx.Partitions.Any() && !ctx.SeenDevices.Any())
{
DicConsole.WriteLine("There are no statistics.");
return;
return 1;
}
bool thereAreStats = false;
@@ -198,6 +235,7 @@ namespace DiscImageChef.Commands
}
if(!thereAreStats) DicConsole.WriteLine("There are no statistics.");
return 0;
}
}
}

View File

@@ -30,25 +30,67 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using DiscImageChef.Console;
using DiscImageChef.Core;
using Mono.Options;
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);
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.Verbose);
this.masterDbUpdate = masterDbUpdate;
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name}",
"",
Help,
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
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);
return 0;
}
internal static void DoUpdate(bool 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.Console;
using DiscImageChef.Core;
using Mono.Options;
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);
DicConsole.DebugWriteLine("Verify command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Verify command", "--input={0}", options.InputFile);
DicConsole.DebugWriteLine("Verify command", "--verify-disc={0}", options.VerifyDisc);
DicConsole.DebugWriteLine("Verify command", "--verify-sectors={0}", options.VerifySectors);
Options = new OptionSet
{
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
$"{MainClass.AssemblyCopyright}",
"",
$"usage: DiscImageChef {Name} [OPTIONS] imagefile",
"",
Help,
{"verify-disc|w", "Verify disc image if supported.", b => verifyDisc = b != null},
{"verify-sectors|s", "Verify all sectors if supported.", b => verifySectors = b != null},
{"help|h|?", "Show this message and exit.", v => showHelp = v != null}
};
}
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();
IFilter inputFilter = filtersList.GetFilter(options.InputFile);
IFilter inputFilter = filtersList.GetFilter(inputFile);
if(inputFilter == null)
{
DicConsole.ErrorWriteLine("Cannot open specified file.");
return;
return 1;
}
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
@@ -64,13 +112,13 @@ namespace DiscImageChef.Commands
if(inputFormat == null)
{
DicConsole.ErrorWriteLine("Unable to recognize image format, not verifying");
return;
return 2;
}
inputFormat.Open(inputFilter);
Core.Statistics.AddMediaFormat(inputFormat.Format);
Core.Statistics.AddMedia(inputFormat.Info.MediaType, false);
Core.Statistics.AddFilter(inputFilter.Name);
Statistics.AddMediaFormat(inputFormat.Format);
Statistics.AddMedia(inputFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
bool? correctDisc = null;
long totalSectors = 0;
@@ -78,7 +126,7 @@ namespace DiscImageChef.Commands
long correctSectors = 0;
long unknownSectors = 0;
if(options.VerifyDisc)
if(verifyDisc)
{
DateTime startCheck = DateTime.UtcNow;
bool? discCheckStatus = inputFormat.VerifyMediaImage();
@@ -103,7 +151,7 @@ namespace DiscImageChef.Commands
DicConsole.VerboseWriteLine("Checking disc image checksums took {0} seconds", checkTime.TotalSeconds);
}
if(options.VerifySectors)
if(verifySectors)
{
bool formatHasTracks;
try
@@ -215,7 +263,7 @@ namespace DiscImageChef.Commands
DicConsole.VerboseWriteLine("Checking sector checksums took {0} seconds", checkTime.TotalSeconds);
if(options.Verbose)
if(MainClass.Verbose)
{
DicConsole.VerboseWriteLine("LBAs with error:");
if(failingLbas.Count == (int)inputFormat.Info.Sectors)
@@ -243,7 +291,8 @@ namespace DiscImageChef.Commands
correctSectors = totalSectors - errorSectors - unknownSectors;
}
Core.Statistics.AddCommand("verify");
Statistics.AddCommand("verify");
return 0;
}
}
}

View File

@@ -53,11 +53,11 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Commands\ConvertImage.cs" />
<Compile Include="Commands\Gui.cs" />
<Compile Include="Commands\ImageInfo.cs" />
<Compile Include="Commands\ListOptions.cs" />
<Compile Include="Commands\Update.cs" />
<Compile Include="Main.cs" />
<Compile Include="Options.cs" />
<Compile Include="Commands\Formats.cs" />
<Compile Include="Commands\Analyze.cs" />
<Compile Include="Commands\Compare.cs" />
@@ -262,11 +262,12 @@
<Content Include="..\.github\PULL_REQUEST_TEMPLATE.md" />
</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.Mac64" Version="2.4.1" />
<PackageReference Include="Eto.Platform.Wpf" Version="2.4.1" />
<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="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.2.5" />

View File

@@ -34,24 +34,35 @@ using System;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using CommandLine;
using DiscImageChef.Commands;
using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.Database;
using DiscImageChef.Gui.Forms;
using DiscImageChef.Settings;
using Eto;
using Eto.Forms;
using Microsoft.EntityFrameworkCore;
using Statistics = DiscImageChef.Core.Statistics;
using Mono.Options;
namespace DiscImageChef
{
class MainClass
{
internal static bool Verbose;
internal static bool Debug;
internal static string AssemblyCopyright;
internal static string AssemblyTitle;
internal static AssemblyInformationalVersionAttribute AssemblyVersion;
[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.WriteEvent += System.Console.Write;
DicConsole.ErrorWriteLineEvent += System.Console.Error.WriteLine;
@@ -66,7 +77,7 @@ namespace DiscImageChef
if(!File.Exists(Settings.Settings.MasterDbPath))
{
masterDbUpdate = true;
Update.DoUpdate(masterDbUpdate);
UpdateCommand.DoUpdate(masterDbUpdate);
}
DicContext mctx = DicContext.Create(Settings.Settings.MasterDbPath);
@@ -74,193 +85,63 @@ namespace DiscImageChef
mctx.SaveChanges();
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();
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.ShareStats)
Task.Run(() => { Statistics.SubmitStats(); });
Parser.Default.ParseArguments(args, typeof(AnalyzeOptions), typeof(BenchmarkOptions),
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 =>
CommandSet commands = new CommandSet("DiscImageChef")
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Analyze.DoAnalyze(opts);
}).WithParsed<CompareOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Compare.DoCompare(opts);
}).WithParsed<ChecksumOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Checksum.DoChecksum(opts);
}).WithParsed<EntropyOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Entropy.DoEntropy(opts);
}).WithParsed<VerifyOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Verify.DoVerify(opts);
}).WithParsed<PrintHexOptions>(opts =>
{
if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
PrintCopyright();
Commands.PrintHex.DoPrintHex(opts);
}).WithParsed<DecodeOptions>(opts =>
{
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;
$"{AssemblyTitle} {AssemblyVersion?.InformationalVersion}",
$"{AssemblyCopyright}",
"",
"usage: DiscImageChef COMMAND [OPTIONS]",
"",
"Global options:",
{"verbose|v", "Shows verbose output.", b => Verbose = b != null},
{"debug|d", "Shows debug output from plugins.", b => Debug = b != null},
"",
"Available commands:",
new AnalyzeCommand(),
new BenchmarkCommand(),
new ChecksumCommand(),
new CompareCommand(),
new ConfigureCommand(false),
new ConvertImageCommand(),
new CreateSidecarCommand(),
new DecodeCommand(),
new DeviceInfoCommand(),
new DeviceReportCommand(),
new DumpMediaCommand(),
new EntropyCommand(),
new ExtractFilesCommand(),
new FormatsCommand(),
new GuiCommand(),
new ImageInfoCommand(),
new ListDevicesCommand(),
new ListEncodingsCommand(),
new ListOptionsCommand(),
new LsCommand(),
new MediaInfoCommand(),
new MediaScanCommand(),
new PrintHexCommand(),
new StatisticsCommand(),
new UpdateCommand(masterDbUpdate),
new VerifyCommand()
};
new Application(Platform.Detect).Run(new frmMain(opts.Debug, opts.Verbose));
}).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));
int ret = commands.Run(args);
Statistics.SaveStats();
return ret;
}
static void PrintCopyright()
internal static void PrintCopyright()
{
object[] attributes =
typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
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("{0} {1}", AssemblyTitle, AssemblyVersion?.InformationalVersion);
DicConsole.WriteLine("{0}", AssemblyCopyright);
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 { }
}