comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:8ac8eb805b6c
1 using System;
2 using System.Diagnostics;
3 using System.Globalization;
4 using System.IO;
5 using System.Windows.Forms;
6
7 namespace AutoCRCheck {
8 static class Program {
9 static Boolean DeleteBad = false;
10 static String RenameBadSuffix = null;
11 static Boolean WaitOnCompletion = false;
12 static Boolean PrintMissing = false;
13 static Boolean PrintMismatch = false;
14 static UInt32 DirectoriesChecked = 0;
15 static UInt32 ListsChecked = 0;
16 static UInt32 FilesMissing = 0;
17 static UInt32 FilesBad = 0;
18 static UInt32 FilesGood = 0;
19 [STAThread]
20 static int Main(String[] args) {
21 String rootdirectory = null;
22 Console.Error.WriteLine("UCIS AutoCRCheck (c) 2014 Ivo Smits <Ivo@UCIS.nl>");
23 Console.Error.WriteLine("See http://wiki.ucis.nl/AutoCRCheck for more information");
24 for (int i = 0; i < args.Length; i++) {
25 if (args[i].StartsWith("-")) {
26 switch (args[i].Substring(1)) {
27 case "d":
28 case "delete":
29 DeleteBad = true;
30 break;
31 case "r":
32 case "rename":
33 RenameBadSuffix = args[++i];
34 break;
35 case "w":
36 case "wait":
37 WaitOnCompletion = true;
38 break;
39 case "printmissing":
40 PrintMissing = true;
41 break;
42 case "p":
43 case "printmismatch":
44 PrintMismatch = true;
45 break;
46 case "help":
47 case "h":
48 PrintCommandlineHelp(Console.Out);
49 return -1;
50 default:
51 Console.Error.WriteLine("Error: unknown command line argument: " + args[i]);
52 PrintCommandlineHelp(Console.Error);
53 return -1;
54 }
55 } else {
56 if (rootdirectory != null) {
57 Console.Error.WriteLine("Error: duplicate root directory specified.");
58 return -1;
59 }
60 rootdirectory = args[i];
61 }
62 }
63 if (rootdirectory == null) {
64 Console.Error.WriteLine("Root directory not set, waiting for GUI input...");
65 try {
66 using (new Control()) ;
67 } catch {
68 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.");
69 PrintCommandlineHelp(Console.Error);
70 return -1;
71 }
72 using (frmOptions options = new frmOptions()) {
73 DialogResult result = options.ShowDialog();
74 if (result != DialogResult.OK) return -2;
75 rootdirectory = options.RootDirectory;
76 DeleteBad = options.MismatchDelete;
77 RenameBadSuffix = options.MismatchRenameSuffix;
78 WaitOnCompletion = true;
79 }
80
81 }
82 if (!Directory.Exists(rootdirectory)) {
83 Console.Error.WriteLine("Error: root directory not found.");
84 return -1;
85 }
86 rootdirectory = Path.GetFullPath(rootdirectory);
87 ScanDirectory(rootdirectory);
88 String report = String.Format(
89 "{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",
90 DirectoriesChecked, ListsChecked, FilesMissing, FilesBad, FilesGood);
91 Console.Error.WriteLine(report);
92 Console.Error.WriteLine("Done.");
93 if (WaitOnCompletion) {
94 MessageBox.Show("All files have been checked." + Environment.NewLine + report, "UCIS AutoCRCheck", MessageBoxButtons.OK, MessageBoxIcon.Information);
95 }
96 return 0;
97 }
98 static void PrintCommandlineHelp(TextWriter w) {
99 w.WriteLine("UCIS AutoCRCheck recursively checks directories for .SFV files and handles mismatching checksums as instructed.");
100 w.WriteLine("Usage: AutoCRCheck.exe [options] [root directory]");
101 w.WriteLine("Possible options:");
102 w.WriteLine(" -delete Delete mismatching files");
103 w.WriteLine(" -rename [suffix] Rename mismatching files, append [suffix] to filename");
104 w.WriteLine(" -printmissing Print full path of missing files");
105 w.WriteLine(" -printmismatch Print full path of mismatched files");
106 w.WriteLine(" -wait Wait for user input when done");
107 w.WriteLine(" -help Display this message");
108 w.WriteLine();
109 w.WriteLine("Examples:");
110 w.WriteLine(" AutoCRCheck.exe . -rename .badcrc");
111 w.WriteLine(" AutoCRCheck.exe . -printmismatch > badfiles.txt");
112 }
113 static void ScanDirectory(String dir) {
114 DirectoriesChecked++;
115 Console.Error.WriteLine("Directory: {0}", dir);
116 foreach (String sfv in Directory.GetFiles(dir, "*.sfv")) {
117 ListsChecked++;
118 Console.Error.WriteLine("Checksum file: {0}", Path.GetFileName(sfv));
119 using (TextReader reader = File.OpenText(Path.Combine(dir, sfv))) {
120 while (true) {
121 String line = reader.ReadLine();
122 if (line == null) break;
123 if (line.Length == 0 || line[0] == ';') continue;
124 int lastspace = line.LastIndexOf(' ');
125 if (lastspace == -1) continue;
126 String file = line.Substring(0, lastspace).TrimEnd(' ');
127 String cksumstr = line.Substring(lastspace);
128 UInt32 goodcksum;
129 if (!UInt32.TryParse(cksumstr, NumberStyles.HexNumber, null, out goodcksum)) {
130 Console.Error.WriteLine("Failed to decode checksum string: {0}", cksumstr);
131 continue;
132 }
133 String filepath = Path.Combine(dir, file);
134 if (!File.Exists(filepath)) {
135 FilesMissing++;
136 Console.Error.WriteLine("File not found: {0}", file);
137 if (PrintMissing) Console.Out.WriteLine(filepath);
138 continue;
139 }
140 UInt32 realcksum;
141 Console.Error.Write("Checking file: {0}... ", file);
142 using (Stream input = File.OpenRead(filepath)) realcksum = CRCCalculate(input);
143 if (goodcksum != realcksum) {
144 FilesBad++;
145 Console.Error.WriteLine("Mismatch.");
146 if (PrintMismatch) Console.Out.WriteLine(filepath);
147 if (RenameBadSuffix != null) {
148 File.Move(filepath, filepath + RenameBadSuffix);
149 } else if (DeleteBad) {
150 File.Delete(filepath);
151 }
152 } else {
153 FilesGood++;
154 Console.Error.WriteLine("Good.");
155 }
156 }
157 }
158 }
159 foreach (String subdir in Directory.GetDirectories(dir)) {
160 ScanDirectory(Path.Combine(dir, subdir));
161 }
162 }
163 static readonly UInt32[] CRCTable = CRCGenerateTable();
164 static UInt32[] CRCGenerateTable() {
165 UInt32[] table = new UInt32[256];
166 for (UInt32 v = 0; v < 256; v++) {
167 UInt32 e = CRCReflect(v, 8) << 24;
168 for (int i = 0; i < 8; i++) {
169 if ((e & 0x80000000L) == 0) e <<= 1;
170 else e = (e << 1) ^ 0x04C11DB7;
171 }
172 table[v] = CRCReflect(e, 32);
173 }
174 return table;
175 }
176 static UInt32 CRCReflect(UInt32 r, int v) {
177 UInt32 ret = 0;
178 for (int i = 1; i < v + 1; i++, r >>= 1) if ((r & 1) != 0) ret |= 1u << (v - i);
179 return ret;
180 }
181 static uint CRCCalculate(Stream input) {
182 uint c = 0xffffffff;
183 Byte[] buffer = new Byte[Math.Min(1024, input.Length)];
184 while (true) {
185 int n = input.Read(buffer, 0, buffer.Length);
186 if (n <= 0) break;
187 for (int i = 0; i < n; i++) c = CRCTable[(c ^ buffer[i]) & 0xFF] ^ (c >> 8);
188 }
189 return c ^ 0xffffffff;
190 }
191 }
192 }