Implements verification on all currently supported disk

images.
	Implements DC42 CRC calculation.
	Calculates TeleDisk CRC for disk sectors.
	Resolves #2 and bumps version to 2.1.
This commit is contained in:
2014-08-25 05:00:25 +01:00
parent fd60149c37
commit 3a03e3121e
13 changed files with 721 additions and 107 deletions

View File

@@ -27,6 +27,6 @@ Global
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = DiscImageChef\DiscImageChef.csproj
description = The Disc Image Chef.
version = 2.0
version = 2.1
EndGlobalSection
EndGlobal

View File

@@ -54,7 +54,7 @@ using System.Reflection;
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("2.0.*")]
[assembly: AssemblyVersion("2.1.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

View File

@@ -36,6 +36,8 @@ Copyright (C) 2011-2014 Claunia.com
****************************************************************************/
//$Id$
using System;
using DiscImageChef.ImagePlugins;
using System.Collections.Generic;
namespace DiscImageChef.Commands
{
@@ -51,7 +53,211 @@ namespace DiscImageChef.Commands
Console.WriteLine("--verify-disc={0}", options.VerifyDisc);
Console.WriteLine("--verify-sectors={0}", options.VerifySectors);
}
Console.WriteLine("Verifying not yet implemented."); return;
ImagePlugin inputFormat = ImageFormat.Detect(options.InputFile);
if (inputFormat == null)
{
Console.WriteLine("Unable to recognize image format, not verifying");
return;
}
inputFormat.OpenImage(options.InputFile);
if (options.VerifyDisc)
{
DateTime StartCheck = DateTime.UtcNow;
bool? discCheckStatus = inputFormat.VerifyDiskImage();
DateTime EndCheck = DateTime.UtcNow;
TimeSpan CheckTime = EndCheck - StartCheck;
switch (discCheckStatus)
{
case true:
Console.WriteLine("Disc image checksums are correct");
break;
case false:
Console.WriteLine("Disc image checksums are incorrect");
break;
case null:
Console.WriteLine("Disc image does not contain checksums");
break;
}
if (MainClass.isVerbose)
Console.WriteLine("Checking disc image checksums took {0} seconds", CheckTime.TotalSeconds);
}
if (options.VerifySectors)
{
bool formatHasTracks;
try
{
List<Track> inputTracks = inputFormat.GetTracks();
if (inputTracks.Count > 0)
formatHasTracks = true;
else
formatHasTracks = false;
}
catch
{
formatHasTracks = false;
}
DateTime StartCheck;
DateTime EndCheck;
List<UInt64> FailingLBAs = new List<UInt64>();
List<UInt64> UnknownLBAs = new List<UInt64>();
bool? checkStatus = null;
if (formatHasTracks)
{
List<Track> inputTracks = inputFormat.GetTracks();
UInt64 currentSectorAll = 0;
StartCheck = DateTime.UtcNow;
foreach (Track currentTrack in inputTracks)
{
UInt64 remainingSectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector;
UInt64 currentSector = 0;
while (remainingSectors > 0)
{
Console.Write("\rChecking sector {0} of {1}, on track {2}", currentSectorAll, inputFormat.GetSectors(), currentTrack.TrackSequence);
List<UInt64> tempFailingLBAs;
List<UInt64> tempUnknownLBAs;
bool? tempStatus;
if (remainingSectors < 512)
tempStatus = inputFormat.VerifySectors(currentSector, (uint)remainingSectors, currentTrack.TrackSequence, out tempFailingLBAs, out tempUnknownLBAs);
else
tempStatus = inputFormat.VerifySectors(currentSector, 512, currentTrack.TrackSequence, out tempFailingLBAs, out tempUnknownLBAs);
if (checkStatus == null || tempStatus == null)
checkStatus = null;
else if (checkStatus == false || tempStatus == false)
checkStatus = false;
else if (checkStatus == true && tempStatus == true)
checkStatus = true;
else
checkStatus = null;
foreach (UInt64 failLBA in tempFailingLBAs)
FailingLBAs.Add(failLBA);
foreach (UInt64 unknownLBA in tempUnknownLBAs)
UnknownLBAs.Add(unknownLBA);
if (remainingSectors < 512)
{
currentSector += remainingSectors;
currentSectorAll += remainingSectors;
remainingSectors = 0;
}
else
{
currentSector += 512;
currentSectorAll += 512;
remainingSectors -= 512;
}
}
}
EndCheck = DateTime.UtcNow;
}
else
{
UInt64 remainingSectors = inputFormat.GetSectors();
UInt64 currentSector = 0;
StartCheck = DateTime.UtcNow;
while (remainingSectors > 0)
{
Console.Write("\rChecking sector {0} of {1}", currentSector, inputFormat.GetSectors());
List<UInt64> tempFailingLBAs;
List<UInt64> tempUnknownLBAs;
bool? tempStatus;
if (remainingSectors < 512)
tempStatus = inputFormat.VerifySectors(currentSector, (uint)remainingSectors, out tempFailingLBAs, out tempUnknownLBAs);
else
tempStatus = inputFormat.VerifySectors(currentSector, 512, out tempFailingLBAs, out tempUnknownLBAs);
if (checkStatus == null || tempStatus == null)
checkStatus = null;
else if (checkStatus == false || tempStatus == false)
checkStatus = false;
else if (checkStatus == true && tempStatus == true)
checkStatus = true;
else
checkStatus = null;
foreach (UInt64 failLBA in tempFailingLBAs)
FailingLBAs.Add(failLBA);
foreach (UInt64 unknownLBA in tempUnknownLBAs)
UnknownLBAs.Add(unknownLBA);
if (remainingSectors < 512)
{
currentSector += remainingSectors;
remainingSectors = 0;
}
else
{
currentSector += 512;
remainingSectors -= 512;
}
}
EndCheck = DateTime.UtcNow;
}
TimeSpan CheckTime = EndCheck - StartCheck;
Console.Write("\r");
switch (checkStatus)
{
case true:
Console.WriteLine("All sector checksums are correct");
break;
case false:
Console.WriteLine("There is at least one sector with incorrect checksum or errors");
break;
case null:
Console.WriteLine("There is at least one sector that does not contain a checksum");
break;
}
if (MainClass.isVerbose)
Console.WriteLine("Checking sector checksums took {0} seconds", CheckTime.TotalSeconds);
if (MainClass.isVerbose)
{
Console.WriteLine("LBAs with error:");
if (FailingLBAs.Count == (int)inputFormat.GetSectors())
Console.WriteLine("\tall sectors.");
else
for (int i = 0; i < FailingLBAs.Count; i++)
Console.WriteLine("\t{0}", FailingLBAs[i]);
Console.WriteLine("LBAs without checksum:");
if (UnknownLBAs.Count == (int)inputFormat.GetSectors())
Console.WriteLine("\tall sectors.");
else
for (int i = 0; i < UnknownLBAs.Count; i++)
Console.WriteLine("\t{0}", UnknownLBAs[i]);
}
Console.WriteLine("Total sectors........... {0}", inputFormat.GetSectors());
Console.WriteLine("Total errors............ {0}", FailingLBAs.Count);
Console.WriteLine("Total unknowns.......... {0}", UnknownLBAs.Count);
Console.WriteLine("Total errors+unknowns... {0}", FailingLBAs.Count + UnknownLBAs.Count);
}
}
}
}

