cmogstored.git  about / heads / tags
alternative mogstored implementation for MogileFS
blob 3990812c5531992ae81783e2aa9654601b94705c 1838 bytes (raw)
$ git show HEAD:digest.c	# shows this blob on the CLI

 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
 
/*
 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
 */
#include "cmogstored.h"
#include "digest.h"

__attribute__((constructor)) static void digest_init(void)
{
	CHECK(Gc_rc, GC_OK, gc_init());
	atexit(gc_done);
}

void mog_digest_init(struct mog_digest *digest, enum Gc_hash alg)
{
	digest->alg = alg;
	CHECK(Gc_rc, GC_OK, gc_hash_open(alg, 0, &digest->ctx));
}

enum mog_digest_next mog_digest_read(struct mog_digest *digest, int fd)
{
	size_t len;
	char *buf = mog_fsbuf_get(&len);
	size_t i = 1024;

	while (--i > 0) {
		ssize_t r = read(fd, buf, len);

		if (r > 0) { /* most likely */
			gc_hash_write(digest->ctx, r, buf);
			if (mog_thr_prepare_quit())
				return MOG_DIGEST_YIELD;
		} else if (r == 0) {
			/* wait for user to call mog_digest_hex() */
			return MOG_DIGEST_EOF;
		} else {
			assert(r < 0 && errno && "buggy read(2)?");
			/* may happen on crazy FSes */
			if (errno == EINTR)
				continue;
			/* bail on EAGAIN, not possible on regular files */
			return MOG_DIGEST_ERROR;
		}
	}

	return MOG_DIGEST_CONTINUE;
}

void mog_digest_hex(struct mog_digest *digest, char *buf, size_t len)
{
	static const char hex[] = "0123456789abcdef";
	char *out = buf;
	size_t hashlen = gc_hash_digest_length(digest->alg);
	union { const char *s; const unsigned char *u; } result;

	result.s = gc_hash_read(digest->ctx);

	/* hashlen = 16 for MD5, 20 for SHA-1 */
	if (digest->alg == GC_MD5)
		assert(hashlen == 16 && "bad hashlen");
	assert(len >= (hashlen * 2) && "hex buffer too small");
	assert(hashlen != 0 && "bad hashlen");

	while (hashlen--) {
		*out++ = hex[*result.u >> 4];
		*out++ = hex[*result.u & 0x0f];
		result.u++;
	}
}

void mog_digest_destroy(struct mog_digest *digest)
{
	if (digest->ctx)
		gc_hash_close(digest->ctx);
}

git clone https://yhbt.net/cmogstored.git