Decouple stream hashing from special file info

This commit is contained in:
Matt Nadareski
2020-09-17 23:07:49 -07:00
parent 3ad55d806b
commit 1e4afb3046
12 changed files with 93 additions and 79 deletions

View File

@@ -62,7 +62,7 @@ namespace SabreTools.Library.DatFiles
} }
catch (InvalidDataException ex) catch (InvalidDataException ex)
{ {
Globals.Logger.Warning($"Malformed line found in '{filename}' at line {svr.LineNumber}"); Globals.Logger.Error(ex, $"Malformed line found in '{filename}' at line {svr.LineNumber}");
if (throwOnError) throw ex; if (throwOnError) throw ex;
continue; continue;
} }

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text; using System.Text;
using SabreTools.Library.Data; using SabreTools.Library.Data;

View File

@@ -1867,7 +1867,7 @@ namespace SabreTools.Library.DatFiles
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error($"Error with file '{filename}': {ex}"); Globals.Logger.Error(ex, $"Error with file '{filename}'");
if (throwOnError) throw ex; if (throwOnError) throw ex;
} }
} }

View File

@@ -1,5 +1,5 @@
using System.IO; using System.IO;
using SabreTools.Library.DatFiles;
using SabreTools.Library.IO; using SabreTools.Library.IO;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
@@ -99,5 +99,35 @@ namespace SabreTools.Library.FileTypes
} }
#endregion #endregion
#region Manipulation
/// <summary>
/// Remove hashes from the metadata
/// </summary>
/// <param name="remove">Hash representing hashes to remove</param>
public void RemoveHashes(Hash remove)
{
if (remove.HasFlag(Hash.CRC))
CRC = null;
if (remove.HasFlag(Hash.MD5))
MD5 = null;
#if NET_FRAMEWORK
if (remove.HasFlag(Hash.RIPEMD160))
RIPEMD160 = null;
#endif
if (remove.HasFlag(Hash.SHA1))
SHA1 = null;
if (remove.HasFlag(Hash.SHA256))
SHA256 = null;
if (remove.HasFlag(Hash.SHA384))
SHA384 = null;
if (remove.HasFlag(Hash.SHA512))
SHA512 = null;
if (remove.HasFlag(Hash.SpamSum))
SpamSum = null;
}
#endregion
} }
} }

View File

@@ -233,7 +233,8 @@ namespace SabreTools.Library.FileTypes
var gz = new gZip(); var gz = new gZip();
ZipReturn ret = gz.ZipFileOpen(this.Filename); ZipReturn ret = gz.ZipFileOpen(this.Filename);
ret = gz.ZipFileOpenReadStream(0, out Stream gzstream, out ulong streamSize); ret = gz.ZipFileOpenReadStream(0, out Stream gzstream, out ulong streamSize);
BaseFile gzipEntryRom = gzstream.GetInfo(omitFromScan: omitFromScan, asFiles: TreatAsFiles.AaruFormats | TreatAsFiles.CHDs); BaseFile gzipEntryRom = gzstream.GetInfo();
gzipEntryRom.RemoveHashes(omitFromScan);
gzipEntryRom.Filename = gz.Filename(0); gzipEntryRom.Filename = gz.Filename(0);
gzipEntryRom.Parent = gamename; gzipEntryRom.Parent = gamename;
gzipEntryRom.Date = (date && gz.TimeStamp > 0 ? gz.TimeStamp.ToString() : null); gzipEntryRom.Date = (date && gz.TimeStamp > 0 ? gz.TimeStamp.ToString() : null);

View File

