Cleanup
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
using LibIRD;
|
using LibIRD;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Enumeration;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace BuildIRD
|
namespace BuildIRD
|
||||||
|
|||||||
+3
-7
@@ -131,10 +131,6 @@ namespace LibIRD
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Helper Functions
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -150,7 +146,7 @@ namespace LibIRD
|
|||||||
byte[] header,
|
byte[] header,
|
||||||
byte[] footer,
|
byte[] footer,
|
||||||
byte[][] regionHashes,
|
byte[][] regionHashes,
|
||||||
ulong[] fileKeys,
|
long[] fileKeys,
|
||||||
byte[][] fileHashes,
|
byte[][] fileHashes,
|
||||||
ushort extraConfig,
|
ushort extraConfig,
|
||||||
ushort attachments,
|
ushort attachments,
|
||||||
@@ -535,11 +531,11 @@ namespace LibIRD
|
|||||||
|
|
||||||
// Read file hashes
|
// Read file hashes
|
||||||
uint fileCount = br.ReadUInt32();
|
uint fileCount = br.ReadUInt32();
|
||||||
ulong[] fileKeys = new ulong[fileCount];
|
long[] fileKeys = new long[fileCount];
|
||||||
byte[][] fileHashes = new byte[fileCount][];
|
byte[][] fileHashes = new byte[fileCount][];
|
||||||
for (int i = 0; i < fileCount; i++)
|
for (int i = 0; i < fileCount; i++)
|
||||||
{
|
{
|
||||||
fileKeys[i] = br.ReadUInt64();
|
fileKeys[i] = br.ReadInt64();
|
||||||
fileHashes[i] = br.ReadBytes(16);
|
fileHashes[i] = br.ReadBytes(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+95
-48
@@ -92,15 +92,15 @@ namespace LibIRD
|
|||||||
public byte[][] RegionHashes { get; private protected set; }
|
public byte[][] RegionHashes { get; private protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of decrypted files in the image
|
/// Number of files in the image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint FileCount { get; private protected set; }
|
public uint FileCount { get; private protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starting sector for each decrypted file
|
/// Starting sector for each file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks><see cref="FileCount"/> files, alternating with each <see cref="FileHashes"/> entry</remarks>
|
/// <remarks><see cref="FileCount"/> files, alternating with each <see cref="FileHashes"/> entry</remarks>
|
||||||
public ulong[] FileKeys { get; private protected set; }
|
public long[] FileKeys { get; private protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MD5 hashes for all decrypted files in the image
|
/// MD5 hashes for all decrypted files in the image
|
||||||
@@ -125,8 +125,15 @@ namespace LibIRD
|
|||||||
/// <remarks>Offset to use when reading the footer</remarks>
|
/// <remarks>Offset to use when reading the footer</remarks>
|
||||||
private long UpdateEnd { get; set; }
|
private long UpdateEnd { get; set; }
|
||||||
|
|
||||||
private long[] FileStart { get; set; }
|
/// <summary>
|
||||||
private long[] FileEnd { get; set; }
|
/// First sector of each region
|
||||||
|
/// </summary>
|
||||||
|
private long[] RegionStart { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Last sector of each region
|
||||||
|
/// </summary>
|
||||||
|
private long[] RegionEnd { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -143,7 +150,7 @@ namespace LibIRD
|
|||||||
byte[] header,
|
byte[] header,
|
||||||
byte[] footer,
|
byte[] footer,
|
||||||
byte[][] regionHashes,
|
byte[][] regionHashes,
|
||||||
ulong[] fileKeys,
|
long[] fileKeys,
|
||||||
byte[][] fileHashes)
|
byte[][] fileHashes)
|
||||||
{
|
{
|
||||||
TitleID = titleID;
|
TitleID = titleID;
|
||||||
@@ -212,29 +219,25 @@ namespace LibIRD
|
|||||||
// Read and compress the ISO footer
|
// Read and compress the ISO footer
|
||||||
GetFooter(fs);
|
GetFooter(fs);
|
||||||
|
|
||||||
// Recursively count all files in ISO to allocate arrays
|
// Process all regions on ISO
|
||||||
|
HashRegions(fs);
|
||||||
|
|
||||||
|
// TODO: Speed up program by hashing regions and files at the same time (read from filesystem only once)
|
||||||
|
|
||||||
|
// Recursively count all files in ISO to allocate file arrays
|
||||||
DiscDirectoryInfo rootDir = reader.GetDirectoryInfo("\\");
|
DiscDirectoryInfo rootDir = reader.GetDirectoryInfo("\\");
|
||||||
FileCount = 0;
|
FileCount = 0;
|
||||||
CountFiles(rootDir);
|
CountFiles(rootDir);
|
||||||
FileStart = new long[FileCount];
|
FileKeys = new long[FileCount];
|
||||||
FileEnd = new long[FileCount];
|
|
||||||
FileKeys = new ulong[FileCount];
|
|
||||||
FileHashes = new byte[FileCount][];
|
FileHashes = new byte[FileCount][];
|
||||||
|
|
||||||
// Determine file offsets and hashes
|
// Determine file offsets and hashes
|
||||||
uint fileCount = FileCount;
|
uint fileCount = FileCount;
|
||||||
FileCount = 0;
|
FileCount = 0;
|
||||||
GetFileExtents(rootDir, reader);
|
ProcessFiles(fs, reader, rootDir);
|
||||||
if (FileCount != fileCount)
|
if (FileCount != fileCount)
|
||||||
throw new InvalidFileSystemException("Unexpected ISO filesystem error: ");
|
throw new InvalidFileSystemException("Unexpected ISO filesystem error: ");
|
||||||
|
Array.Sort(FileKeys, FileHashes);
|
||||||
// Get MD5 hash for all regions and files on ISO
|
|
||||||
HashData(fs);
|
|
||||||
for (int i = 0; i < FileCount; i++)
|
|
||||||
{
|
|
||||||
FileKeys[i] = (ulong)FileStart[i];
|
|
||||||
FileHashes[i] = NullMD5;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -375,7 +378,7 @@ namespace LibIRD
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fs"></param>
|
/// <param name="fs"></param>
|
||||||
/// <exception cref="InvalidFileSystemException"></exception>
|
/// <exception cref="InvalidFileSystemException"></exception>
|
||||||
private void HashData(FileStream fs)
|
private void HashRegions(FileStream fs)
|
||||||
{
|
{
|
||||||
// Determine the number of unencryted regions
|
// Determine the number of unencryted regions
|
||||||
fs.Seek(0, SeekOrigin.Begin);
|
fs.Seek(0, SeekOrigin.Begin);
|
||||||
@@ -387,11 +390,11 @@ namespace LibIRD
|
|||||||
if (RegionCount <= 0)
|
if (RegionCount <= 0)
|
||||||
throw new InvalidFileSystemException("No regions detected in ISO");
|
throw new InvalidFileSystemException("No regions detected in ISO");
|
||||||
RegionHashes = new byte[RegionCount][];
|
RegionHashes = new byte[RegionCount][];
|
||||||
|
RegionStart = new long[RegionCount];
|
||||||
|
RegionEnd = new long[RegionCount];
|
||||||
|
|
||||||
// Determine the extent for each region
|
// Determine the extent for each region
|
||||||
byte[] regionSector = new byte[4];
|
byte[] regionSector = new byte[4];
|
||||||
long[] regionStart = new long[RegionCount];
|
|
||||||
long[] regionEnd = new long[RegionCount];
|
|
||||||
fs.Seek(8, SeekOrigin.Begin);
|
fs.Seek(8, SeekOrigin.Begin);
|
||||||
fs.Read(regionSector, 0, 4);
|
fs.Read(regionSector, 0, 4);
|
||||||
Array.Reverse(regionSector, 0, 4);
|
Array.Reverse(regionSector, 0, 4);
|
||||||
@@ -399,22 +402,22 @@ namespace LibIRD
|
|||||||
{
|
{
|
||||||
// End sector of previous region is start of this region
|
// End sector of previous region is start of this region
|
||||||
if (i % 2 == 1)
|
if (i % 2 == 1)
|
||||||
regionStart[i] = BitConverter.ToInt32(regionSector) + 1;
|
RegionStart[i] = BitConverter.ToInt32(regionSector) + 1;
|
||||||
else
|
else
|
||||||
regionStart[i] = BitConverter.ToInt32(regionSector);
|
RegionStart[i] = BitConverter.ToInt32(regionSector);
|
||||||
// Determine end sector offset of this region
|
// Determine end sector offset of this region
|
||||||
fs.Read(regionSector, 0, 4);
|
fs.Read(regionSector, 0, 4);
|
||||||
Array.Reverse(regionSector, 0, 4);
|
Array.Reverse(regionSector, 0, 4);
|
||||||
if (i % 2 == 1)
|
if (i % 2 == 1)
|
||||||
regionEnd[i] = BitConverter.ToInt32(regionSector) - 1;
|
RegionEnd[i] = BitConverter.ToInt32(regionSector) - 1;
|
||||||
else
|
else
|
||||||
regionEnd[i] = BitConverter.ToInt32(regionSector);
|
RegionEnd[i] = BitConverter.ToInt32(regionSector);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove header from first region
|
// Remove header from first region
|
||||||
regionStart[0] = FirstDataSector;
|
RegionStart[0] = FirstDataSector;
|
||||||
// Remove footer from last region
|
// Remove footer from last region
|
||||||
regionEnd[^1] = (UpdateEnd / SectorSize) - 1;
|
RegionEnd[^1] = (UpdateEnd / SectorSize) - 1;
|
||||||
|
|
||||||
// Determine MD5 hashes for each region
|
// Determine MD5 hashes for each region
|
||||||
using MD5 md5 = MD5.Create();
|
using MD5 md5 = MD5.Create();
|
||||||
@@ -422,11 +425,11 @@ namespace LibIRD
|
|||||||
for (int i = 0; i < RegionCount; i++)
|
for (int i = 0; i < RegionCount; i++)
|
||||||
{
|
{
|
||||||
// Start reading data from first sector of region
|
// Start reading data from first sector of region
|
||||||
fs.Seek(SectorSize * regionStart[i], SeekOrigin.Begin);
|
fs.Seek(SectorSize * RegionStart[i], SeekOrigin.Begin);
|
||||||
|
|
||||||
// Compute MD5 hash for just the region portion of the ISO file
|
// Compute MD5 hash for just the region portion of the ISO file
|
||||||
int numBytes;
|
int numBytes;
|
||||||
for (long j = regionStart[i]; j <= regionEnd[i]; j++)
|
for (long j = RegionStart[i]; j <= RegionEnd[i]; j++)
|
||||||
{
|
{
|
||||||
// Read one sector at a time
|
// Read one sector at a time
|
||||||
numBytes = fs.Read(buf, 0, buf.Length);
|
numBytes = fs.Read(buf, 0, buf.Length);
|
||||||
@@ -444,23 +447,11 @@ namespace LibIRD
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recursively determines file count
|
/// Determine and store hashes for all files and files within subdirectories recursively
|
||||||
/// </summary>
|
|
||||||
/// <param name="dir"></param>
|
|
||||||
private void CountFiles(DiscDirectoryInfo dir)
|
|
||||||
{
|
|
||||||
FileCount += (uint)dir.GetFiles().Length;
|
|
||||||
foreach (DiscDirectoryInfo dirInfo in dir.GetDirectories())
|
|
||||||
CountFiles(dirInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determine byte extents for all files and files within subdirectories recursively
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader"></param>
|
/// <param name="reader"></param>
|
||||||
/// <param name="dir"></param>
|
/// <param name="path"></param>
|
||||||
/// <exception cref="InvalidFileSystemException"></exception>
|
private void ProcessFiles(FileStream fs, CDReader reader, DiscDirectoryInfo dir)
|
||||||
private void GetFileExtents(DiscDirectoryInfo dir, CDReader reader)
|
|
||||||
{
|
{
|
||||||
// Process all files in current directory
|
// Process all files in current directory
|
||||||
foreach (DiscFileInfo fileInfo in dir.GetFiles())
|
foreach (DiscFileInfo fileInfo in dir.GetFiles())
|
||||||
@@ -472,18 +463,74 @@ namespace LibIRD
|
|||||||
throw new InvalidFileSystemException("Unexpected file extent in ISO filestream for " + filePath);
|
throw new InvalidFileSystemException("Unexpected file extent in ISO filestream for " + filePath);
|
||||||
if (fileExtents.Length > 1)
|
if (fileExtents.Length > 1)
|
||||||
throw new InvalidFileSystemException("Non-contiguous file detected");
|
throw new InvalidFileSystemException("Non-contiguous file detected");
|
||||||
FileStart[FileCount] = fileExtents[0].Start;
|
long firstByte = fileExtents[0].Start;
|
||||||
FileEnd[FileCount] = fileExtents[0].Length;
|
long fileLength = fileExtents[0].Length;
|
||||||
|
FileKeys[FileCount] = firstByte / 2048;
|
||||||
|
|
||||||
|
// Determine whether file is in encrypted or decrypted region
|
||||||
|
bool encrypted = false;
|
||||||
|
for (int i = RegionCount - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
if (RegionStart[i] <= firstByte / 2048)
|
||||||
|
{
|
||||||
|
encrypted = i % 2 == 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt file if encrypted
|
||||||
|
if (encrypted)
|
||||||
|
{
|
||||||
|
FileHashes[FileCount] = NullMD5;
|
||||||
|
FileCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start reading data from the beginning of the ISO file
|
||||||
|
fs.Seek(firstByte, SeekOrigin.Begin);
|
||||||
|
byte[] buf = new byte[SectorSize];
|
||||||
|
int numBytes;
|
||||||
|
// Read all data before the first data sector
|
||||||
|
MD5 md5 = MD5.Create();
|
||||||
|
for (long i = 0; i < (fileLength / SectorSize); i++)
|
||||||
|
{
|
||||||
|
numBytes = fs.Read(buf, 0, buf.Length);
|
||||||
|
// Check that an entire sector was read
|
||||||
|
if (numBytes < buf.Length)
|
||||||
|
throw new InvalidFileSystemException("Disc region ended unexpectedly");
|
||||||
|
md5.TransformBlock(buf, 0, numBytes, null, 0);
|
||||||
|
}
|
||||||
|
// Read remaining partial sector
|
||||||
|
if (fileLength % SectorSize != 0)
|
||||||
|
{
|
||||||
|
numBytes = fs.Read(buf, 0, (int)(fileLength % SectorSize));
|
||||||
|
md5.TransformBlock(buf, 0, numBytes, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalise and store MD5 hash
|
||||||
|
md5.TransformFinalBlock(buf, 0, 0);
|
||||||
|
FileHashes[FileCount] = md5.Hash;
|
||||||
FileCount++;
|
FileCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively process all subfolders of current directory
|
// Recursively process all subfolders of current directory
|
||||||
foreach (DiscDirectoryInfo dirInfo in dir.GetDirectories())
|
foreach (DiscDirectoryInfo dirInfo in dir.GetDirectories())
|
||||||
{
|
{
|
||||||
GetFileExtents(dirInfo, reader);
|
ProcessFiles(fs, reader, dirInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recursively determines file count
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dir"></param>
|
||||||
|
private void CountFiles(DiscDirectoryInfo dir)
|
||||||
|
{
|
||||||
|
FileCount += (uint)dir.GetFiles().Length;
|
||||||
|
foreach (DiscDirectoryInfo dirInfo in dir.GetDirectories())
|
||||||
|
CountFiles(dirInfo);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user