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 GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = DiscImageChef\DiscImageChef.csproj StartupItem = DiscImageChef\DiscImageChef.csproj
description = The Disc Image Chef. description = The Disc Image Chef.
version = 2.0 version = 2.1
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -54,7 +54,7 @@ using System.Reflection;
// The form "{Major}.{Minor}.*" will automatically update the build and revision, // The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the 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, // The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.

View File

@@ -36,6 +36,8 @@ Copyright (C) 2011-2014 Claunia.com
****************************************************************************/ ****************************************************************************/
//$Id$ //$Id$
using System; using System;
using DiscImageChef.ImagePlugins;
using System.Collections.Generic;
namespace DiscImageChef.Commands namespace DiscImageChef.Commands
{ {
@@ -51,7 +53,211 @@ namespace DiscImageChef.Commands
Console.WriteLine("--verify-disc={0}", options.VerifyDisc); Console.WriteLine("--verify-disc={0}", options.VerifyDisc);
Console.WriteLine("--verify-sectors={0}", options.VerifySectors); 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> <RootNamespace>DiscImageChef</RootNamespace>
<AssemblyName>DiscImageChef</AssemblyName> <AssemblyName>DiscImageChef</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<ReleaseVersion>2.0</ReleaseVersion> <ReleaseVersion>2.1</ReleaseVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>True</DebugSymbols> <DebugSymbols>True</DebugSymbols>

View File

@@ -1251,70 +1251,68 @@ namespace DiscImageChef.ImagePlugins
_imageInfo.diskBarcode = discimage.barcode; _imageInfo.diskBarcode = discimage.barcode;
_imageInfo.diskType = discimage.disktype; _imageInfo.diskType = discimage.disktype;
foreach(CDRWinTrack track in discimage.tracks) foreach (CDRWinTrack track in discimage.tracks)
{ {
switch(track.tracktype) switch (track.tracktype)
{ {
case CDRWinTrackTypeAudio: case CDRWinTrackTypeAudio:
{ {
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC))
_imageInfo.readableSectorTags.Add(SectorTagType.CDTrackISRC); _imageInfo.readableSectorTags.Add(SectorTagType.CDTrackISRC);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackFlags)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackFlags))
_imageInfo.readableSectorTags.Add(SectorTagType.CDTrackFlags); _imageInfo.readableSectorTags.Add(SectorTagType.CDTrackFlags);
break; break;
} }
case CDRWinTrackTypeCDG: case CDRWinTrackTypeCDG:
{ {
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC))
_imageInfo.readableSectorTags.Add(SectorTagType.CDTrackISRC); _imageInfo.readableSectorTags.Add(SectorTagType.CDTrackISRC);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackFlags)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackFlags))
_imageInfo.readableSectorTags.Add(SectorTagType.CDTrackFlags); _imageInfo.readableSectorTags.Add(SectorTagType.CDTrackFlags);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubchannel)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubchannel))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubchannel); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubchannel);
break; break;
} }
case CDRWinTrackTypeMode2Formless: case CDRWinTrackTypeMode2Formless:
case CDRWinTrackTypeCDI: case CDRWinTrackTypeCDI:
{ {
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
break; break;
} }
case CDRWinTrackTypeMode2Raw: case CDRWinTrackTypeMode2Raw:
case CDRWinTrackTypeCDIRaw: case CDRWinTrackTypeCDIRaw:
{ {
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
break; break;
} }
case CDRWinTrackTypeMode1Raw: case CDRWinTrackTypeMode1Raw:
{ {
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_P)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_P))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_P); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_P);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_Q)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_Q))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_Q); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_Q);
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC)) if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC); _imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
break; break;
} }
default:
break;
} }
} }
@@ -1928,6 +1926,8 @@ namespace DiscImageChef.ImagePlugins
{ {
List<Track> tracks = new List<Track>(); List<Track> tracks = new List<Track>();
UInt64 previousStartSector = 0;
foreach (CDRWinTrack cdr_track in discimage.tracks) foreach (CDRWinTrack cdr_track in discimage.tracks)
{ {
Track _track = new Track(); Track _track = new Track();
@@ -1936,6 +1936,7 @@ namespace DiscImageChef.ImagePlugins
_track.TrackDescription = cdr_track.title; _track.TrackDescription = cdr_track.title;
if (!cdr_track.indexes.TryGetValue(0, out _track.TrackStartSector)) if (!cdr_track.indexes.TryGetValue(0, out _track.TrackStartSector))
cdr_track.indexes.TryGetValue(1, out _track.TrackStartSector); cdr_track.indexes.TryGetValue(1, out _track.TrackStartSector);
_track.TrackStartSector += previousStartSector;
_track.TrackEndSector = _track.TrackStartSector + cdr_track.sectors - 1; _track.TrackEndSector = _track.TrackStartSector + cdr_track.sectors - 1;
_track.TrackPregap = cdr_track.pregap; _track.TrackPregap = cdr_track.pregap;
_track.TrackSession = cdr_track.session; _track.TrackSession = cdr_track.session;
@@ -1943,6 +1944,7 @@ namespace DiscImageChef.ImagePlugins
_track.TrackType = CDRWinTrackTypeToTrackType(cdr_track.tracktype); _track.TrackType = CDRWinTrackTypeToTrackType(cdr_track.tracktype);
tracks.Add(_track); tracks.Add(_track);
previousStartSector = _track.TrackEndSector + 1;
} }
return tracks; return tracks;
@@ -1989,6 +1991,85 @@ namespace DiscImageChef.ImagePlugins
return discimage.sessions; 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 #endregion
#region Private methods #region Private methods
@@ -2168,6 +2249,7 @@ namespace DiscImageChef.ImagePlugins
{ {
return _imageInfo.imageCreator; return _imageInfo.imageCreator;
} }
#endregion #endregion
} }
} }

