diff --git a/SabreTools.Helper/Tools/ArchiveTools.cs b/SabreTools.Helper/Tools/ArchiveTools.cs index 06063807..cb29798c 100644 --- a/SabreTools.Helper/Tools/ArchiveTools.cs +++ b/SabreTools.Helper/Tools/ArchiveTools.cs @@ -19,31 +19,67 @@ namespace SabreTools.Helper /// Output directory to build to /// Type of archive to attempt to write to /// RomData representing the new information - public static void WriteArchiveOrFile(string input, string output, ArchiveType archiveType, RomData rom) + public static void WriteFileToArchive(string input, string output, ArchiveType archiveType, RomData rom) { string archiveFileName = output + Path.DirectorySeparatorChar + rom.Game + ".zip"; string singleFileName = output + Path.DirectorySeparatorChar + rom.Game + Path.DirectorySeparatorChar + rom.Name; - IWriter outarchive = null; - FileStream fs = null; + IWritableArchive outarchive = null; try { - fs = File.OpenWrite(archiveFileName); - outarchive = WriterFactory.Open(fs, ArchiveType.Zip, CompressionType.Deflate); - outarchive.Write(rom.Name, input); - } - catch - { - if (!File.Exists(singleFileName)) + if (!File.Exists(archiveFileName)) { - File.Copy(input, singleFileName); + outarchive = ArchiveFactory.Create(archiveType) as IWritableArchive; } + else + { + outarchive = ArchiveFactory.Open(archiveFileName, Options.LookForHeader) as IWritableArchive; + } + outarchive.AddEntry(rom.Name, input); + outarchive.SaveTo(archiveFileName, new CompressionInfo { Type = CompressionType.Deflate }); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + finally + { + outarchive?.Dispose(); + } + } + + /// + /// Copy a file either to an output archive or to an output folder + /// + /// Input filename to be moved + /// Output directory to build to + /// Type of archive to attempt to write to + /// RomData representing the new information + public static void WriteFolderToArchive(string input, string output, ArchiveType archiveType) + { + string archiveFileName = output + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(input) + ".zip"; + + IWritableArchive outarchive = null; + try + { + if (!File.Exists(archiveFileName)) + { + outarchive = ArchiveFactory.Create(archiveType) as IWritableArchive; + } + else + { + outarchive = ArchiveFactory.Open(archiveFileName, Options.LookForHeader) as IWritableArchive; + } + outarchive.AddAllFromDirectory(input, "*", SearchOption.AllDirectories); + outarchive.SaveTo(archiveFileName, new CompressionInfo { Type = CompressionType.Deflate }); + } + catch (Exception ex) + { + Console.WriteLine(ex); } finally { outarchive?.Dispose(); - fs?.Close(); - fs?.Dispose(); } } diff --git a/SabreTools.Helper/Tools/Output.cs b/SabreTools.Helper/Tools/Output.cs index b0b75899..3e1caf2d 100644 --- a/SabreTools.Helper/Tools/Output.cs +++ b/SabreTools.Helper/Tools/Output.cs @@ -608,7 +608,7 @@ namespace SabreTools.Helper long adjustedLength = br.BaseStream.Length - bytesToRemoveFromTail; // Seek to the correct position - br.BaseStream.Seek(bytesToRemoveFromHead, SeekOrigin.Begin); + br.BaseStream.Seek((bytesToRemoveFromHead < 0 ? 0 : bytesToRemoveFromHead), SeekOrigin.Begin); // Now read the file in chunks and write out byte[] buffer = new byte[bufferSize]; @@ -695,5 +695,22 @@ namespace SabreTools.Helper } } } - } + + /// + /// Copy a file to a new location, creating directories as needed + /// + /// Input filename + /// Output filename + public static void CopyFileToNewLocation(string input, string output) + { + if (File.Exists(input) && !File.Exists(output)) + { + if (!Directory.Exists(Path.GetDirectoryName(output))) + { + Directory.CreateDirectory(Path.GetDirectoryName(output)); + } + File.Copy(input, output); + } + } + } } diff --git a/SabreTools.Helper/Tools/RomTools.cs b/SabreTools.Helper/Tools/RomTools.cs index d59ac89b..dcdd0ae8 100644 --- a/SabreTools.Helper/Tools/RomTools.cs +++ b/SabreTools.Helper/Tools/RomTools.cs @@ -16,6 +16,7 @@ namespace SabreTools.Helper /// True if MD5 hashes should not be calculated, false otherwise /// True if SHA-1 hashes should not be calcluated, false otherwise /// Populated RomData object if success, empty one on error + /// Add read-offset for hash info public static RomData GetSingleFileInfo(string input, bool noMD5 = false, bool noSHA1 = false) { RomData rom = new RomData diff --git a/SimpleSort/SimpleSort.cs b/SimpleSort/SimpleSort.cs index 3051d02a..c03828e7 100644 --- a/SimpleSort/SimpleSort.cs +++ b/SimpleSort/SimpleSort.cs @@ -1,4 +1,5 @@ using SabreTools.Helper; +using SharpCompress.Archive; using SharpCompress.Common; using System; using System.Collections.Generic; @@ -249,6 +250,16 @@ namespace SabreTools _outdir = Path.GetFullPath(_outdir); } + // Then create or clean the temp directory + if (!Directory.Exists(_tempdir)) + { + Directory.CreateDirectory(_tempdir); + } + else + { + Output.CleanDirectory(_tempdir); + } + // Then, loop through and check each of the inputs _logger.User("Starting to loop through inputs"); foreach (string input in _inputs) @@ -275,6 +286,20 @@ namespace SabreTools } } + // Now process the output directory and write all to zipfiles + foreach (string dir in Directory.EnumerateDirectories(_outdir, "*", SearchOption.TopDirectoryOnly)) + { + ArchiveTools.WriteFolderToArchive(dir, _outdir, ArchiveType.Zip); + try + { + Directory.Delete(dir, true); + } + catch (Exception ex) + { + _logger.Error(ex.ToString()); + } + } + // Now one final delete of the temp directory Directory.Delete(_tempdir, true); @@ -295,21 +320,93 @@ namespace SabreTools input = Path.GetFullPath(input); _logger.User("Beginning processing of '" + input + "'"); - // Get the hash of the file first - RomData rom = RomTools.GetSingleFileInfo(input); - - // If we have a blank RomData, it's an error - if (rom.Name == null) + // If we have an archive, scan it if necessary + bool shouldscan = true; + try { - return false; + IArchive temp = ArchiveFactory.Open(input); + switch (temp.Type) + { + case ArchiveType.GZip: + shouldscan = (_gz != ArchiveScanLevel.Internal); + break; + case ArchiveType.Rar: + shouldscan = (_rar != ArchiveScanLevel.Internal); + break; + case ArchiveType.SevenZip: + shouldscan = (_7z != ArchiveScanLevel.Internal); + break; + case ArchiveType.Zip: + shouldscan = (_zip != ArchiveScanLevel.Internal); + break; + } + } + catch + { + shouldscan = true; } - // Try to find the matches to the file that was found - List foundroms = RomTools.GetDuplicates(rom, _datdata); - _logger.User("File '" + input + "' had " + foundroms.Count + " matches in the DAT!"); - foreach (RomData found in foundroms) + // Hash and match the external files + if (shouldscan) { - ArchiveTools.WriteArchiveOrFile(input, _outdir, ArchiveType.Zip, found); + RomData rom = RomTools.GetSingleFileInfo(input); + + // If we have a blank RomData, it's an error + if (rom.Name == null) + { + return false; + } + + // Try to find the matches to the file that was found + List foundroms = RomTools.GetDuplicates(rom, _datdata); + _logger.User("File '" + input + "' had " + foundroms.Count + " matches in the DAT!"); + foreach (RomData found in foundroms) + { + _logger.Log("Matched name: " + found.Name); + string singleFileName = _outdir + Path.DirectorySeparatorChar + found.Game + Path.DirectorySeparatorChar + found.Name; + Output.CopyFileToNewLocation(input, singleFileName); + } + + // Now get the headerless file if it exists + int hs = 0; + RomTools.GetFileHeaderType(input, out hs, _logger); + if (hs > 0) + { + string newinput = input + ".new"; + _logger.Log("Creating unheadered file: '" + newinput + "'"); + Output.RemoveBytesFromFile(input, newinput, hs, 0); + RomData drom = RomTools.GetSingleFileInfo(newinput); + + // If we have a blank RomData, it's an error + if (drom.Name == null) + { + return false; + } + + // Try to find the matches to the file that was found + List founddroms = RomTools.GetDuplicates(drom, _datdata); + _logger.User("File '" + newinput + "' had " + founddroms.Count + " matches in the DAT!"); + foreach (RomData found in founddroms) + { + _logger.Log("Matched name: " + found.Name); + + // First output the headerless rom + string singleFileName = _outdir + Path.DirectorySeparatorChar + found.Game + Path.DirectorySeparatorChar + found.Name; + Output.CopyFileToNewLocation(newinput, singleFileName); + + // Then output the headered rom (renamed) + RomData newfound = found; + newfound.Name = Path.GetFileNameWithoutExtension(newfound.Name) + " (" + rom.CRC + ")" + Path.GetExtension(newfound.Name); + + _logger.Log("Matched name: " + newfound.Name); + + singleFileName = _outdir + Path.DirectorySeparatorChar + newfound.Game + Path.DirectorySeparatorChar + newfound.Name; + Output.CopyFileToNewLocation(input, singleFileName); + } + + // Now remove this temporary file + File.Delete(newinput); + } } // Now, if the file is a supported archive type, also run on all files within