diff options
Diffstat (limited to '')
-rw-r--r-- | hash.c | 98 |
1 files changed, 98 insertions, 0 deletions
@@ -0,0 +1,98 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +size_t +inithashers(struct algorithm *algorithms, size_t nalgorithms) +{ + size_t i; + for (i = 0; i < nalgorithms;) { + if (libhashsum_init_hasher_from_string(&algorithms[i].hasher, algorithms[i].algostr)) { + weprintf("%s:", algorithms[i].algostr); + free(algorithms[i].result); + /* keep order */ + memmove(&algorithms[i], &algorithms[i + 1U], (--nalgorithms - i) * sizeof(*algorithms)); + } else { + algorithms[i].offset = 0; + i++; + } + } + return nalgorithms; +} + + +void +destroyhashers(struct algorithm *algorithms, size_t nalgorithms) +{ + size_t i; + for (i = 0; i < nalgorithms; i++) + if (algorithms[i].hasher.destroy) + algorithms[i].hasher.destroy(&algorithms[i].hasher); +} + + +static void +process(struct algorithm *algorithm, struct global_data *global) +{ + size_t r; + r = algorithm->hasher.process(&algorithm->hasher, + &global->buffer->buf[algorithm->offset], + global->buffer->ready - algorithm->offset); + algorithm->offset += r; +} + + +static void +finalise(struct algorithm *algorithm, struct global_data *global) +{ + if (algorithm->hasher.finalise_const(&algorithm->hasher, &global->buffer->buf[algorithm->offset], + global->buffer->ready - algorithm->offset, 0)) + abort(); + format_result(algorithm, global->file, global->format, global->hexinput); +} + + +int +calculate(const char *file, struct barrier_group *group, struct global_data *global) +{ + int fd, is_new_fd, r, ret = -1, saved_errno; + const char *fname; + + global->nalgorithms = inithashers(global->algorithms, global->nalgorithms); + if (!global->nalgorithms) + return 0; + + fd = openfile(file, &is_new_fd, &fname); + if (fd < 0) + return -1; + + global->buffer->ready = 0; + global->buffer->procoff = 0; + global->buffer->offset = 0; + while (!(r = feedbuffer(fd, global->buffer, fname))) { + if (!global->hexinput) { + global->buffer->ready = global->buffer->offset; + global->buffer->procoff = global->buffer->offset; + } else { + if (unhex(global->buffer)) { + weprintf("%s: not a hexadecimal file", fname); + errno = 0; + goto fail; + } + } + barriersend(group, global, &process); + shiftbuffer(global->algorithms, global->nalgorithms, global->buffer); + } + if (r < 0) + goto fail; + + barriersend(group, global, &finalise); + ret = 0; +fail: + saved_errno = errno; + destroyhashers(global->algorithms, global->nalgorithms); + if (is_new_fd) + close(fd); + errno = saved_errno; + return ret; +} |