View File

@@ -373,6 +373,83 @@ namespace DiscImageChef.ImagePlugins
return true; 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() public override bool ImageHasPartitions()
{ {
return _imageInfo.imageHasPartitions; return _imageInfo.imageHasPartitions;
@@ -640,6 +717,25 @@ namespace DiscImageChef.ImagePlugins
} }
#endregion Unsupported features #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> /// <param name="tag">Tag type to read.</param>
public abstract byte[] ReadDiskTag(DiskTagType tag); public abstract byte[] ReadDiskTag(DiskTagType tag);
// Gets a disk tag
/// <summary> /// <summary>
/// Reads a sector's user data. /// Reads a sector's user data.
/// </summary> /// </summary>
@@ -370,7 +369,50 @@ namespace DiscImageChef.ImagePlugins
/// </summary> /// </summary>
/// <returns>The sessions.</returns> /// <returns>The sessions.</returns>
public abstract List<Session> GetSessions(); 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 // CD flags bitmask
@@ -719,8 +761,9 @@ namespace DiscImageChef.ImagePlugins
FDFORMAT_35_HD, FDFORMAT_35_HD,
// Generic hard disks // Generic hard disks
GENERIC_HDD GENERIC_HDD}
};
;
/// <summary> /// <summary>
/// Track (as partitioning element) types. /// Track (as partitioning element) types.
@@ -738,8 +781,9 @@ namespace DiscImageChef.ImagePlugins
/// <summary>Data track, compact disc mode 2, form 1</summary> /// <summary>Data track, compact disc mode 2, form 1</summary>
CDMode2Form1, CDMode2Form1,
/// <summary>Data track, compact disc mode 2, form 2</summary> /// <summary>Data track, compact disc mode 2, form 2</summary>
CDMode2Form2 CDMode2Form2}
};
;
/// <summary> /// <summary>
/// Track defining structure. /// Track defining structure.
@@ -811,8 +855,9 @@ namespace DiscImageChef.ImagePlugins
/// <summary>CD track flags, 1 byte</summary> /// <summary>CD track flags, 1 byte</summary>
CDTrackFlags, CDTrackFlags,
/// <summary>DVD sector copyright information</summary> /// <summary>DVD sector copyright information</summary>
DVD_CMI DVD_CMI}
};
;
/// <summary> /// <summary>
/// Metadata present for each disk. /// Metadata present for each disk.
@@ -834,8 +879,9 @@ namespace DiscImageChef.ImagePlugins
/// <summary>DVD Copyright Management Information</summary> /// <summary>DVD Copyright Management Information</summary>
DVD_CMI, DVD_CMI,
/// <summary>DVD Disc Manufacturer Information</summary> /// <summary>DVD Disc Manufacturer Information</summary>
DVD_DMI DVD_DMI}
};
;
/// <summary> /// <summary>
/// Feature is supported by image but not implemented yet. /// Feature is supported by image but not implemented yet.

View File

