๐Ÿ“ฆ cloudflare / cloudflare-blog

๐Ÿ“„ utils.c ยท 107 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>

#include "common.h"

// Produces x if f is true, else y if f is false.
#define BRANCHLESS_IF_ELSE(f, x, y)                                            \
	(((x) & -((typeof(x)) !!(f))) | ((y) & -((typeof(y)) !(f))))

int parse_hex(uint8_t *restrict dst, uint8_t *restrict src, int max)
{
	int n = 0;
	while (n < max) {
		uint8_t a = ' ';
		while (a == ' ') {
			a = *src++;
		}
		if (a == 0) {
			// correct exit
			return n;
		}
		uint8_t b = ' ';
		while (b == ' ') {
			b = *src++;
		}
		if (b == 0) {
			// error, odd characters
			return -1;
		}
		a |= 0x20;
		b |= 0x20;

		uint32_t a1 = BRANCHLESS_IF_ELSE(
			(a >= '0' && a <= '9'), a - '0',
			BRANCHLESS_IF_ELSE((a >= 'a' && a <= 'f'), a - 'a' + 10,
					   0x100));
		uint32_t b1 = BRANCHLESS_IF_ELSE(
			(b >= '0' && b <= '9'), b - '0',
			BRANCHLESS_IF_ELSE((b >= 'a' && b <= 'f'), b - 'a' + 10,
					   0x100));
		if (a1 == 0x100 || b1 == 0x100) {
			// error, not a-f chars
			return -2;
		}
		*dst++ = (a1 << 4) | b1;
		n += 1;
	}
	return n;
}

int mmdist_load(const char *fname, struct mmdist **state_ptr)
{
	int fd = open(fname, O_RDONLY);
	if (fd < 0) {
		return errno ? errno : EINVAL;
	}

	struct stat statbuf;
	int r = fstat(fd, &statbuf);
	if (r < 0) {
		return errno ? errno : EINVAL;
	}
	uint64_t size = statbuf.st_size;

	if (size % (144 * 2 + 1) != 0) {
		close(fd);
		return EMSGSIZE;
	}

	uint8_t *file_mem =
		mmap(NULL, size, PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0);
	if (file_mem == MAP_FAILED) {
		return errno ? errno : EINVAL;
	}

	int items = size / (144 * 2 + 1);

	struct mmdist *state = calloc(1, sizeof(struct mmdist) + 144 * items);
	if (state == NULL) {
		munmap(file_mem, size);
		close(fd);
		return ENOMEM;
	}
	state->items = items;

	int item;
	for (item = 0; item < items; item++) {
		parse_hex(state->hashes[item], &file_mem[item * (144 * 2 + 1)],
			  144);
	}

	munmap(file_mem, size);
	close(fd);

	*state_ptr = state;
	return r;
}