View File

@@ -10,7 +10,7 @@
<RootNamespace>DiscImageChef</RootNamespace>
<AssemblyName>DiscImageChef</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<ReleaseVersion>2.0</ReleaseVersion>
<ReleaseVersion>2.1</ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>True</DebugSymbols>

View File

@@ -1313,8 +1313,6 @@ namespace DiscImageChef.ImagePlugins
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
break;
}
default:
break;
}
}
@@ -1928,6 +1926,8 @@ namespace DiscImageChef.ImagePlugins
{
List<Track> tracks = new List<Track>();
UInt64 previousStartSector = 0;
foreach (CDRWinTrack cdr_track in discimage.tracks)
{
Track _track = new Track();
@@ -1936,6 +1936,7 @@ namespace DiscImageChef.ImagePlugins
_track.TrackDescription = cdr_track.title;
if (!cdr_track.indexes.TryGetValue(0, out _track.TrackStartSector))
cdr_track.indexes.TryGetValue(1, out _track.TrackStartSector);
_track.TrackStartSector += previousStartSector;
_track.TrackEndSector = _track.TrackStartSector + cdr_track.sectors - 1;
_track.TrackPregap = cdr_track.pregap;
_track.TrackSession = cdr_track.session;
@@ -1943,6 +1944,7 @@ namespace DiscImageChef.ImagePlugins
_track.TrackType = CDRWinTrackTypeToTrackType(cdr_track.tracktype);
tracks.Add(_track);
previousStartSector = _track.TrackEndSector + 1;
}
return tracks;
@@ -1989,6 +1991,85 @@ namespace DiscImageChef.ImagePlugins
return discimage.sessions;
}
public override bool? VerifySector(UInt64 sectorAddress)
{
byte[] buffer = ReadSectorLong(sectorAddress);
return Checksums.CDChecksums.CheckCDSector(buffer);
}
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
{
byte[] buffer = ReadSectorLong(sectorAddress, track);
return Checksums.CDChecksums.CheckCDSector(buffer);
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
byte[] buffer = ReadSectorsLong(sectorAddress, length);
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (int i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector);
switch (sectorStatus)
{
case null:
UnknownLBAs.Add((ulong)i + sectorAddress);
break;
case false:
FailingLBAs.Add((ulong)i + sectorAddress);
break;
}
}
if (UnknownLBAs.Count > 0)
return null;
if (FailingLBAs.Count > 0)
return false;
return true;
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (int i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector);
switch (sectorStatus)
{
case null:
UnknownLBAs.Add((ulong)i + sectorAddress);
break;
case false:
FailingLBAs.Add((ulong)i + sectorAddress);
break;
}
}
if (UnknownLBAs.Count > 0)
return null;
if (FailingLBAs.Count > 0)
return false;
return true;
}
public override bool? VerifyDiskImage()
{
return null;
}
#endregion
#region Private methods
@@ -2168,6 +2249,7 @@ namespace DiscImageChef.ImagePlugins
{
return _imageInfo.imageCreator;
}
#endregion
}
}