@@ -2010,7 +2010,7 @@ namespace DiscImageChef.ImagePlugins
} }
break; break;
} }
// TODO // TODO
case DAOMode.DataM2RawSub: case DAOMode.DataM2RawSub:
throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented"); throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
case DAOMode.DataRawSub: case DAOMode.DataRawSub:
@@ -2291,6 +2291,85 @@ namespace DiscImageChef.ImagePlugins
return imageSessions; 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 #endregion
#region Private methods #region Private methods

View File

@@ -47,6 +47,7 @@ namespace DiscImageChef.ImagePlugins
class TeleDisk : ImagePlugin class TeleDisk : ImagePlugin
{ {
#region Internal Structures #region Internal Structures
struct TD0Header struct TD0Header
{ {
// "TD" or "td" depending on compression // "TD" or "td" depending on compression
@@ -122,7 +123,7 @@ namespace DiscImageChef.ImagePlugins
} }
#endregion #endregion
#region Internal Constants #region Internal Constants
// "TD" as little endian uint. // "TD" as little endian uint.
@@ -186,13 +187,18 @@ namespace DiscImageChef.ImagePlugins
const byte dataBlockRLE = 0x02; const byte dataBlockRLE = 0x02;
#endregion #endregion
#region Internal variables #region Internal variables
TD0Header header; TD0Header header;
TDCommentBlockHeader commentHeader; TDCommentBlockHeader commentHeader;
byte[] commentBlock; byte[] commentBlock;
Dictionary<UInt32, byte[]> sectorsData; // LBA, data Dictionary<UInt32, byte[]> sectorsData;
// LBA, data
UInt32 totalDiskSize; UInt32 totalDiskSize;
bool ADiskCRCHasFailed;
List<UInt64> SectorsWhereCRCHasFailed;
#endregion #endregion
#region Accesible variables #region Accesible variables
@@ -231,6 +237,8 @@ namespace DiscImageChef.ImagePlugins
_imageInfo.driveManufacturer = null; _imageInfo.driveManufacturer = null;
_imageInfo.driveModel = null; _imageInfo.driveModel = null;
_imageInfo.driveSerialNumber = null; _imageInfo.driveSerialNumber = null;
ADiskCRCHasFailed = false;
SectorsWhereCRCHasFailed = new List<UInt64>();
} }
public override bool IdentifyImage(string imagePath) public override bool IdentifyImage(string imagePath)
@@ -295,7 +303,7 @@ namespace DiscImageChef.ImagePlugins
return true; return true;
} }
public override bool OpenImage(string imagePath) public override bool OpenImage(string imagePath)
{ {
header = new TD0Header(); header = new TD0Header();
@@ -346,8 +354,12 @@ namespace DiscImageChef.ImagePlugins
// This may deny legal images // This may deny legal images
// That would be much of a coincidence // That would be much of a coincidence
if (header.crc != calculatedHeaderCRC && MainClass.isDebug) if (header.crc != calculatedHeaderCRC)
Console.WriteLine("DEBUG (TeleDisk plugin): Calculated CRC does not coincide with stored one."); {
ADiskCRCHasFailed = true;
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): Calculated CRC does not coincide with stored one.");
}
if (header.sequence != 0x00) if (header.sequence != 0x00)
return false; return false;
@@ -390,7 +402,7 @@ namespace DiscImageChef.ImagePlugins
UInt16 cmtcrc = TeleDiskCRC(0, commentBlockForCRC); UInt16 cmtcrc = TeleDiskCRC(0, commentBlockForCRC);
if(MainClass.isDebug) if (MainClass.isDebug)
{ {
Console.WriteLine("DEBUG (TeleDisk plugin): Comment header"); Console.WriteLine("DEBUG (TeleDisk plugin): Comment header");
Console.WriteLine("DEBUG (TeleDisk plugin): \tcommentheader.crc = 0x{0:X4}", commentHeader.crc); Console.WriteLine("DEBUG (TeleDisk plugin): \tcommentheader.crc = 0x{0:X4}", commentHeader.crc);
@@ -404,23 +416,25 @@ namespace DiscImageChef.ImagePlugins
Console.WriteLine("DEBUG (TeleDisk plugin): \tcommentheader.second = {0}", commentHeader.second); Console.WriteLine("DEBUG (TeleDisk plugin): \tcommentheader.second = {0}", commentHeader.second);
} }
for(int i=0;i<commentBlock.Length;i++) ADiskCRCHasFailed |= cmtcrc != commentHeader.crc;
for (int i = 0; i < commentBlock.Length; i++)
{ {
// Replace NULLs, used by TeleDisk as newline markers, with UNIX newline marker // Replace NULLs, used by TeleDisk as newline markers, with UNIX newline marker
if(commentBlock[i]==0x00) if (commentBlock[i] == 0x00)
commentBlock[i]=0x0A; commentBlock[i] = 0x0A;
} }
_imageInfo.imageComments = System.Text.Encoding.ASCII.GetString(commentBlock); _imageInfo.imageComments = System.Text.Encoding.ASCII.GetString(commentBlock);
if(MainClass.isDebug) if (MainClass.isDebug)
{ {
Console.WriteLine("DEBUG (TeleDisk plugin): Comment"); Console.WriteLine("DEBUG (TeleDisk plugin): Comment");
Console.WriteLine("DEBUG (TeleDisk plugin): {0}", _imageInfo.imageComments); Console.WriteLine("DEBUG (TeleDisk plugin): {0}", _imageInfo.imageComments);
} }
_imageInfo.imageCreationTime = new DateTime(commentHeader.year+1900, commentHeader.month+1, commentHeader.day, _imageInfo.imageCreationTime = new DateTime(commentHeader.year + 1900, commentHeader.month + 1, commentHeader.day,
commentHeader.hour, commentHeader.minute, commentHeader.second, DateTimeKind.Unspecified); commentHeader.hour, commentHeader.minute, commentHeader.second, DateTimeKind.Unspecified);
} }
FileInfo fi = new FileInfo(imagePath); FileInfo fi = new FileInfo(imagePath);
@@ -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); 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 (TDTrack.sectors == 0xFF) // End of disk image
{ {
if (MainClass.isDebug) if (MainClass.isDebug)
@@ -529,6 +545,17 @@ namespace DiscImageChef.ImagePlugins
} }
decodedData = DecodeTeleDiskData(TDSector.sectorSize, TDData.dataEncoding, data); 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 else
{ {
@@ -598,32 +625,32 @@ namespace DiscImageChef.ImagePlugins
stream.Close(); stream.Close();
return true; return true;
} }
public override bool ImageHasPartitions() public override bool ImageHasPartitions()
{ {
return _imageInfo.imageHasPartitions; return _imageInfo.imageHasPartitions;
} }
public override UInt64 GetImageSize() public override UInt64 GetImageSize()
{ {
return _imageInfo.imageSize; return _imageInfo.imageSize;
} }
public override UInt64 GetSectors() public override UInt64 GetSectors()
{ {
return _imageInfo.sectors; return _imageInfo.sectors;
} }
public override UInt32 GetSectorSize() public override UInt32 GetSectorSize()
{ {
return _imageInfo.sectorSize; return _imageInfo.sectorSize;
} }
public override byte[] ReadSector(UInt64 sectorAddress) public override byte[] ReadSector(UInt64 sectorAddress)
{ {
return ReadSectors(sectorAddress, 1); return ReadSectors(sectorAddress, 1);
} }
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length) public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
{ {
if (sectorAddress > (ulong)sectorsData.Count - 1) if (sectorAddress > (ulong)sectorsData.Count - 1)
@@ -643,7 +670,7 @@ namespace DiscImageChef.ImagePlugins
byte[] sector; byte[] sector;
if(!sectorsData.TryGetValue((uint)i, out sector)) if (!sectorsData.TryGetValue((uint)i, out sector))
throw new ImageNotSupportedException(String.Format("Error reading sector {0}", i)); throw new ImageNotSupportedException(String.Format("Error reading sector {0}", i));
if (first) if (first)
@@ -662,58 +689,97 @@ namespace DiscImageChef.ImagePlugins
return data; return data;
} }
public override byte[] ReadSectorLong(UInt64 sectorAddress) public override byte[] ReadSectorLong(UInt64 sectorAddress)
{ {
return ReadSectors(sectorAddress, 1); return ReadSectors(sectorAddress, 1);
} }
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length) public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length)
{ {
return ReadSectors(sectorAddress, length); return ReadSectors(sectorAddress, length);
} }
public override string GetImageFormat() public override string GetImageFormat()
{ {
return "Sydex TeleDisk"; return "Sydex TeleDisk";
} }
public override string GetImageVersion() public override string GetImageVersion()
{ {
return _imageInfo.imageVersion; return _imageInfo.imageVersion;
} }
public override string GetImageApplication() public override string GetImageApplication()
{ {
return _imageInfo.imageApplication; return _imageInfo.imageApplication;
} }
public override string GetImageApplicationVersion() public override string GetImageApplicationVersion()
{ {
return _imageInfo.imageApplicationVersion; return _imageInfo.imageApplicationVersion;
} }
public override DateTime GetImageCreationTime() public override DateTime GetImageCreationTime()
{ {
return _imageInfo.imageCreationTime; return _imageInfo.imageCreationTime;
} }
public override DateTime GetImageLastModificationTime() public override DateTime GetImageLastModificationTime()
{ {
return _imageInfo.imageLastModificationTime; return _imageInfo.imageLastModificationTime;
} }
public override string GetImageName() public override string GetImageName()
{ {
return _imageInfo.imageName; return _imageInfo.imageName;
} }
public override DiskType GetDiskType() public override DiskType GetDiskType()
{ {
return _imageInfo.diskType; 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 #region Private methods
static UInt16 TeleDiskCRC(UInt16 crc, byte[] buffer) static UInt16 TeleDiskCRC(UInt16 crc, byte[] buffer)
{ {
int counter = 0; int counter = 0;
@@ -782,7 +848,7 @@ namespace DiscImageChef.ImagePlugins
repeatNumber = BitConverter.ToUInt16(encodedData, ins); repeatNumber = BitConverter.ToUInt16(encodedData, ins);
Array.Copy(encodedData, ins + 2, repeatValue, 0, 2); Array.Copy(encodedData, ins + 2, repeatValue, 0, 2);
byte[] decodedPiece = new byte[repeatNumber*2]; byte[] decodedPiece = new byte[repeatNumber * 2];
ArrayHelpers.ArrayFill(decodedPiece, repeatValue); ArrayHelpers.ArrayFill(decodedPiece, repeatValue);
Array.Copy(decodedPiece, 0, decodedData, outs, decodedPiece.Length); Array.Copy(decodedPiece, 0, decodedData, outs, decodedPiece.Length);
ins += 4; ins += 4;
@@ -845,7 +911,7 @@ namespace DiscImageChef.ImagePlugins
return decodedData; return decodedData;
} }
private DiskType DecodeTeleDiskDiskType() DiskType DecodeTeleDiskDiskType()
{ {
switch (header.driveType) switch (header.driveType)
{ {
@@ -858,7 +924,7 @@ namespace DiscImageChef.ImagePlugins
case 163840: case 163840:
{ {
// Acorn disk uses 256 bytes/sector // Acorn disk uses 256 bytes/sector
if(_imageInfo.sectorSize == 256) if (_imageInfo.sectorSize == 256)
return DiskType.ACORN_525_SS_DD_40; return DiskType.ACORN_525_SS_DD_40;
else // DOS disks use 512 bytes/sector else // DOS disks use 512 bytes/sector
return DiskType.DOS_525_SS_DD_8; return DiskType.DOS_525_SS_DD_8;
@@ -866,7 +932,7 @@ namespace DiscImageChef.ImagePlugins
case 184320: case 184320:
{ {
// Atari disk uses 256 bytes/sector // Atari disk uses 256 bytes/sector
if(_imageInfo.sectorSize == 256) if (_imageInfo.sectorSize == 256)
return DiskType.ATARI_525_DD; return DiskType.ATARI_525_DD;
else // DOS disks use 512 bytes/sector else // DOS disks use 512 bytes/sector
return DiskType.DOS_525_SS_DD_9; return DiskType.DOS_525_SS_DD_9;
@@ -874,7 +940,7 @@ namespace DiscImageChef.ImagePlugins
case 327680: case 327680:
{ {
// Acorn disk uses 256 bytes/sector // Acorn disk uses 256 bytes/sector
if(_imageInfo.sectorSize == 256) if (_imageInfo.sectorSize == 256)
return DiskType.ACORN_525_SS_DD_80; return DiskType.ACORN_525_SS_DD_80;
else // DOS disks use 512 bytes/sector else // DOS disks use 512 bytes/sector
return DiskType.DOS_525_DS_DD_8; return DiskType.DOS_525_DS_DD_8;
@@ -994,7 +1060,7 @@ namespace DiscImageChef.ImagePlugins
case 512512: case 512512:
{ {
// DEC disk uses 256 bytes/sector // DEC disk uses 256 bytes/sector
if(_imageInfo.sectorSize == 256) if (_imageInfo.sectorSize == 256)
return DiskType.RX02; return DiskType.RX02;
else // ECMA disks use 128 bytes/sector else // ECMA disks use 128 bytes/sector
return DiskType.ECMA_59; return DiskType.ECMA_59;
@@ -1024,140 +1090,141 @@ namespace DiscImageChef.ImagePlugins
} }
} }
#endregion #endregion
#region Unsupported features #region Unsupported features
public override byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag) public override byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag) public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override byte[] ReadDiskTag(DiskTagType tag) public override byte[] ReadDiskTag(DiskTagType tag)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override string GetImageCreator() public override string GetImageCreator()
{ {
return _imageInfo.imageCreator; return _imageInfo.imageCreator;
} }
public override string GetImageComments() public override string GetImageComments()
{ {
return _imageInfo.imageComments; return _imageInfo.imageComments;
} }
public override string GetDiskManufacturer() public override string GetDiskManufacturer()
{ {
return _imageInfo.diskManufacturer; return _imageInfo.diskManufacturer;
} }
public override string GetDiskModel() public override string GetDiskModel()
{ {
return _imageInfo.diskModel; return _imageInfo.diskModel;
} }
public override string GetDiskSerialNumber() public override string GetDiskSerialNumber()
{ {
return _imageInfo.diskSerialNumber; return _imageInfo.diskSerialNumber;
} }
public override string GetDiskBarcode() public override string GetDiskBarcode()
{ {
return _imageInfo.diskBarcode; return _imageInfo.diskBarcode;
} }
public override string GetDiskPartNumber() public override string GetDiskPartNumber()
{ {
return _imageInfo.diskPartNumber; return _imageInfo.diskPartNumber;
} }
public override int GetDiskSequence() public override int GetDiskSequence()
{ {
return _imageInfo.diskSequence; return _imageInfo.diskSequence;
} }
public override int GetLastDiskSequence() public override int GetLastDiskSequence()
{ {
return _imageInfo.lastDiskSequence; return _imageInfo.lastDiskSequence;
} }
public override string GetDriveManufacturer() public override string GetDriveManufacturer()
{ {
return _imageInfo.driveManufacturer; return _imageInfo.driveManufacturer;
} }
public override string GetDriveModel() public override string GetDriveModel()
{ {
return _imageInfo.driveModel; return _imageInfo.driveModel;
} }
public override string GetDriveSerialNumber() public override string GetDriveSerialNumber()
{ {
return _imageInfo.driveSerialNumber; return _imageInfo.driveSerialNumber;
} }
public override List<PartPlugins.Partition> GetPartitions() public override List<PartPlugins.Partition> GetPartitions()
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override List<Track> GetTracks() public override List<Track> GetTracks()
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override List<Track> GetSessionTracks(Session session) public override List<Track> GetSessionTracks(Session session)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override List<Track> GetSessionTracks(UInt16 session) public override List<Track> GetSessionTracks(UInt16 session)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override List<Session> GetSessions() public override List<Session> GetSessions()
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override byte[] ReadSector(UInt64 sectorAddress, UInt32 track) public override byte[] ReadSector(UInt64 sectorAddress, UInt32 track)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag) public override byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track) public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag) public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track) public override byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track) public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
#endregion Unsupported features #endregion Unsupported features
} }
} }

View File

@@ -46,8 +46,10 @@ namespace DiscImageChef.ImagePlugins
class ZZZRawImage : ImagePlugin class ZZZRawImage : ImagePlugin
{ {
#region Internal variables #region Internal variables
string rawImagePath; string rawImagePath;
bool differentTrackZeroSize; bool differentTrackZeroSize;
#endregion #endregion
#region Accesible variables #region Accesible variables
@@ -356,7 +358,45 @@ namespace DiscImageChef.ImagePlugins
return _imageInfo.diskType; 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 #region Private methods
private DiskType CalculateDiskType() private DiskType CalculateDiskType()
{ {
if (_imageInfo.sectorSize == 2048) if (_imageInfo.sectorSize == 2048)
@@ -492,6 +532,7 @@ namespace DiscImageChef.ImagePlugins
} }
} }
} }
#endregion #endregion
#region Unsupported features #region Unsupported features

View File

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

View File

@@ -1,4 +1,4 @@
DiscImageChef v2.00 DiscImageChef v2.10
=================== ===================
Disc Image Chef (because "swiss-army-knife" is used too much) 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. * 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 * 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 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) * 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 Changelog
========= =========

3
TODO
View File

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