Mercurial > hg > AutoCRCheck
view Program.cs @ 0:8ac8eb805b6c default tip
Initial commit
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Fri, 07 Feb 2014 23:23:08 +0100 |
parents | |
children |
line wrap: on
line source
???using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Windows.Forms; namespace AutoCRCheck { static class Program { static Boolean DeleteBad = false; static String RenameBadSuffix = null; static Boolean WaitOnCompletion = false; static Boolean PrintMissing = false; static Boolean PrintMismatch = false; static UInt32 DirectoriesChecked = 0; static UInt32 ListsChecked = 0; static UInt32 FilesMissing = 0; static UInt32 FilesBad = 0; static UInt32 FilesGood = 0; [STAThread] static int Main(String[] args) { String rootdirectory = null; Console.Error.WriteLine("UCIS AutoCRCheck (c) 2014 Ivo Smits <Ivo@UCIS.nl>"); Console.Error.WriteLine("See http://wiki.ucis.nl/AutoCRCheck for more information"); for (int i = 0; i < args.Length; i++) { if (args[i].StartsWith("-")) { switch (args[i].Substring(1)) { case "d": case "delete": DeleteBad = true; break; case "r": case "rename": RenameBadSuffix = args[++i]; break; case "w": case "wait": WaitOnCompletion = true; break; case "printmissing": PrintMissing = true; break; case "p": case "printmismatch": PrintMismatch = true; break; case "help": case "h": PrintCommandlineHelp(Console.Out); return -1; default: Console.Error.WriteLine("Error: unknown command line argument: " + args[i]); PrintCommandlineHelp(Console.Error); return -1; } } else { if (rootdirectory != null) { Console.Error.WriteLine("Error: duplicate root directory specified."); return -1; } rootdirectory = args[i]; } } if (rootdirectory == null) { Console.Error.WriteLine("Root directory not set, waiting for GUI input..."); try { using (new Control()) ; } catch { Console.Error.WriteLine("It looks like you're trying to run this application in a non-GUI session. Luckily we're handling this nearly fatal error for you."); PrintCommandlineHelp(Console.Error); return -1; } using (frmOptions options = new frmOptions()) { DialogResult result = options.ShowDialog(); if (result != DialogResult.OK) return -2; rootdirectory = options.RootDirectory; DeleteBad = options.MismatchDelete; RenameBadSuffix = options.MismatchRenameSuffix; WaitOnCompletion = true; } } if (!Directory.Exists(rootdirectory)) { Console.Error.WriteLine("Error: root directory not found."); return -1; } rootdirectory = Path.GetFullPath(rootdirectory); ScanDirectory(rootdirectory); String report = String.Format( "{0} directories scanned.\n{1} .SFV files processed\n{2} files were missing\n{3} files had a mismatching checksum, they have been dealt with.\n{4} files are good", DirectoriesChecked, ListsChecked, FilesMissing, FilesBad, FilesGood); Console.Error.WriteLine(report); Console.Error.WriteLine("Done."); if (WaitOnCompletion) { MessageBox.Show("All files have been checked." + Environment.NewLine + report, "UCIS AutoCRCheck", MessageBoxButtons.OK, MessageBoxIcon.Information); } return 0; } static void PrintCommandlineHelp(TextWriter w) { w.WriteLine("UCIS AutoCRCheck recursively checks directories for .SFV files and handles mismatching checksums as instructed."); w.WriteLine("Usage: AutoCRCheck.exe [options] [root directory]"); w.WriteLine("Possible options:"); w.WriteLine(" -delete Delete mismatching files"); w.WriteLine(" -rename [suffix] Rename mismatching files, append [suffix] to filename"); w.WriteLine(" -printmissing Print full path of missing files"); w.WriteLine(" -printmismatch Print full path of mismatched files"); w.WriteLine(" -wait Wait for user input when done"); w.WriteLine(" -help Display this message"); w.WriteLine(); w.WriteLine("Examples:"); w.WriteLine(" AutoCRCheck.exe . -rename .badcrc"); w.WriteLine(" AutoCRCheck.exe . -printmismatch > badfiles.txt"); } static void ScanDirectory(String dir) { DirectoriesChecked++; Console.Error.WriteLine("Directory: {0}", dir); foreach (String sfv in Directory.GetFiles(dir, "*.sfv")) { ListsChecked++; Console.Error.WriteLine("Checksum file: {0}", Path.GetFileName(sfv)); using (TextReader reader = File.OpenText(Path.Combine(dir, sfv))) { while (true) { String line = reader.ReadLine(); if (line == null) break; if (line.Length == 0 || line[0] == ';') continue; int lastspace = line.LastIndexOf(' '); if (lastspace == -1) continue; String file = line.Substring(0, lastspace).TrimEnd(' '); String cksumstr = line.Substring(lastspace); UInt32 goodcksum; if (!UInt32.TryParse(cksumstr, NumberStyles.HexNumber, null, out goodcksum)) { Console.Error.WriteLine("Failed to decode checksum string: {0}", cksumstr); continue; } String filepath = Path.Combine(dir, file); if (!File.Exists(filepath)) { FilesMissing++; Console.Error.WriteLine("File not found: {0}", file); if (PrintMissing) Console.Out.WriteLine(filepath); continue; } UInt32 realcksum; Console.Error.Write("Checking file: {0}... ", file); using (Stream input = File.OpenRead(filepath)) realcksum = CRCCalculate(input); if (goodcksum != realcksum) { FilesBad++; Console.Error.WriteLine("Mismatch."); if (PrintMismatch) Console.Out.WriteLine(filepath); if (RenameBadSuffix != null) { File.Move(filepath, filepath + RenameBadSuffix); } else if (DeleteBad) { File.Delete(filepath); } } else { FilesGood++; Console.Error.WriteLine("Good."); } } } } foreach (String subdir in Directory.GetDirectories(dir)) { ScanDirectory(Path.Combine(dir, subdir)); } } static readonly UInt32[] CRCTable = CRCGenerateTable(); static UInt32[] CRCGenerateTable() { UInt32[] table = new UInt32[256]; for (UInt32 v = 0; v < 256; v++) { UInt32 e = CRCReflect(v, 8) << 24; for (int i = 0; i < 8; i++) { if ((e & 0x80000000L) == 0) e <<= 1; else e = (e << 1) ^ 0x04C11DB7; } table[v] = CRCReflect(e, 32); } return table; } static UInt32 CRCReflect(UInt32 r, int v) { UInt32 ret = 0; for (int i = 1; i < v + 1; i++, r >>= 1) if ((r & 1) != 0) ret |= 1u << (v - i); return ret; } static uint CRCCalculate(Stream input) { uint c = 0xffffffff; Byte[] buffer = new Byte[Math.Min(1024, input.Length)]; while (true) { int n = input.Read(buffer, 0, buffer.Length); if (n <= 0) break; for (int i = 0; i < n; i++) c = CRCTable[(c ^ buffer[i]) & 0xFF] ^ (c >> 8); } return c ^ 0xffffffff; } } }