@@ -206,7 +206,8 @@ namespace SabreTools.Library.FileTypes
else else
{ {
Stream entryStream = entry.OpenEntryStream(); Stream entryStream = entry.OpenEntryStream();
BaseFile rarEntryRom = entryStream.GetInfo(size: entry.Size, omitFromScan: omitFromScan, asFiles: TreatAsFiles.AaruFormats | TreatAsFiles.CHDs); BaseFile rarEntryRom = entryStream.GetInfo(size: entry.Size);
rarEntryRom.RemoveHashes(omitFromScan);
rarEntryRom.Filename = entry.Key; rarEntryRom.Filename = entry.Key;
rarEntryRom.Parent = gamename; rarEntryRom.Parent = gamename;
rarEntryRom.Date = entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss"); rarEntryRom.Date = entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss");

View File

@@ -318,7 +318,8 @@ namespace SabreTools.Library.FileTypes
// Otherwise, use the stream directly // Otherwise, use the stream directly
else else
{ {
BaseFile zipEntryRom = readStream.GetInfo(size: (long)zf.UncompressedSize(i), omitFromScan: omitFromScan, keepReadOpen: true, asFiles: TreatAsFiles.AaruFormats | TreatAsFiles.CHDs); BaseFile zipEntryRom = readStream.GetInfo(size: (long)zf.UncompressedSize(i), keepReadOpen: true);
zipEntryRom.RemoveHashes(omitFromScan);
zipEntryRom.Filename = zf.Filename(i); zipEntryRom.Filename = zf.Filename(i);
zipEntryRom.Parent = gamename; zipEntryRom.Parent = gamename;
found.Add(zipEntryRom); found.Add(zipEntryRom);

View File

@@ -211,7 +211,8 @@ namespace SabreTools.Library.FileTypes
else else
{ {
Stream entryStream = entry.OpenEntryStream(); Stream entryStream = entry.OpenEntryStream();
BaseFile tarEntryRom = entryStream.GetInfo(size: entry.Size, omitFromScan: omitFromScan, asFiles: TreatAsFiles.AaruFormats | TreatAsFiles.CHDs); BaseFile tarEntryRom = entryStream.GetInfo(size: entry.Size);
tarEntryRom.RemoveHashes(omitFromScan);
tarEntryRom.Filename = entry.Key; tarEntryRom.Filename = entry.Key;
tarEntryRom.Parent = gamename; tarEntryRom.Parent = gamename;
tarEntryRom.Date = entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss"); tarEntryRom.Date = entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss");

View File

@@ -223,7 +223,8 @@ namespace SabreTools.Library.FileTypes
else else
{ {
var xzStream = new XZStream(File.OpenRead(this.Filename)); var xzStream = new XZStream(File.OpenRead(this.Filename));
BaseFile xzEntryRom = xzStream.GetInfo(omitFromScan: omitFromScan, asFiles: TreatAsFiles.AaruFormats | TreatAsFiles.CHDs); BaseFile xzEntryRom = xzStream.GetInfo();
xzEntryRom.RemoveHashes(omitFromScan);
xzEntryRom.Filename = gamename; xzEntryRom.Filename = gamename;
xzEntryRom.Parent = gamename; xzEntryRom.Parent = gamename;
_children.Add(xzEntryRom); _children.Add(xzEntryRom);

View File

@@ -321,7 +321,8 @@ namespace SabreTools.Library.FileTypes
// Otherwise, use the stream directly // Otherwise, use the stream directly
else else
{ {
BaseFile zipEntryRom = readStream.GetInfo(size: (long)zf.UncompressedSize(i), omitFromScan: omitFromScan, keepReadOpen: true, asFiles: TreatAsFiles.AaruFormats | TreatAsFiles.CHDs); BaseFile zipEntryRom = readStream.GetInfo(size: (long)zf.UncompressedSize(i), keepReadOpen: true);
zipEntryRom.RemoveHashes(omitFromScan);
zipEntryRom.Filename = zf.Filename(i); zipEntryRom.Filename = zf.Filename(i);
zipEntryRom.Parent = gamename; zipEntryRom.Parent = gamename;
string convertedDate = zf.LastModified(i).ToString("yyyy/MM/dd hh:mm:ss"); string convertedDate = zf.LastModified(i).ToString("yyyy/MM/dd hh:mm:ss");

View File

@@ -350,6 +350,10 @@ namespace SabreTools.Library.IO
if (!File.Exists(input)) if (!File.Exists(input))
return null; return null;
// Get input information
var fileType = input.GetFileType();
var inputStream = TryOpenRead(input);
// Get the information from the file stream // Get the information from the file stream
BaseFile baseFile; BaseFile baseFile;
if (header != null) if (header != null)
@@ -359,30 +363,49 @@ namespace SabreTools.Library.IO
// If there's a match, get the new information from the stream // If there's a match, get the new information from the stream
if (rule.Tests != null && rule.Tests.Count != 0) if (rule.Tests != null && rule.Tests.Count != 0)
{ {
// Create the input and output streams // Create the output stream
MemoryStream outputStream = new MemoryStream(); MemoryStream outputStream = new MemoryStream();
FileStream inputStream = TryOpenRead(input);
// Transform the stream and get the information from it // Transform the stream and get the information from it
rule.TransformStream(inputStream, outputStream, keepReadOpen: false, keepWriteOpen: true); rule.TransformStream(inputStream, outputStream, keepReadOpen: false, keepWriteOpen: true);
baseFile = outputStream.GetInfo(omitFromScan: omitFromScan, keepReadOpen: false, asFiles: asFiles);
// Dispose of the streams if (fileType == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFiles.AaruFormats))
baseFile = AaruFormat.Create(outputStream);
else if (fileType == FileType.CHD && !asFiles.HasFlag(TreatAsFiles.CHDs))
baseFile = CHDFile.Create(outputStream);
else
baseFile = outputStream.GetInfo(keepReadOpen: false);
// Dispose of the output stream
outputStream.Dispose(); outputStream.Dispose();
inputStream.Dispose();
} }
// Otherwise, just get the info // Otherwise, just get the info
else else
{ {
baseFile = TryOpenRead(input).GetInfo(omitFromScan: omitFromScan, keepReadOpen: false, asFiles: asFiles); if (fileType == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFiles.AaruFormats))
baseFile = AaruFormat.Create(inputStream);
else if (fileType == FileType.CHD && !asFiles.HasFlag(TreatAsFiles.CHDs))
baseFile = CHDFile.Create(inputStream);
else
baseFile = inputStream.GetInfo(keepReadOpen: false);
} }
} }
else else
{ {
baseFile = TryOpenRead(input).GetInfo(omitFromScan: omitFromScan, keepReadOpen: false, asFiles: asFiles); if (fileType == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFiles.AaruFormats))
baseFile = AaruFormat.Create(inputStream);
else if (fileType == FileType.CHD && !asFiles.HasFlag(TreatAsFiles.CHDs))
baseFile = CHDFile.Create(inputStream);
else
baseFile = inputStream.GetInfo(keepReadOpen: false);
} }
// Dispose of the input stream
inputStream.Dispose();
// Add unique data from the file // Add unique data from the file
baseFile.RemoveHashes(omitFromScan);
baseFile.Filename = Path.GetFileName(input); baseFile.Filename = Path.GetFileName(input);
baseFile.Date = (date ? new FileInfo(input).LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss") : string.Empty); baseFile.Date = (date ? new FileInfo(input).LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss") : string.Empty);

View File

@@ -45,11 +45,10 @@ namespace SabreTools.Library.IO
/// <param name="size">Size of the input stream</param> /// <param name="size">Size of the input stream</param>
/// <param name="omitFromScan">Hash flag saying what hashes should not be calculated (defaults to none)</param> /// <param name="omitFromScan">Hash flag saying what hashes should not be calculated (defaults to none)</param>
/// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param> /// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param>
/// <param name="asFiles">TreatAsFiles representing special format scanning</param>
/// <returns>Populated BaseFile object if success, empty one on error</returns> /// <returns>Populated BaseFile object if success, empty one on error</returns>
public static BaseFile GetInfo(this Stream input, long size = -1, Hash omitFromScan = 0x0, bool keepReadOpen = false, TreatAsFiles asFiles = 0x00) public static BaseFile GetInfo(this Stream input, long size = -1, bool keepReadOpen = false)
{ {
return GetInfoAsync(input, size, omitFromScan, keepReadOpen, asFiles).ConfigureAwait(false).GetAwaiter().GetResult(); return GetInfoAsync(input, size, keepReadOpen).ConfigureAwait(false).GetAwaiter().GetResult();
} }
/// <summary> /// <summary>
@@ -57,53 +56,14 @@ namespace SabreTools.Library.IO
/// </summary> /// </summary>
/// <param name="input">Filename to get information from</param> /// <param name="input">Filename to get information from</param>
/// <param name="size">Size of the input stream</param> /// <param name="size">Size of the input stream</param>
/// <param name="omitFromScan">Hash flag saying what hashes should not be calculated (defaults to none)</param>
/// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param> /// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param>
/// <param name="asFiles">TreatAsFiles representing special format scanning</param>
/// <returns>Populated BaseFile object if success, empty one on error</returns> /// <returns>Populated BaseFile object if success, empty one on error</returns>
public static async Task<BaseFile> GetInfoAsync(Stream input, long size = -1, Hash omitFromScan = 0x0, bool keepReadOpen = false, TreatAsFiles asFiles = 0x00) public static async Task<BaseFile> GetInfoAsync(Stream input, long size = -1, bool keepReadOpen = false)
{ {
// If we want to automatically set the size // If we want to automatically set the size
if (size == -1) if (size == -1)
size = input.Length; size = input.Length;
// We first check to see if it's an AaruFormat if we have to
if (!asFiles.HasFlag(TreatAsFiles.AaruFormats))
{
var aaruFormat = AaruFormat.Create(input);
input.SeekIfPossible();
// If we found a valid AaruFormat
if (aaruFormat != null)
{
if (!keepReadOpen)
input.Dispose();
return aaruFormat;
}
}
// Then, we first check to see if it's a CHD if we have to
if (!asFiles.HasFlag(TreatAsFiles.CHDs))
{
var chd = CHDFile.Create(input);
input.SeekIfPossible();
// If we found a valid CHD
if (chd != null)
{
if (!keepReadOpen)
input.Dispose();
return chd;
}
}
BaseFile rom = new BaseFile()
{
Size = size,
};
try try
{ {
// Get a list of hashers to run over the buffer // Get a list of hashers to run over the buffer
@@ -169,28 +129,26 @@ namespace SabreTools.Library.IO
await Task.WhenAll(hashers.Select(h => h.Finalize())); await Task.WhenAll(hashers.Select(h => h.Finalize()));
// Get the results // Get the results
if (!omitFromScan.HasFlag(Hash.CRC)) BaseFile baseFile = new BaseFile()
rom.CRC = hashers.First(h => h.HashType == Hash.CRC).GetHash(); {
if (!omitFromScan.HasFlag(Hash.MD5)) Size = size,
rom.MD5 = hashers.First(h => h.HashType == Hash.MD5).GetHash(); CRC = hashers.First(h => h.HashType == Hash.CRC).GetHash(),
MD5 = hashers.First(h => h.HashType == Hash.MD5).GetHash(),
#if NET_FRAMEWORK #if NET_FRAMEWORK
if (!omitFromScan.HasFlag(Hash.RIPEMD160)) RIPEMD160 = hashers.First(h => h.HashType == Hash.RIPEMD160).GetHash(),
rom.RIPEMD160 = hashers.First(h => h.HashType == Hash.RIPEMD160).GetHash();
#endif #endif
if (!omitFromScan.HasFlag(Hash.SHA1)) SHA1 = hashers.First(h => h.HashType == Hash.SHA1).GetHash(),
rom.SHA1 = hashers.First(h => h.HashType == Hash.SHA1).GetHash(); SHA256 = hashers.First(h => h.HashType == Hash.SHA256).GetHash(),
if (!omitFromScan.HasFlag(Hash.SHA256)) SHA384 = hashers.First(h => h.HashType == Hash.SHA384).GetHash(),
rom.SHA256 = hashers.First(h => h.HashType == Hash.SHA256).GetHash(); SHA512 = hashers.First(h => h.HashType == Hash.SHA512).GetHash(),
if (!omitFromScan.HasFlag(Hash.SHA384)) SpamSum = hashers.First(h => h.HashType == Hash.SpamSum).GetHash(),
rom.SHA384 = hashers.First(h => h.HashType == Hash.SHA384).GetHash(); };
if (!omitFromScan.HasFlag(Hash.SHA512))
rom.SHA512 = hashers.First(h => h.HashType == Hash.SHA512).GetHash();
if (!omitFromScan.HasFlag(Hash.SpamSum))
rom.SpamSum = hashers.First(h => h.HashType == Hash.SpamSum).GetHash();
// Dispose of the hashers // Dispose of the hashers
loadBuffer.Dispose(); loadBuffer.Dispose();
hashers.ForEach(h => h.Dispose()); hashers.ForEach(h => h.Dispose());
return baseFile;
} }
catch (IOException ex) catch (IOException ex)
{ {
@@ -204,8 +162,6 @@ namespace SabreTools.Library.IO
else else
input.SeekIfPossible(); input.SeekIfPossible();
} }
return rom;
} }
/// <summary> /// <summary>