View File

@@ -373,6 +373,83 @@ namespace DiscImageChef.ImagePlugins
return true;
}
public override bool? VerifySector(UInt64 sectorAddress)
{
return null;
}
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
{
return null;
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
UnknownLBAs.Add(i);
return null;
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
UnknownLBAs.Add(i);
return null;
}
public override bool? VerifyDiskImage()
{
byte[] data = new byte[header.dataSize];
byte[] tags = new byte[header.tagSize];
UInt32 dataChk;
UInt32 tagsChk = 0;
if (MainClass.isDebug)
Console.WriteLine("DEBUG (DC42 plugin): Reading data");
FileStream datastream = new FileStream(dc42ImagePath, FileMode.Open, FileAccess.Read);
datastream.Seek((long)(dataOffset), SeekOrigin.Begin);
datastream.Read(data, 0, (int)header.dataSize);
datastream.Close();
if (MainClass.isDebug)
Console.WriteLine("DEBUG (DC42 plugin): Calculating data checksum");
dataChk = DC42CheckSum(data);
if (MainClass.isDebug)
{
Console.WriteLine("DEBUG (DC42 plugin): Calculated data checksum = 0x{0:X8}", dataChk);
Console.WriteLine("DEBUG (DC42 plugin): Stored data checksum = 0x{0:X8}", header.dataChecksum);
}
if (header.tagSize > 0)
{
if (MainClass.isDebug)
Console.WriteLine("DEBUG (DC42 plugin): Reading tags");
FileStream tagstream = new FileStream(dc42ImagePath, FileMode.Open, FileAccess.Read);
tagstream.Seek((long)(tagOffset), SeekOrigin.Begin);
tagstream.Read(tags, 0, (int)header.tagSize);
tagstream.Close();
if (MainClass.isDebug)
Console.WriteLine("DEBUG (DC42 plugin): Calculating data checksum");
tagsChk = DC42CheckSum(data);
if (MainClass.isDebug)
{
Console.WriteLine("DEBUG (DC42 plugin): Calculated data checksum = 0x{0:X8}", tagsChk);
Console.WriteLine("DEBUG (DC42 plugin): Stored data checksum = 0x{0:X8}", header.tagChecksum);
}
}
return dataChk == header.dataChecksum && tagsChk == header.tagChecksum;
}
public override bool ImageHasPartitions()
{
return _imageInfo.imageHasPartitions;
@@ -640,6 +717,25 @@ namespace DiscImageChef.ImagePlugins
}
#endregion Unsupported features
#region Private methods
private static UInt32 DC42CheckSum(byte[] buffer)
{
UInt32 dc42chk = 0;
if ((buffer.Length & 0x01) == 0x01)
return 0xFFFFFFFF;
for (UInt32 i = 0; i < buffer.Length; i += 2)
{
dc42chk += (uint)(buffer[i] << 8);
dc42chk += buffer[i + 1];
dc42chk = (dc42chk >> 1) | (dc42chk << 31);
}
return dc42chk;
}
#endregion
}
}

