/* tigersum - a command line utility to calculate the tiger hash from input. Copyright (C) 2014 Michele "King_DuckZ" Santullo This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import std.regex; import std.stdio; import std.file : isDir; import std.string; import tiger; import std.exception; import std.format; import std.array : appender; mixin(import("tigersumConfig.d")); private void writeError (string parFile, string parMessage) { stderr.writefln("tigersum: %s: %s", parFile, parMessage); } private void writeWarning (string parMessage) { writeError("WARNING", parMessage); } void calculateSums (in string[] parFiles, in string parCWD, bool parTiger2, string parFileMode, bool parBsdStyle) { ulong[] read_buff = new ulong[READ_BUFF_BLOCKS * 64 / ulong.sizeof]; foreach (file_name; parFiles) { const auto curr_path = parCWD ~ file_name; File curr_file; try { curr_file = File(curr_path, parFileMode); } catch (ErrnoException err) { writeError(file_name, "unexisting file or directory"); continue; } if (!isDir(curr_path)) { const string hash = tigerToString(getTiger(curr_file, parTiger2, cast(char[])read_buff)); if (parBsdStyle) { writefln("tiger (%s) = %s", file_name, hash); } else { writefln("%s %s", hash, file_name); } } else { writeError(file_name, "is a directory"); } } } bool checkSums (in string parFile, in string parCWD, bool parTiger2, string parFileMode) { File curr_list = File(parFile, "r"); bool ret_val = true; const auto reg_bsd = r"^tiger \((.+)\)\s*=\s*([a-fA-F0-9]{48})$"; const auto reg_normal = r"^([a-fA-F0-9]{48})\s+(.+)$"; int unmatched_lines; int mismatches; int failed_open; foreach (line; curr_list.byLine()) { auto m = match(line, reg_bsd); int index_hash, index_file; if (m) { index_hash = 2; index_file = 1; } else { m = match(line, reg_normal); index_hash = 1; index_file = 2; } if (m) { const string capt_filename = cast(string)m.captures[index_file]; writef("%s: ", capt_filename); const string curr_path = parCWD ~ capt_filename; File curr_file; try { curr_file = File(curr_path, parFileMode); } catch (ErrnoException err) { ++failed_open; writeln("opening or reading FAILED"); writeError(capt_filename, "unexisting file or directory"); continue; } const string curr_tiger = tigerToString(getTiger(curr_file, parTiger2)); const string check_tiger = (cast(string)m.captures[index_hash]).toLower; if (check_tiger == curr_tiger) { writeln("OK"); } else { ++mismatches; writeln("FAILED"); } } else { ++unmatched_lines; } } if (unmatched_lines) { auto writer = appender!string(); formattedWrite(writer, "%d line%s not formatted correctly", unmatched_lines, (unmatched_lines == 1 ? "" : "s")); writeWarning(writer.data); } if (failed_open) { auto writer = appender!string(); formattedWrite(writer, "%d listed file%s can't be read", failed_open, (failed_open == 1 ? "" : "s")); writeWarning(writer.data); } if (mismatches) { auto writer = appender!string(); formattedWrite(writer, "%d calculated checksum%s match", mismatches, (mismatches == 1 ? " DOESN'T" : "s DON'T")); writeWarning(writer.data); } return ret_val; } bool checkSums (in string[] parFiles, in string parCWD, bool parTiger2, string parFileMode) { bool ret_val = true; foreach (file_name; parFiles) { const auto curr_path = parCWD ~ file_name; ret_val &= checkSums(curr_path, parCWD, parTiger2, parFileMode); } return ret_val; }