mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add option to verify SwitchFS and SD cards
This commit is contained in:
parent
e21c384a9c
commit
6213111af9
4 changed files with 93 additions and 11 deletions
|
@ -78,8 +78,6 @@ namespace LibHac
|
|||
int bytesToRead = (int)Math.Min(CurrentEntry.OffsetEnd - Position, count);
|
||||
int bytesRead = base.Read(buffer, outPos, bytesToRead);
|
||||
|
||||
if (bytesRead == 0) break;
|
||||
|
||||
outPos += bytesRead;
|
||||
totalBytesRead += bytesRead;
|
||||
count -= bytesRead;
|
||||
|
@ -89,6 +87,10 @@ namespace LibHac
|
|||
CurrentEntry = CurrentEntry.Next;
|
||||
UpdateCounterSubsection(CurrentEntry.Counter);
|
||||
}
|
||||
else if (bytesRead == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return totalBytesRead;
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace LibHac
|
|||
{
|
||||
if (validities[i] == Validity.Unchecked)
|
||||
{
|
||||
levelStream.Position = levelStream.SectorSize * i;
|
||||
levelStream.Position = (long)levelStream.SectorSize * i;
|
||||
levelStream.Read(buffer, 0, buffer.Length, IntegrityCheckLevel.IgnoreOnInvalid);
|
||||
}
|
||||
|
||||
|
|
|
@ -478,33 +478,52 @@ namespace LibHac
|
|||
}
|
||||
}
|
||||
|
||||
public static void VerifySection(this Nca nca, int index, IProgressReport logger = null)
|
||||
public static Validity VerifyNca(this Nca nca, IProgressReport logger = null, bool quiet = false)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (nca.Sections[i] != null)
|
||||
{
|
||||
Validity sectionValidity = VerifySection(nca, i, logger, quiet);
|
||||
|
||||
if (sectionValidity == Validity.Invalid) return Validity.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
return Validity.Valid;
|
||||
}
|
||||
|
||||
public static Validity VerifySection(this Nca nca, int index, IProgressReport logger = null, bool quiet = false)
|
||||
{
|
||||
if (nca.Sections[index] == null) throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
NcaSection sect = nca.Sections[index];
|
||||
NcaHashType hashType = sect.Header.HashType;
|
||||
if (hashType != NcaHashType.Sha256 && hashType != NcaHashType.Ivfc) return;
|
||||
if (hashType != NcaHashType.Sha256 && hashType != NcaHashType.Ivfc) return Validity.Unchecked;
|
||||
|
||||
HierarchicalIntegrityVerificationStream stream = nca.OpenHashedSection(index, IntegrityCheckLevel.IgnoreOnInvalid);
|
||||
if (stream == null) return;
|
||||
if (stream == null) return Validity.Unchecked;
|
||||
|
||||
logger?.LogMessage($"Verifying section {index}...");
|
||||
if (!quiet) logger?.LogMessage($"Verifying section {index}...");
|
||||
|
||||
for (int i = 0; i < stream.Levels.Length - 1; i++)
|
||||
{
|
||||
logger?.LogMessage($" Verifying Hash Level {i}...");
|
||||
Validity result = stream.ValidateLevel(i, true, logger);
|
||||
if (!quiet) logger?.LogMessage($" Verifying Hash Level {i}...");
|
||||
Validity levelValidity = stream.ValidateLevel(i, true, logger);
|
||||
|
||||
if (hashType == NcaHashType.Ivfc)
|
||||
{
|
||||
sect.Header.IvfcInfo.LevelHeaders[i].HashValidity = result;
|
||||
sect.Header.IvfcInfo.LevelHeaders[i].HashValidity = levelValidity;
|
||||
}
|
||||
else if (hashType == NcaHashType.Sha256 && i == stream.Levels.Length - 2)
|
||||
{
|
||||
sect.Header.Sha256Info.HashValidity = result;
|
||||
sect.Header.Sha256Info.HashValidity = levelValidity;
|
||||
}
|
||||
|
||||
if (levelValidity == Validity.Invalid) return Validity.Invalid;
|
||||
}
|
||||
|
||||
return Validity.Valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,67 @@ namespace hactoolnet
|
|||
{
|
||||
ExportSdSaves(ctx, switchFs);
|
||||
}
|
||||
|
||||
if (ctx.Options.Validate)
|
||||
{
|
||||
ValidateSwitchFs(ctx, switchFs);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateSwitchFs(Context ctx, SwitchFs switchFs)
|
||||
{
|
||||
if (ctx.Options.TitleId != 0)
|
||||
{
|
||||
ulong id = ctx.Options.TitleId;
|
||||
|
||||
if (!switchFs.Titles.TryGetValue(id, out Title title))
|
||||
{
|
||||
ctx.Logger.LogMessage($"Could not find title {id:X16}");
|
||||
return;
|
||||
}
|
||||
|
||||
ValidateTitle(ctx, title, "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Application app in switchFs.Applications.Values)
|
||||
{
|
||||
ctx.Logger.LogMessage($"Checking {app.Name}...");
|
||||
|
||||
Title mainTitle = app.Patch ?? app.Main;
|
||||
|
||||
if (mainTitle != null)
|
||||
{
|
||||
ValidateTitle(ctx, mainTitle, "Main title");
|
||||
}
|
||||
|
||||
foreach (Title title in app.AddOnContent)
|
||||
{
|
||||
ValidateTitle(ctx, title, "Add-on content");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateTitle(Context ctx, Title title, string caption)
|
||||
{
|
||||
try
|
||||
{
|
||||
ctx.Logger.LogMessage($" {caption} {title.Id:x16}");
|
||||
|
||||
foreach (Nca nca in title.Ncas)
|
||||
{
|
||||
ctx.Logger.LogMessage($" {nca.Header.ContentType.ToString()}");
|
||||
|
||||
Validity validity = nca.VerifyNca(ctx.Logger, true);
|
||||
|
||||
ctx.Logger.LogMessage($" {validity.ToString()}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ctx.Logger.LogMessage($"Error processing title {title.Id:x16}:\n{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveTitle(Context ctx, SwitchFs switchFs)
|
||||
|
|
Loading…
Reference in a new issue