View File

@@ -108,7 +108,6 @@ namespace DiscImageChef.ImagePlugins
/// <param name="tag">Tag type to read.</param>
public abstract byte[] ReadDiskTag(DiskTagType tag);
// Gets a disk tag
/// <summary>
/// Reads a sector's user data.
/// </summary>
@@ -370,7 +369,50 @@ namespace DiscImageChef.ImagePlugins
/// </summary>
/// <returns>The sessions.</returns>
public abstract List<Session> GetSessions();
// Returns disc sessions
/// <summary>
/// Verifies a sector.
/// </summary>
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
/// <param name="sectorAddress">Sector address (LBA).</param>
public abstract bool? VerifySector(UInt64 sectorAddress);
/// <summary>
/// Verifies a sector, relative to track.
/// </summary>
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
/// <param name="sectorAddress">Sector address (relative LBA).</param>
/// <param name="track">Track.</param>
public abstract bool? VerifySector(UInt64 sectorAddress, UInt32 track);
/// <summary>
/// Verifies several sectors.
/// </summary>
/// <returns>True if all are correct, false if any is incorrect, null if any is uncheckable.</returns>
/// <param name="sectorAddress">Starting sector address (LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="FailingLBAs">List of incorrect sectors</param>
/// <param name="UnknownLBAs">List of uncheckable sectors</param>
public abstract bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs);
/// <summary>
/// Verifies several sectors, relative to track.
/// </summary>
/// <returns>True if all are correct, false if any is incorrect, null if any is uncheckable.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="FailingLBAs">List of incorrect sectors</param>
/// <param name="UnknownLBAs">List of uncheckable sectors</param>
public abstract bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs);
/// <summary>
/// Verifies disk image internal checksum.
/// </summary>
/// <returns>True if correct, false if incorrect, null if there is no internal checksum available</returns>
public abstract bool? VerifyDiskImage();
// CD flags bitmask
@@ -719,8 +761,9 @@ namespace DiscImageChef.ImagePlugins
FDFORMAT_35_HD,
// Generic hard disks
GENERIC_HDD
};
GENERIC_HDD}
;
/// <summary>
/// Track (as partitioning element) types.
@@ -738,8 +781,9 @@ namespace DiscImageChef.ImagePlugins
/// <summary>Data track, compact disc mode 2, form 1</summary>
CDMode2Form1,
/// <summary>Data track, compact disc mode 2, form 2</summary>
CDMode2Form2
};
CDMode2Form2}
;
/// <summary>
/// Track defining structure.
@@ -811,8 +855,9 @@ namespace DiscImageChef.ImagePlugins
/// <summary>CD track flags, 1 byte</summary>
CDTrackFlags,
/// <summary>DVD sector copyright information</summary>
DVD_CMI
};
DVD_CMI}
;
/// <summary>
/// Metadata present for each disk.
@@ -834,8 +879,9 @@ namespace DiscImageChef.ImagePlugins
/// <summary>DVD Copyright Management Information</summary>
DVD_CMI,
/// <summary>DVD Disc Manufacturer Information</summary>
DVD_DMI
};
DVD_DMI}
;
/// <summary>
/// Feature is supported by image but not implemented yet.

View File

