From 8339dc12642776552238786138a754030d957e9c Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 24 Aug 2016 16:29:49 -0700 Subject: [PATCH] [ArchiveTools] V1 of TGZ write (untested, unused) --- SabreTools.Helper/Tools/ArchiveTools.cs | 91 +++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/SabreTools.Helper/Tools/ArchiveTools.cs b/SabreTools.Helper/Tools/ArchiveTools.cs index f7cf1711..9df4699d 100644 --- a/SabreTools.Helper/Tools/ArchiveTools.cs +++ b/SabreTools.Helper/Tools/ArchiveTools.cs @@ -569,6 +569,85 @@ namespace SabreTools.Helper return rom; } + /// + /// Write an input file to a torrent GZ file + /// + /// File to write from + /// Directory to write archive to + /// Logger object for file and console output + /// True if the write was a success, false otherwise + public static bool WriteTorrentGZ(string input, string outdir, Logger logger) + { + // Check that the input file exists + if (!File.Exists(input)) + { + logger.Warning("File " + input + " does not exist!"); + return false; + } + input = Path.GetFullPath(input); + + // Make sure the output directory exists + if (!Directory.Exists(outdir)) + { + Directory.CreateDirectory(outdir); + } + outdir = Path.GetFullPath(outdir); + + // Now get the Rom info for the file so we have hashes and size + Rom rom = RomTools.GetSingleFileInfo(input); + + // Now, check to make sure the output file doesn't already exist + string outfile = Path.Combine(outdir, rom.SHA1 + ".gz"); + if (File.Exists(outfile)) + { + return true; + } + + // Rename the input file based on the SHA-1 + string tempname = Path.Combine(Path.GetDirectoryName(input), rom.SHA1); + File.Move(input, tempname); + + // If it doesn't exist, create the output file and then write + using (FileStream inputstream = new FileStream(tempname, FileMode.Open)) + using (GZipStream output = new GZipStream(File.OpenWrite(outfile), CompressionMode.Compress)) + { + inputstream.CopyTo(output); + } + + // Name the original input file correctly again + File.Move(tempname, input); + + // Now that it's renamed, inject the header info + using (BinaryReader br = new BinaryReader(File.Open(outfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) + using (BinaryWriter bw = new BinaryWriter(File.Open(outfile, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))) + using (StreamWriter sw = new StreamWriter(new MemoryStream())) + { + // Copy the first part of the file to the memory stream + sw.Write(br.ReadBytes(3)); //0x1F (ID1), 0x8B (ID2), 0x08 (Compression method - Deflate) + + // Now write TGZ info + byte[] data = new byte[] { 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x0 } // Flags with FEXTRA set (1), MTIME (4), XFLAG (1), OS (1), FEXTRA-LEN (2, Mirrored) + .Concat(StringToByteArray(rom.MD5)) // MD5 + .Concat(StringToByteArray(rom.CRC)) // CRC + .Concat(BitConverter.GetBytes(rom.Size).Reverse().ToArray()) // Long size (Mirrored) + .ToArray(); + sw.Write(data); + + // Finally, copy the rest of the data from the original file + br.BaseStream.Seek(10, SeekOrigin.Begin); + while (br.BaseStream.Position < br.BaseStream.Length) + { + sw.Write(br.ReadByte()); + } + + // Now write the new file over the original + sw.BaseStream.Seek(0, SeekOrigin.Begin); + sw.BaseStream.CopyTo(bw.BaseStream); + } + + return true; + } + /// /// Returns the archive type of an input file /// @@ -634,5 +713,17 @@ namespace SabreTools.Helper return outtype; } + + /// + /// http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa + /// + public static byte[] StringToByteArray(String hex) + { + int NumberChars = hex.Length; + byte[] bytes = new byte[NumberChars / 2]; + for (int i = 0; i < NumberChars; i += 2) + bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); + return bytes; + } } }