aboutsummaryrefslogblamecommitdiffstats
path: root/get.c
blob: 5758388fd105dcaea333bc50bfd2bc6b0218660f (plain) (tree)


































































































                                                                                                                               
/* See LICENSE file for copyright and license details. */
#include "common.h"


struct recursion_buffer {
	char *buf;
	size_t size;
	size_t len;
};


static int
calculate_and_print(const char *file, struct barrier_group *group, struct global_data *global, struct recursion_buffer *recbuf)
{
	struct dirent *f;
	DIR *dir;
	size_t i, len, old_len;

	if (!recbuf)
		goto as_file;
	dir = opendir(file);
	if (!dir)
		goto as_file;
	if (recbuf->size - recbuf->len < strlen(file) + 1U) {
		recbuf->size = recbuf->len + strlen(file) + 1U;
		recbuf->buf = erealloc(recbuf->buf, recbuf->size);
	}
	old_len = recbuf->len;
	stpcpy(&recbuf->buf[recbuf->len], file);
	recbuf->len += strlen(file);
	if (recbuf->buf[recbuf->len - 1U] != '/')
		recbuf->buf[recbuf->len++] = '/';
	len = recbuf->len;
	while ((errno = 0, f = readdir(dir))) {
		if (recbuf->size - len < strlen(f->d_name) + 1U) {
			recbuf->size = len + strlen(f->d_name) + 1U;
			recbuf->buf = erealloc(recbuf->buf, recbuf->size);
		}
		stpcpy(&recbuf->buf[len], f->d_name);
		if (calculate_and_print(recbuf->buf, group, global, recbuf))
			goto recusion_error;
	}
	recbuf->len = old_len;
	recbuf->buf[recbuf->len] = '\0';
	if (errno) {
		weprintf("%s:", file);
	recusion_error:
		closedir(dir);
		return -1;
	}
	closedir(dir);
	return 0;

as_file:
	global->file = file;
	if (calculate(global->file, group, global))
		return -1;
	for (i = 0; i < global->nalgorithms; i++)
		writeall(STDOUT_FILENO, global->algorithms[i].result, global->algorithms[i].result_length, "<stdout>");
	return 0;
}


int
calculate_and_print_each(char **files, struct algorithm *algorithms, size_t nalgorithms,
                         size_t nthreads, enum format format, int hexinput, int recursive)
{
	struct recursion_buffer recbuf = {NULL, 0, 0};
	size_t wanted_nalgorithms = nalgorithms;
	struct buffer buffer = {0};
	struct barrier_group group;
	struct global_data global;
	int ret = 0;

	global.format = format;
	global.hexinput = hexinput;
	global.buffer = &buffer;
	global.algorithms = algorithms;
	global.nalgorithms = nalgorithms;

	if (!nthreads)
		nthreads = getautonthreads();
	nthreads = MAX(MIN(nalgorithms, nthreads), 1U);

	createbarriergroup(&group, nthreads, &global);

	for (; *files; files++)
		if (calculate_and_print(*files, &group, &global, recursive ? &recbuf : NULL))
			ret = 2;

	if (global.nalgorithms != wanted_nalgorithms)
		ret = 2;

	killbarriergroup(&group, &global);

	free(buffer.buf);
	free(recbuf.buf);
	return ret;
}