/* 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; }