tigersum/src/sums.d

160 lines
4.6 KiB
D

/* 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 <http://www.gnu.org/licenses/>.
*/
import tigersumConfig;
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;
import std.path;
private const string g_out_format = "%s %s";
private void writeError (string parFile, string parMessage) {
stderr.writefln("tigersum: %s: %s", parFile, parMessage);
}
private void writeWarning (string parMessage) {
writeError("WARNING", parMessage);
}
private void calculateSumsOnFiles (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 = buildPath(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(g_out_format, hash, file_name);
}
}
else {
writeError(file_name, "is a directory");
}
}
}
private void calculateSumsOnStdIn (bool parTiger2, bool parBsdStyle) {
const string hash = tigerToString(getTiger(stdin, parTiger2));
writefln(g_out_format, hash, "-");
}
void calculateSums (in string[] parFiles, in string parCWD, bool parTiger2, string parFileMode, bool parBsdStyle) {
if (parFiles.empty || parFiles.length == 1 && parFiles[0] == "-") {
calculateSumsOnStdIn(parTiger2, parBsdStyle);
}
else {
calculateSumsOnFiles(parFiles, parCWD, parTiger2, parFileMode, parBsdStyle);
}
}
bool checkSums (in string parFile, in string parRoot, 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 = buildPath(parRoot, 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) {
string curr_path = buildPath(parCWD, file_name);
ret_val &= checkSums(curr_path, dirName(curr_path), parTiger2, parFileMode);
}
return ret_val;
}