@@ -2291,6 +2291,85 @@ namespace DiscImageChef.ImagePlugins
return imageSessions;
}
public override bool? VerifySector(UInt64 sectorAddress)
{
byte[] buffer = ReadSectorLong(sectorAddress);
return Checksums.CDChecksums.CheckCDSector(buffer);
}
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
{
byte[] buffer = ReadSectorLong(sectorAddress, track);
return Checksums.CDChecksums.CheckCDSector(buffer);
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
byte[] buffer = ReadSectorsLong(sectorAddress, length);
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (int i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector);
switch (sectorStatus)
{
case null:
UnknownLBAs.Add((ulong)i + sectorAddress);
break;
case false:
FailingLBAs.Add((ulong)i + sectorAddress);
break;
}
}
if (UnknownLBAs.Count > 0)
return null;
if (FailingLBAs.Count > 0)
return false;
return true;
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (int i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector);
switch (sectorStatus)
{
case null:
UnknownLBAs.Add((ulong)i + sectorAddress);
break;
case false:
FailingLBAs.Add((ulong)i + sectorAddress);
break;
}
}
if (UnknownLBAs.Count > 0)
return null;
if (FailingLBAs.Count > 0)
return false;
return true;
}
public override bool? VerifyDiskImage()
{
return null;
}
#endregion
#region Private methods

View File

@@ -47,6 +47,7 @@ namespace DiscImageChef.ImagePlugins
class TeleDisk : ImagePlugin
{
#region Internal Structures
struct TD0Header
{
// "TD" or "td" depending on compression
@@ -188,11 +189,16 @@ namespace DiscImageChef.ImagePlugins
#endregion
#region Internal variables
TD0Header header;
TDCommentBlockHeader commentHeader;
byte[] commentBlock;
Dictionary<UInt32, byte[]> sectorsData; // LBA, data
Dictionary<UInt32, byte[]> sectorsData;
// LBA, data
UInt32 totalDiskSize;
bool ADiskCRCHasFailed;
List<UInt64> SectorsWhereCRCHasFailed;
#endregion
#region Accesible variables
@@ -231,6 +237,8 @@ namespace DiscImageChef.ImagePlugins
_imageInfo.driveManufacturer = null;
_imageInfo.driveModel = null;
_imageInfo.driveSerialNumber = null;
ADiskCRCHasFailed = false;
SectorsWhereCRCHasFailed = new List<UInt64>();
}
public override bool IdentifyImage(string imagePath)
@@ -346,8 +354,12 @@ namespace DiscImageChef.ImagePlugins
// This may deny legal images
// That would be much of a coincidence
if (header.crc != calculatedHeaderCRC && MainClass.isDebug)
if (header.crc != calculatedHeaderCRC)
{
ADiskCRCHasFailed = true;
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): Calculated CRC does not coincide with stored one.");
}
if (header.sequence != 0x00)
return false;
@@ -404,6 +416,8 @@ namespace DiscImageChef.ImagePlugins
Console.WriteLine("DEBUG (TeleDisk plugin): \tcommentheader.second = {0}", commentHeader.second);
}
ADiskCRCHasFailed |= cmtcrc != commentHeader.crc;
for (int i = 0; i < commentBlock.Length; i++)
{
// Replace NULLs, used by TeleDisk as newline markers, with UNIX newline marker
@@ -468,6 +482,8 @@ namespace DiscImageChef.ImagePlugins
Console.WriteLine("DEBUG (TeleDisk plugin): \tTrack header CRC: 0x{0:X2} (calculated 0x{1:X2})\t", TDTrack.crc, TDTrackCalculatedCRC);
}
ADiskCRCHasFailed |= TDTrackCalculatedCRC != TDTrack.crc;
if (TDTrack.sectors == 0xFF) // End of disk image
{
if (MainClass.isDebug)
@@ -529,6 +545,17 @@ namespace DiscImageChef.ImagePlugins
}
decodedData = DecodeTeleDiskData(TDSector.sectorSize, TDData.dataEncoding, data);
byte TDSectorCalculatedCRC = (byte)(TeleDiskCRC(0, decodedData) & 0xFF);
if (TDSectorCalculatedCRC != TDSector.crc)
{
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): Sector LBA {0} calculated CRC 0x{1:X2} differs from stored CRC 0x{2:X2}", LBA, TDSectorCalculatedCRC, TDSector.crc);
if ((TDSector.flags & FlagsSectorNoID) != FlagsSectorNoID)
if (!sectorsData.ContainsKey(LBA) && (TDSector.flags & FlagsSectorDuplicate) != FlagsSectorDuplicate)
SectorsWhereCRCHasFailed.Add((UInt64)LBA);
}
}
else
{
@@ -713,7 +740,46 @@ namespace DiscImageChef.ImagePlugins
return _imageInfo.diskType;
}
public override bool? VerifySector(UInt64 sectorAddress)
{
return !SectorsWhereCRCHasFailed.Contains(sectorAddress);
}
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
{
return null;
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
if (SectorsWhereCRCHasFailed.Contains(sectorAddress))
FailingLBAs.Add(sectorAddress);
return FailingLBAs.Count <= 0;
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
UnknownLBAs.Add(i);
return null;
}
public override bool? VerifyDiskImage()
{
return ADiskCRCHasFailed;
}
#region Private methods
static UInt16 TeleDiskCRC(UInt16 crc, byte[] buffer)
{
int counter = 0;
@@ -845,7 +911,7 @@ namespace DiscImageChef.ImagePlugins
return decodedData;
}
private DiskType DecodeTeleDiskDiskType()
DiskType DecodeTeleDiskDiskType()
{
switch (header.driveType)
{
@@ -1024,6 +1090,7 @@ namespace DiscImageChef.ImagePlugins
}
}
#endregion
#region Unsupported features

