2017-05-19 20:28:49 +01:00
|
|
|
// /***************************************************************************
|
2016-07-28 18:13:49 +01:00
|
|
|
// The Disc Image Chef
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Filename : Checksum.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
//
|
|
|
|
|
// Component : Verbs.
|
|
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Implements the 'checksum' 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/>.
|
|
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2018-12-29 17:34:38 +00:00
|
|
|
// Copyright © 2011-2019 Natalia Portillo
|
2016-07-28 18:13:49 +01:00
|
|
|
// ****************************************************************************/
|
2014-07-03 18:35:19 +01:00
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2018-06-25 19:08:16 +01:00
|
|
|
using DiscImageChef.CommonTypes;
|
2019-01-05 19:50:56 +00:00
|
|
|
using DiscImageChef.CommonTypes.Enums;
|
2018-06-25 19:08:16 +01:00
|
|
|
using DiscImageChef.CommonTypes.Interfaces;
|
|
|
|
|
using DiscImageChef.CommonTypes.Structs;
|
2015-10-18 22:04:03 +01:00
|
|
|
using DiscImageChef.Console;
|
2017-05-27 15:17:20 +01:00
|
|
|
using DiscImageChef.Core;
|
2019-01-05 16:59:23 +00:00
|
|
|
using Mono.Options;
|
2017-05-27 18:03:57 +01:00
|
|
|
using Schemas;
|
2014-06-16 01:45:04 +01:00
|
|
|
|
|
|
|
|
namespace DiscImageChef.Commands
|
|
|
|
|
{
|
2019-01-05 16:59:23 +00:00
|
|
|
class ChecksumCommand : Command
|
2014-06-16 01:45:04 +01:00
|
|
|
{
|
2015-11-10 06:16:23 +00:00
|
|
|
// How many sectors to read at once
|
2017-12-20 17:15:26 +00:00
|
|
|
const uint SECTORS_TO_READ = 256;
|
2015-11-10 06:16:23 +00:00
|
|
|
|
2019-01-05 16:59:23 +00:00
|
|
|
bool doAdler32 = true;
|
|
|
|
|
bool doCrc16 = true;
|
|
|
|
|
bool doCrc32 = true;
|
|
|
|
|
bool doCrc64;
|
|
|
|
|
bool doFletcher16;
|
|
|
|
|
bool doFletcher32;
|
|
|
|
|
bool doMd5 = true;
|
|
|
|
|
bool doSha1 = true;
|
|
|
|
|
bool doSha256;
|
|
|
|
|
bool doSha384;
|
|
|
|
|
bool doSha512;
|
|
|
|
|
bool doSpamSum = true;
|
|
|
|
|
string inputFile;
|
|
|
|
|
bool separatedTracks = true;
|
|
|
|
|
bool showHelp;
|
|
|
|
|
bool wholeDisc = true;
|
|
|
|
|
|
|
|
|
|
public ChecksumCommand() : base("checksum", "Checksums an image.")
|
2014-06-16 01:45:04 +01:00
|
|
|
{
|
2019-01-05 16:59:23 +00:00
|
|
|
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},
|
|
|
|
|
{"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);
|
2019-01-05 19:50:56 +00:00
|
|
|
return (int)ErrorNumber.HelpRequested;
|
2019-01-05 16:59:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MainClass.PrintCopyright();
|
|
|
|
|
if(MainClass.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
|
|
|
|
|
if(MainClass.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
|
2019-01-05 20:21:57 +00:00
|
|
|
Statistics.AddCommand("checksum");
|
2019-01-05 16:59:23 +00:00
|
|
|
|
|
|
|
|
if(extra.Count > 1)
|
|
|
|
|
{
|
|
|
|
|
DicConsole.ErrorWriteLine("Too many arguments.");
|
2019-01-05 19:50:56 +00:00
|
|
|
return (int)ErrorNumber.UnexpectedArgumentCount;
|
2019-01-05 16:59:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(extra.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
DicConsole.ErrorWriteLine("Missing input image.");
|
2019-01-05 19:50:56 +00:00
|
|
|
return (int)ErrorNumber.MissingArgument;
|
2019-01-05 16:59:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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", "--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);
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2016-09-05 17:37:31 +01:00
|
|
|
FiltersList filtersList = new FiltersList();
|
2019-01-05 16:59:23 +00:00
|
|
|
IFilter inputFilter = filtersList.GetFilter(inputFile);
|
2016-09-05 17:37:31 +01:00
|
|
|
|
|
|
|
|
if(inputFilter == null)
|
2016-02-04 16:51:03 +00:00
|
|
|
{
|
2016-09-05 17:37:31 +01:00
|
|
|
DicConsole.ErrorWriteLine("Cannot open specified file.");
|
2019-01-05 19:50:56 +00:00
|
|
|
return (int)ErrorNumber.CannotOpenFile;
|
2016-02-04 16:51:03 +00:00
|
|
|
}
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
IMediaImage inputFormat = ImageFormat.Detect(inputFilter);
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(inputFormat == null)
|
2014-07-03 18:35:19 +01:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming");
|
2019-01-05 19:50:56 +00:00
|
|
|
return (int)ErrorNumber.UnrecognizedFormat;
|
2014-07-03 18:35:19 +01:00
|
|
|
}
|
|
|
|
|
|
2017-12-28 19:56:36 +00:00
|
|
|
inputFormat.Open(inputFilter);
|
2019-01-05 16:59:23 +00:00
|
|
|
Statistics.AddMediaFormat(inputFormat.Format);
|
|
|
|
|
Statistics.AddMedia(inputFormat.Info.MediaType, false);
|
|
|
|
|
Statistics.AddFilter(inputFilter.Name);
|
2017-05-27 18:03:57 +01:00
|
|
|
EnableChecksum enabledChecksums = new EnableChecksum();
|
|
|
|
|
|
2019-01-05 16:59:23 +00:00
|
|
|
if(doAdler32) enabledChecksums |= EnableChecksum.Adler32;
|
|
|
|
|
if(doCrc16) enabledChecksums |= EnableChecksum.Crc16;
|
|
|
|
|
if(doCrc32) enabledChecksums |= EnableChecksum.Crc32;
|
|
|
|
|
if(doCrc64) enabledChecksums |= EnableChecksum.Crc64;
|
|
|
|
|
if(doMd5) enabledChecksums |= EnableChecksum.Md5;
|
|
|
|
|
if(doSha1) enabledChecksums |= EnableChecksum.Sha1;
|
|
|
|
|
if(doSha256) enabledChecksums |= EnableChecksum.Sha256;
|
|
|
|
|
if(doSha384) enabledChecksums |= EnableChecksum.Sha384;
|
|
|
|
|
if(doSha512) enabledChecksums |= EnableChecksum.Sha512;
|
|
|
|
|
if(doSpamSum) enabledChecksums |= EnableChecksum.SpamSum;
|
|
|
|
|
if(doFletcher16) enabledChecksums |= EnableChecksum.Fletcher16;
|
|
|
|
|
if(doFletcher32) enabledChecksums |= EnableChecksum.Fletcher32;
|
|
|
|
|
|
|
|
|
|
Checksum mediaChecksum = null;
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
switch(inputFormat)
|
|
|
|
|
{
|
|
|
|
|
case IOpticalMediaImage opticalInput when opticalInput.Tracks != null:
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Checksum trackChecksum = null;
|
|
|
|
|
|
|
|
|
|
if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums);
|
|
|
|
|
|
|
|
|
|
ulong previousTrackEnd = 0;
|
|
|
|
|
|
|
|
|
|
List<Track> inputTracks = opticalInput.Tracks;
|
|
|
|
|
foreach(Track currentTrack in inputTracks)
|
|
|
|
|
{
|
|
|
|
|
if(currentTrack.TrackStartSector - previousTrackEnd != 0 && wholeDisc)
|
|
|
|
|
for(ulong i = previousTrackEnd + 1; i < currentTrack.TrackStartSector; i++)
|
|
|
|
|
{
|
|
|
|
|
DicConsole.Write("\rHashing track-less sector {0}", i);
|
|
|
|
|
|
|
|
|
|
byte[] hiddenSector = inputFormat.ReadSector(i);
|
|
|
|
|
|
|
|
|
|
mediaChecksum?.Update(hiddenSector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("Checksum command",
|
|
|
|
|
"Track {0} starts at sector {1} and ends at sector {2}",
|
|
|
|
|
currentTrack.TrackSequence, currentTrack.TrackStartSector,
|
|
|
|
|
currentTrack.TrackEndSector);
|
|
|
|
|
|
|
|
|
|
if(separatedTracks) trackChecksum = new Checksum(enabledChecksums);
|
|
|
|
|
|
|
|
|
|
ulong sectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector + 1;
|
|
|
|
|
ulong doneSectors = 0;
|
|
|
|
|
DicConsole.WriteLine("Track {0} has {1} sectors", currentTrack.TrackSequence, sectors);
|
|
|
|
|
|
|
|
|
|
while(doneSectors < sectors)
|
|
|
|
|
{
|
|
|
|
|
byte[] sector;
|
|
|
|
|
|
|
|
|
|
if(sectors - doneSectors >= SECTORS_TO_READ)
|
|
|
|
|
{
|
|
|
|
|
sector = opticalInput.ReadSectors(doneSectors, SECTORS_TO_READ,
|
|
|
|
|
currentTrack.TrackSequence);
|
|
|
|
|
DicConsole.Write("\rHashings sectors {0} to {2} of track {1}", doneSectors,
|
|
|
|
|
currentTrack.TrackSequence, doneSectors + SECTORS_TO_READ);
|
|
|
|
|
doneSectors += SECTORS_TO_READ;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sector = opticalInput.ReadSectors(doneSectors, (uint)(sectors - doneSectors),
|
|
|
|
|
currentTrack.TrackSequence);
|
|
|
|
|
DicConsole.Write("\rHashings sectors {0} to {2} of track {1}", doneSectors,
|
|
|
|
|
currentTrack.TrackSequence, doneSectors + (sectors - doneSectors));
|
|
|
|
|
doneSectors += sectors - doneSectors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(wholeDisc) mediaChecksum?.Update(sector);
|
|
|
|
|
|
|
|
|
|
if(separatedTracks) trackChecksum?.Update(sector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DicConsole.WriteLine();
|
|
|
|
|
|
|
|
|
|
if(separatedTracks)
|
|
|
|
|
if(trackChecksum != null)
|
|
|
|
|
foreach(ChecksumType chk in trackChecksum.End())
|
|
|
|
|
DicConsole.WriteLine("Track {0}'s {1}: {2}", currentTrack.TrackSequence,
|
|
|
|
|
chk.type, chk.Value);
|
|
|
|
|
|
|
|
|
|
previousTrackEnd = currentTrack.TrackEndSector;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(opticalInput.Info.Sectors - previousTrackEnd != 0 && wholeDisc)
|
|
|
|
|
for(ulong i = previousTrackEnd + 1; i < opticalInput.Info.Sectors; i++)
|
|
|
|
|
{
|
|
|
|
|
DicConsole.Write("\rHashing track-less sector {0}", i);
|
|
|
|
|
|
|
|
|
|
byte[] hiddenSector = inputFormat.ReadSector(i);
|
|
|
|
|
mediaChecksum?.Update(hiddenSector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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(MainClass.Debug) DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message);
|
|
|
|
|
else DicConsole.WriteLine("Unable to get separate tracks, not checksumming them");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ITapeImage tapeImage when tapeImage.IsTape && tapeImage.Files?.Count > 0:
|
2014-07-03 18:35:19 +01:00
|
|
|
{
|
2019-01-05 16:59:23 +00:00
|
|
|
Checksum trackChecksum = null;
|
2015-11-10 06:16:23 +00:00
|
|
|
|
2019-01-05 16:59:23 +00:00
|
|
|
if(wholeDisc) mediaChecksum = new Checksum(enabledChecksums);
|
2015-11-10 06:16:23 +00:00
|
|
|
|
|
|
|
|
ulong previousTrackEnd = 0;
|
|
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
foreach(TapeFile currentFile in tapeImage.Files)
|
2015-11-10 06:16:23 +00:00
|
|
|
{
|
2019-05-02 20:00:54 +01:00
|
|
|
if(currentFile.FirstBlock - previousTrackEnd != 0 && wholeDisc)
|
|
|
|
|
for(ulong i = previousTrackEnd + 1; i < currentFile.FirstBlock; i++)
|
2015-11-10 06:16:23 +00:00
|
|
|
{
|
2019-05-02 20:01:21 +01:00
|
|
|
DicConsole.Write("\rHashing file-less block {0}", i);
|
2015-11-10 06:16:23 +00:00
|
|
|
|
|
|
|
|
byte[] hiddenSector = inputFormat.ReadSector(i);
|
|
|
|
|
|
2017-12-21 16:59:15 +00:00
|
|
|
mediaChecksum?.Update(hiddenSector);
|
2015-11-10 06:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
DicConsole.DebugWriteLine("Checksum command",
|
2019-05-02 20:01:21 +01:00
|
|
|
"Track {0} starts at sector {1} and ends at block {2}",
|
2019-05-02 20:00:54 +01:00
|
|
|
currentFile.File, currentFile.FirstBlock, currentFile.LastBlock);
|
2015-11-10 06:16:23 +00:00
|
|
|
|
2019-01-05 16:59:23 +00:00
|
|
|
if(separatedTracks) trackChecksum = new Checksum(enabledChecksums);
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
ulong sectors = currentFile.LastBlock - currentFile.FirstBlock + 1;
|
2015-11-10 06:16:23 +00:00
|
|
|
ulong doneSectors = 0;
|
2019-05-02 20:00:54 +01:00
|
|
|
DicConsole.WriteLine("File {0} has {1} sectors", currentFile.File, sectors);
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
while(doneSectors < sectors)
|
2015-11-10 06:16:23 +00:00
|
|
|
{
|
|
|
|
|
byte[] sector;
|
|
|
|
|
|
2017-12-20 17:26:28 +00:00
|
|
|
if(sectors - doneSectors >= SECTORS_TO_READ)
|
2015-11-10 06:16:23 +00:00
|
|
|
{
|
2019-05-02 20:00:54 +01:00
|
|
|
sector = tapeImage.ReadSectors(doneSectors + currentFile.FirstBlock, SECTORS_TO_READ);
|
2019-05-02 20:01:21 +01:00
|
|
|
DicConsole.Write("\rHashings blocks {0} to {2} of file {1}", doneSectors,
|
2019-05-02 20:00:54 +01:00
|
|
|
currentFile.File, doneSectors + SECTORS_TO_READ);
|
2017-12-20 17:15:26 +00:00
|
|
|
doneSectors += SECTORS_TO_READ;
|
2015-11-10 06:16:23 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-05-02 20:00:54 +01:00
|
|
|
sector = tapeImage.ReadSectors(doneSectors + currentFile.FirstBlock,
|
|
|
|
|
(uint)(sectors - doneSectors));
|
2019-05-02 20:01:21 +01:00
|
|
|
DicConsole.Write("\rHashings blocks {0} to {2} of file {1}", doneSectors,
|
2019-05-02 20:00:54 +01:00
|
|
|
currentFile.File, doneSectors + (sectors - doneSectors));
|
2017-12-20 17:26:28 +00:00
|
|
|
doneSectors += sectors - doneSectors;
|
2015-11-10 06:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
2019-01-05 16:59:23 +00:00
|
|
|
if(wholeDisc) mediaChecksum?.Update(sector);
|
2015-11-10 06:16:23 +00:00
|
|
|
|
2019-01-05 16:59:23 +00:00
|
|
|
if(separatedTracks) trackChecksum?.Update(sector);
|
2015-11-10 06:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DicConsole.WriteLine();
|
|
|
|
|
|
2019-01-05 16:59:23 +00:00
|
|
|
if(separatedTracks)
|
2017-12-21 16:59:15 +00:00
|
|
|
if(trackChecksum != null)
|
|
|
|
|
foreach(ChecksumType chk in trackChecksum.End())
|
2019-05-02 20:00:54 +01:00
|
|
|
DicConsole.WriteLine("File {0}'s {1}: {2}", currentFile.File, chk.type, chk.Value);
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
previousTrackEnd = currentFile.LastBlock;
|
2015-11-10 06:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
if(tapeImage.Info.Sectors - previousTrackEnd != 0 && wholeDisc)
|
|
|
|
|
for(ulong i = previousTrackEnd + 1; i < tapeImage.Info.Sectors; i++)
|
2015-11-10 06:16:23 +00:00
|
|
|
{
|
2019-05-02 20:00:54 +01:00
|
|
|
DicConsole.Write("\rHashing file-less sector {0}", i);
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2015-11-10 06:16:23 +00:00
|
|
|
byte[] hiddenSector = inputFormat.ReadSector(i);
|
2017-12-21 16:59:15 +00:00
|
|
|
mediaChecksum?.Update(hiddenSector);
|
2015-11-10 06:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
2019-01-05 16:59:23 +00:00
|
|
|
if(wholeDisc)
|
2017-12-21 16:59:15 +00:00
|
|
|
if(mediaChecksum != null)
|
|
|
|
|
foreach(ChecksumType chk in mediaChecksum.End())
|
2019-05-02 20:00:54 +01:00
|
|
|
DicConsole.WriteLine("Tape's {0}: {1}", chk.type, chk.Value);
|
|
|
|
|
break;
|
2014-07-03 18:35:19 +01:00
|
|
|
}
|
|
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
default:
|
2014-07-03 18:35:19 +01:00
|
|
|
{
|
2019-05-02 20:00:54 +01:00
|
|
|
mediaChecksum = new Checksum(enabledChecksums);
|
2015-11-10 06:16:23 +00:00
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
ulong sectors = inputFormat.Info.Sectors;
|
|
|
|
|
DicConsole.WriteLine("Sectors {0}", sectors);
|
|
|
|
|
ulong doneSectors = 0;
|
|
|
|
|
|
|
|
|
|
while(doneSectors < sectors)
|
2015-11-10 06:16:23 +00:00
|
|
|
{
|
2019-05-02 20:00:54 +01:00
|
|
|
byte[] sector;
|
2015-11-10 06:16:23 +00:00
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
if(sectors - doneSectors >= SECTORS_TO_READ)
|
|
|
|
|
{
|
|
|
|
|
sector = inputFormat.ReadSectors(doneSectors, SECTORS_TO_READ);
|
|
|
|
|
DicConsole.Write("\rHashings sectors {0} to {1}", doneSectors,
|
|
|
|
|
doneSectors + SECTORS_TO_READ);
|
|
|
|
|
doneSectors += SECTORS_TO_READ;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sector = inputFormat.ReadSectors(doneSectors, (uint)(sectors - doneSectors));
|
|
|
|
|
DicConsole.Write("\rHashings sectors {0} to {1}", doneSectors,
|
|
|
|
|
doneSectors + (sectors - doneSectors));
|
|
|
|
|
doneSectors += sectors - doneSectors;
|
|
|
|
|
}
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
mediaChecksum.Update(sector);
|
|
|
|
|
}
|
2014-07-03 18:35:19 +01:00
|
|
|
|
2019-05-02 20:00:54 +01:00
|
|
|
DicConsole.WriteLine();
|
|
|
|
|
|
|
|
|
|
foreach(ChecksumType chk in mediaChecksum.End())
|
|
|
|
|
DicConsole.WriteLine("Disk's {0}: {1}", chk.type, chk.Value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-06-16 01:45:04 +01:00
|
|
|
}
|
* commandline:
* DiscImageChef.Settings/Settings.cs:
* DiscImageChef.Settings/docs/README.txt:
* DiscImageChef.Settings/packages.config:
* DiscImageChef.Settings/docs/LICENSE.txt:
* DiscImageChef.Settings/docs/ChangeLog.txt:
* DiscImageChef.Settings/docs/mono/index.xml:
* DiscImageChef.Settings/docs/html/index.html:
* DiscImageChef.Settings/Properties/AssemblyInfo.cs:
* DiscImageChef.Settings/DiscImageChef.Settings.csproj:
* DiscImageChef.Settings/docs/mono/ns-Claunia.PropertyList.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/UID.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/UID.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSSet.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/index.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSSet.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDate.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSData.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDate.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSData.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSArray.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSNumber.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSString.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSObject.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSArray.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSNumber.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSString.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSObject.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDictionary.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDictionary.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/XmlPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/XmlPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/ASCIIPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/ASCIIPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListParser.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListWriter.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListWriter.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListFormatException.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListFormatException.html:
Added supports for settings
* DiscImageChef/Commands/Configure.cs:
Added support for settings.
* DiscImageChef/Core/Statistics.cs:
* DiscImageChef/Commands/Verify.cs:
* DiscImageChef/Commands/Entropy.cs:
* DiscImageChef/Commands/Formats.cs:
* DiscImageChef/Commands/PrintHex.cs:
* DiscImageChef/Commands/MediaInfo.cs:
* DiscImageChef/Commands/Statistics.cs:
Added statistics.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
Corrected bug on inquiry decoding.
* DiscImageChef.Decoders/SCSI/Modes.cs:
Corrected bug on decoding mode page 2Ah without write
performance descriptors.
Corrected bug when there is a vendor page 0 in mode sense
decoding.
* DiscImageChef.Devices/Device/Constructor.cs:
Corrected detecting USB or FireWire attached CD/DVD/BD and
tape drives.
Try ATA identify on USB or FireWire that don't have SCSI
INQUIRY.
* DiscImageChef.DiscImages/CDRWin.cs:
Corrected CD-ROM XA vs CD-ROM detection.
* DiscImageChef.Partitions/AppleMap.cs:
Corrected big endian working.
Added debug output.
* DiscImageChef.sln:
Added supports for settings.
* DiscImageChef/Commands/Decode.cs:
* DiscImageChef/Commands/Analyze.cs:
* DiscImageChef/Commands/Compare.cs:
* DiscImageChef/Commands/Checksum.cs:
* DiscImageChef/Commands/Benchmark.cs:
* DiscImageChef/Commands/DeviceInfo.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Added statistics.
* DiscImageChef/Commands/DeviceReport.cs:
Added statistics.
Correct handling empty inquiry string fields.
Suppose it is not removable, til proved wrong.
Corrected MODE SENSE (6/10) detection and calling order.
If device is MMC type but reports neither mode page 2Ah
neither GET CONFIGURATION, try all CDs (old drives work like
that).
Try reading Lead-In and Lead-Out in Audio CD using Audio READ
CD commands.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Added support for DVD raw block (37856 bytes).
Check READ LONG up to 36 times the cooked block size. That
should be enough to detect huge blocked media (like DVD and
BD) without taking ages.
If READ LONG size had to be bruteforced, and debug is
activated, save the result.
* DiscImageChef/Commands/DumpMedia.cs:
Added statistics.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/Commands/MediaScan.cs:
Added statistics.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/DiscImageChef.csproj:
Added support for settings.
Added statistics.
* DiscImageChef/Main.cs:
* DiscImageChef/Options.cs:
Added support for settings.
Added statistics.
2016-02-03 18:58:11 +00:00
|
|
|
|
2019-01-05 19:50:56 +00:00
|
|
|
return (int)ErrorNumber.NoError;
|
2015-11-10 06:16:23 +00:00
|
|
|
}
|
2014-06-16 01:45:04 +01:00
|
|
|
}
|
2017-05-27 18:03:57 +01:00
|
|
|
}
|