2017-05-19 20:28:49 +01:00
|
|
|
// /***************************************************************************
|
2020-02-27 12:31:25 +00:00
|
|
|
// Aaru Data Preservation Suite
|
2016-07-28 18:13:49 +01:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Filename : Verify.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
//
|
2020-03-11 21:56:55 +00:00
|
|
|
// Component : Commands.
|
2016-07-28 18:13:49 +01:00
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
2020-03-11 21:56:55 +00:00
|
|
|
// Implements the 'verify' command.
|
2016-07-28 18:13:49 +01:00
|
|
|
//
|
|
|
|
|
// --[ 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/>.
|
|
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2022-02-18 10:02:53 +00:00
|
|
|
// Copyright © 2011-2022 Natalia Portillo
|
2016-07-28 18:13:49 +01:00
|
|
|
// ****************************************************************************/
|
2014-07-03 18:34:19 +01:00
|
|
|
|
|
|
|
|
using System;
|
2014-08-25 05:00:25 +01:00
|
|
|
using System.Collections.Generic;
|
2020-01-02 04:09:39 +00:00
|
|
|
using System.CommandLine;
|
2022-04-10 12:54:04 +01:00
|
|
|
using System.CommandLine.NamingConventionBinder;
|
2020-02-27 00:33:26 +00:00
|
|
|
using Aaru.CommonTypes;
|
|
|
|
|
using Aaru.CommonTypes.Enums;
|
|
|
|
|
using Aaru.CommonTypes.Interfaces;
|
|
|
|
|
using Aaru.CommonTypes.Structs;
|
|
|
|
|
using Aaru.Console;
|
|
|
|
|
using Aaru.Core;
|
2021-09-14 02:31:59 +01:00
|
|
|
using Spectre.Console;
|
2014-06-16 01:45:04 +01:00
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
namespace Aaru.Commands.Image;
|
|
|
|
|
|
2022-03-07 07:36:44 +00:00
|
|
|
sealed class VerifyCommand : Command
|
2014-06-16 01:45:04 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
public VerifyCommand() : base("verify", "Verifies a disc image integrity, and if supported, sector integrity.")
|
2014-06-16 01:45:04 +01:00
|
|
|
{
|
2022-04-10 12:54:04 +01:00
|
|
|
Add(new Option<bool>(new[]
|
|
|
|
|
{
|
|
|
|
|
"--verify-disc", "-w"
|
|
|
|
|
}, () => true, "Verify disc image if supported."));
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-04-10 12:54:04 +01:00
|
|
|
Add(new Option<bool>(new[]
|
|
|
|
|
{
|
|
|
|
|
"--verify-sectors", "-s"
|
|
|
|
|
}, () => true, "Verify all sectors if supported."));
|
2019-01-05 16:59:23 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
AddArgument(new Argument<string>
|
|
|
|
|
{
|
|
|
|
|
Arity = ArgumentArity.ExactlyOne,
|
|
|
|
|
Description = "Disc image path",
|
|
|
|
|
Name = "image-path"
|
|
|
|
|
});
|
2019-01-05 16:59:23 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
|
|
|
|
|
}
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
public static int Invoke(bool debug, bool verbose, string imagePath, bool verifyDisc = true,
|
|
|
|
|
bool verifySectors = true)
|
|
|
|
|
{
|
|
|
|
|
MainClass.PrintCopyright();
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(debug)
|
|
|
|
|
{
|
|
|
|
|
IAnsiConsole stderrConsole = AnsiConsole.Create(new AnsiConsoleSettings
|
2021-09-14 02:31:59 +01:00
|
|
|
{
|
2022-11-15 15:58:43 +00:00
|
|
|
Out = new AnsiConsoleOutput(System.Console.Error)
|
2021-09-14 02:31:59 +01:00
|
|
|
});
|
2016-09-05 17:37:31 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
AaruConsole.DebugWriteLineEvent += (format, objects) =>
|
2016-02-04 16:51:03 +00:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
if(objects is null)
|
|
|
|
|
stderrConsole.MarkupLine(format);
|
|
|
|
|
else
|
|
|
|
|
stderrConsole.MarkupLine(format, objects);
|
|
|
|
|
};
|
|
|
|
|
}
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(verbose)
|
|
|
|
|
AaruConsole.WriteEvent += (format, objects) =>
|
2021-09-14 02:31:59 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
if(objects is null)
|
|
|
|
|
AnsiConsole.Markup(format);
|
|
|
|
|
else
|
|
|
|
|
AnsiConsole.Markup(format, objects);
|
|
|
|
|
};
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Statistics.AddCommand("verify");
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
AaruConsole.DebugWriteLine("Verify command", "--debug={0}", debug);
|
|
|
|
|
AaruConsole.DebugWriteLine("Verify command", "--input={0}", imagePath);
|
|
|
|
|
AaruConsole.DebugWriteLine("Verify command", "--verbose={0}", verbose);
|
|
|
|
|
AaruConsole.DebugWriteLine("Verify command", "--verify-disc={0}", verifyDisc);
|
|
|
|
|
AaruConsole.DebugWriteLine("Verify command", "--verify-sectors={0}", verifySectors);
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
var filtersList = new FiltersList();
|
|
|
|
|
IFilter inputFilter = null;
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
ctx.AddTask("Identifying file filter...").IsIndeterminate();
|
|
|
|
|
inputFilter = filtersList.GetFilter(imagePath);
|
|
|
|
|
});
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(inputFilter == null)
|
|
|
|
|
{
|
|
|
|
|
AaruConsole.ErrorWriteLine("Cannot open specified file.");
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return (int)ErrorNumber.CannotOpenFile;
|
|
|
|
|
}
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
IBaseImage inputFormat = null;
|
* 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
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
ctx.AddTask("Identifying image format...").IsIndeterminate();
|
|
|
|
|
inputFormat = ImageFormat.Detect(inputFilter);
|
|
|
|
|
});
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(inputFormat == null)
|
|
|
|
|
{
|
|
|
|
|
AaruConsole.ErrorWriteLine("Unable to recognize image format, not verifying");
|
2019-01-20 22:24:15 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return (int)ErrorNumber.FormatNotFound;
|
|
|
|
|
}
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
ErrorNumber opened = ErrorNumber.NoData;
|
2019-01-20 22:24:15 +00:00
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
ctx.AddTask("Opening image file...").IsIndeterminate();
|
|
|
|
|
opened = inputFormat.Open(inputFilter);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(opened != ErrorNumber.NoError)
|
|
|
|
|
{
|
|
|
|
|
AaruConsole.WriteLine("Unable to open image format");
|
|
|
|
|
AaruConsole.WriteLine("Error {0}", opened);
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return (int)opened;
|
|
|
|
|
}
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Statistics.AddMediaFormat(inputFormat.Format);
|
|
|
|
|
Statistics.AddMedia(inputFormat.Info.MediaType, false);
|
|
|
|
|
Statistics.AddFilter(inputFilter.Name);
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
bool? correctImage = null;
|
|
|
|
|
long errorSectors = 0;
|
|
|
|
|
bool? correctSectors = null;
|
|
|
|
|
long unknownSectors = 0;
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
var verifiableImage = inputFormat as IVerifiableImage;
|
|
|
|
|
var verifiableSectorsImage = inputFormat as IVerifiableSectorsImage;
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(verifiableImage is null &&
|
|
|
|
|
verifiableSectorsImage is null)
|
|
|
|
|
{
|
|
|
|
|
AaruConsole.ErrorWriteLine("The specified image does not support any kind of verification");
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return (int)ErrorNumber.NotVerifiable;
|
|
|
|
|
}
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
TimeSpan checkTime;
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(verifyDisc && verifiableImage != null)
|
|
|
|
|
{
|
2022-11-15 15:58:43 +00:00
|
|
|
bool? discCheckStatus = null;
|
2022-11-13 21:14:18 +00:00
|
|
|
checkTime = new TimeSpan();
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
Core.Spectre.ProgressSingleSpinner(ctx =>
|
2014-08-25 05:00:25 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
ctx.AddTask("Verifying image checksums...").IsIndeterminate();
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
DateTime startCheck = DateTime.UtcNow;
|
|
|
|
|
discCheckStatus = verifiableImage.VerifyMediaImage();
|
|
|
|
|
DateTime endCheck = DateTime.UtcNow;
|
|
|
|
|
checkTime = endCheck - startCheck;
|
|
|
|
|
});
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
switch(discCheckStatus)
|
|
|
|
|
{
|
|
|
|
|
case true:
|
|
|
|
|
AaruConsole.WriteLine("Disc image checksums are correct");
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
break;
|
|
|
|
|
case false:
|
|
|
|
|
AaruConsole.WriteLine("Disc image checksums are incorrect");
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
break;
|
|
|
|
|
case null:
|
|
|
|
|
AaruConsole.WriteLine("Disc image does not contain checksums");
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
correctImage = discCheckStatus;
|
|
|
|
|
AaruConsole.VerboseWriteLine("Checking disc image checksums took {0} seconds", checkTime.TotalSeconds);
|
|
|
|
|
}
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
if(!verifySectors)
|
|
|
|
|
return correctImage switch
|
2022-11-15 15:58:43 +00:00
|
|
|
{
|
|
|
|
|
null => (int)ErrorNumber.NotVerifiable,
|
|
|
|
|
false => (int)ErrorNumber.BadImageSectorsNotVerified,
|
|
|
|
|
true => (int)ErrorNumber.CorrectImageSectorsNotVerified
|
|
|
|
|
};
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
DateTime startCheck = DateTime.Now;
|
|
|
|
|
DateTime endCheck = startCheck;
|
|
|
|
|
List<ulong> failingLbas = new();
|
|
|
|
|
List<ulong> unknownLbas = new();
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
if(verifiableSectorsImage is IOpticalMediaImage { Tracks: {} } opticalMediaImage)
|
|
|
|
|
{
|
|
|
|
|
List<Track> inputTracks = opticalMediaImage.Tracks;
|
|
|
|
|
ulong currentSectorAll = 0;
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
startCheck = DateTime.UtcNow;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
AnsiConsole.Progress().AutoClear(true).HideCompleted(true).
|
|
|
|
|
Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn()).
|
|
|
|
|
Start(ctx =>
|
|
|
|
|
{
|
|
|
|
|
ProgressTask discTask = ctx.AddTask("Checking tracks...");
|
|
|
|
|
discTask.MaxValue = inputTracks.Count;
|
2021-09-14 02:31:59 +01:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
foreach(Track currentTrack in inputTracks)
|
|
|
|
|
{
|
|
|
|
|
discTask.Description = $"Checking track {discTask.Value + 1} of {inputTracks.Count}";
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
ulong remainingSectors = currentTrack.EndSector - currentTrack.StartSector + 1;
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
ulong currentSector = 0;
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
ProgressTask trackTask = ctx.AddTask("Checking sector");
|
|
|
|
|
trackTask.MaxValue = remainingSectors;
|
2018-06-22 08:08:38 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
while(remainingSectors > 0)
|
|
|
|
|
{
|
2022-11-13 21:14:18 +00:00
|
|
|
trackTask.Description = $"Checking sector {currentSectorAll} of {
|
|
|
|
|
inputFormat.Info.Sectors}, on track {currentTrack.Sequence}";
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
List<ulong> tempFailingLbas;
|
|
|
|
|
List<ulong> tempUnknownLbas;
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(remainingSectors < 512)
|
2022-11-13 21:14:18 +00:00
|
|
|
opticalMediaImage.VerifySectors(currentSector, (uint)remainingSectors,
|
|
|
|
|
currentTrack.Sequence, out tempFailingLbas,
|
|
|
|
|
out tempUnknownLbas);
|
2022-03-06 13:29:38 +00:00
|
|
|
else
|
2022-11-13 21:14:18 +00:00
|
|
|
opticalMediaImage.VerifySectors(currentSector, 512, currentTrack.Sequence,
|
|
|
|
|
out tempFailingLbas, out tempUnknownLbas);
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
failingLbas.AddRange(tempFailingLbas);
|
2020-01-02 04:09:39 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
unknownLbas.AddRange(tempUnknownLbas);
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(remainingSectors < 512)
|
|
|
|
|
{
|
|
|
|
|
currentSector += remainingSectors;
|
2022-11-13 21:14:18 +00:00
|
|
|
currentSectorAll += remainingSectors;
|
|
|
|
|
trackTask.Value += remainingSectors;
|
2022-03-06 13:29:38 +00:00
|
|
|
remainingSectors = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
currentSector += 512;
|
2022-11-13 21:14:18 +00:00
|
|
|
currentSectorAll += 512;
|
|
|
|
|
trackTask.Value += 512;
|
2022-03-06 13:29:38 +00:00
|
|
|
remainingSectors -= 512;
|
|
|
|
|
}
|
|
|
|
|
}
|
* 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
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
trackTask.StopTask();
|
|
|
|
|
discTask.Increment(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
endCheck = DateTime.UtcNow;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else if(verifiableSectorsImage != null)
|
|
|
|
|
{
|
|
|
|
|
ulong remainingSectors = inputFormat.Info.Sectors;
|
|
|
|
|
ulong currentSector = 0;
|
* 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
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
AnsiConsole.Progress().AutoClear(true).HideCompleted(true).
|
|
|
|
|
Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn()).
|
|
|
|
|
Start(ctx =>
|
|
|
|
|
{
|
|
|
|
|
ProgressTask diskTask = ctx.AddTask("Checking sectors...");
|
|
|
|
|
diskTask.MaxValue = inputFormat.Info.Sectors;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
startCheck = DateTime.UtcNow;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
while(remainingSectors > 0)
|
|
|
|
|
{
|
|
|
|
|
diskTask.Description = $"Checking sector {currentSector} of {inputFormat.Info.Sectors}";
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
List<ulong> tempFailingLbas;
|
|
|
|
|
List<ulong> tempUnknownLbas;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
if(remainingSectors < 512)
|
|
|
|
|
verifiableSectorsImage.VerifySectors(currentSector, (uint)remainingSectors,
|
|
|
|
|
out tempFailingLbas, out tempUnknownLbas);
|
|
|
|
|
else
|
|
|
|
|
verifiableSectorsImage.VerifySectors(currentSector, 512, out tempFailingLbas,
|
|
|
|
|
out tempUnknownLbas);
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
failingLbas.AddRange(tempFailingLbas);
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
unknownLbas.AddRange(tempUnknownLbas);
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
if(remainingSectors < 512)
|
|
|
|
|
{
|
|
|
|
|
currentSector += remainingSectors;
|
|
|
|
|
diskTask.Value += remainingSectors;
|
|
|
|
|
remainingSectors = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
currentSector += 512;
|
|
|
|
|
diskTask.Value += 512;
|
|
|
|
|
remainingSectors -= 512;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
endCheck = DateTime.UtcNow;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkTime = endCheck - startCheck;
|
2019-01-05 19:50:56 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
if(unknownLbas.Count > 0)
|
|
|
|
|
AaruConsole.WriteLine("There is at least one sector that does not contain a checksum");
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
if(failingLbas.Count > 0)
|
|
|
|
|
AaruConsole.WriteLine("There is at least one sector with incorrect checksum or errors");
|
|
|
|
|
|
|
|
|
|
if(unknownLbas.Count == 0 &&
|
|
|
|
|
failingLbas.Count == 0)
|
|
|
|
|
AaruConsole.WriteLine("All sector checksums are correct");
|
|
|
|
|
|
|
|
|
|
AaruConsole.VerboseWriteLine("Checking sector checksums took {0} seconds", checkTime.TotalSeconds);
|
|
|
|
|
|
|
|
|
|
if(verbose)
|
|
|
|
|
{
|
|
|
|
|
AaruConsole.VerboseWriteLine("[red]LBAs with error:[/]");
|
|
|
|
|
|
|
|
|
|
if(failingLbas.Count == (int)inputFormat.Info.Sectors)
|
|
|
|
|
AaruConsole.VerboseWriteLine("\t[red]all sectors.[/]");
|
|
|
|
|
else
|
|
|
|
|
foreach(ulong t in failingLbas)
|
|
|
|
|
AaruConsole.VerboseWriteLine("\t{0}", t);
|
|
|
|
|
|
|
|
|
|
AaruConsole.WriteLine("[yellow3_1]LBAs without checksum:[/]");
|
|
|
|
|
|
|
|
|
|
if(unknownLbas.Count == (int)inputFormat.Info.Sectors)
|
|
|
|
|
AaruConsole.VerboseWriteLine("\t[yellow3_1]all sectors.[/]");
|
|
|
|
|
else
|
|
|
|
|
foreach(ulong t in unknownLbas)
|
|
|
|
|
AaruConsole.VerboseWriteLine("\t{0}", t);
|
2014-06-16 01:45:04 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-13 21:14:18 +00:00
|
|
|
AaruConsole.WriteLine("[italic]Total sectors...........[/] {0}", inputFormat.Info.Sectors);
|
|
|
|
|
AaruConsole.WriteLine("[italic]Total errors............[/] {0}", failingLbas.Count);
|
|
|
|
|
AaruConsole.WriteLine("[italic]Total unknowns..........[/] {0}", unknownLbas.Count);
|
|
|
|
|
AaruConsole.WriteLine("[italic]Total errors+unknowns...[/] {0}", failingLbas.Count + unknownLbas.Count);
|
|
|
|
|
|
|
|
|
|
if(failingLbas.Count > 0)
|
|
|
|
|
correctSectors = false;
|
|
|
|
|
else if((ulong)unknownLbas.Count < inputFormat.Info.Sectors)
|
|
|
|
|
correctSectors = true;
|
|
|
|
|
|
2022-11-13 19:59:24 +00:00
|
|
|
return correctImage switch
|
2022-11-15 15:58:43 +00:00
|
|
|
{
|
|
|
|
|
null when correctSectors is null => (int)ErrorNumber.NotVerifiable,
|
|
|
|
|
null when correctSectors == false => (int)ErrorNumber.BadSectorsImageNotVerified,
|
|
|
|
|
null => (int)ErrorNumber.CorrectSectorsImageNotVerified,
|
|
|
|
|
false when correctSectors is null => (int)ErrorNumber.BadImageSectorsNotVerified,
|
|
|
|
|
false when correctSectors == false => (int)ErrorNumber.BadImageBadSectors,
|
|
|
|
|
false => (int)ErrorNumber.CorrectSectorsBadImage,
|
|
|
|
|
true when correctSectors is null => (int)ErrorNumber.CorrectImageSectorsNotVerified,
|
|
|
|
|
true when correctSectors == false => (int)ErrorNumber.CorrectImageBadSectors,
|
|
|
|
|
true => (int)ErrorNumber.NoError
|
|
|
|
|
};
|
2014-06-16 01:45:04 +01:00
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
}
|