View File

@@ -46,8 +46,10 @@ namespace DiscImageChef.ImagePlugins
class ZZZRawImage : ImagePlugin
{
#region Internal variables
string rawImagePath;
bool differentTrackZeroSize;
#endregion
#region Accesible variables
@@ -356,7 +358,45 @@ namespace DiscImageChef.ImagePlugins
return _imageInfo.diskType;
}
public override bool? VerifySector(UInt64 sectorAddress)
{
return null;
}
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
{
return null;
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
UnknownLBAs.Add(i);
return null;
}
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
{
FailingLBAs = new List<UInt64>();
UnknownLBAs = new List<UInt64>();
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
UnknownLBAs.Add(i);
return null;
}
public override bool? VerifyDiskImage()
{
return null;
}
#region Private methods
private DiskType CalculateDiskType()
{
if (_imageInfo.sectorSize == 2048)
@@ -492,6 +532,7 @@ namespace DiscImageChef.ImagePlugins
}
}
}
#endregion
#region Unsupported features

View File

@@ -41,6 +41,6 @@
</Package>
</Packages>
</Packages>
<ReleaseVersion>2.0</ReleaseVersion>
<ReleaseVersion>2.1</ReleaseVersion>
</PropertyGroup>
</Project>

View File

@@ -1,4 +1,4 @@
DiscImageChef v2.00
DiscImageChef v2.10
===================
Disc Image Chef (because "swiss-army-knife" is used too much)
@@ -23,9 +23,9 @@ Features
* Identifies HFS, HFS+, MFS, BeFS, ext/2/3/4, FAT12/16/32, FFS/UFS/UFS2, HPFS, ISO9660, LisaFS, MinixFS, NTFS, ODS11, Opera, PCEngine, SolarFS, System V and UnixWare boot filesystem.
* Analyzes a disk image getting information about the disk itself and analyzes partitions and filesystems inside them
* Can compare two disk images, even different formats, for different sectors and/or metadata
* Can verify sectors or disk images if supported by the underlying format (well, it will be able to in version 2.1)
* Can verify sectors or disk images if supported by the underlying format
* Can checksum the disks (and if optical disc, separate tracks) user-data (tags and metadata coming soon)
* Supports CRC32 and CRC64 cyclic redundance checksums as well as MD5, RMD160, SHA1, SHA256, SHA384 and SHA512 hashes.
* Supports CRC16, CRC32 and CRC64 cyclic redundance checksums as well as MD5, RMD160, SHA1, SHA256, SHA384 and SHA512 hashes.
Changelog
=========

3
TODO
View File

@@ -74,9 +74,6 @@ Image comparison:
--- Offer the option to see differing values
--- Optimize and multithread
Image verification:
--- Implement verification on image plugins to implement this verb
Checksums:
--- Implement SpamSum fuzzy hashing (aka ssdeep)