aboutsummaryrefslogblamecommitdiffstats
path: root/hash.c
blob: 0784c789d0123f88a7668a0bf328f1af38a50a55 (plain) (tree)

































































































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