2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
5 #include "cmogstored.h"
8 __attribute__((constructor
)) static void digest_init(void)
10 CHECK(Gc_rc
, GC_OK
, gc_init());
14 void mog_digest_init(struct mog_digest
*digest
, enum Gc_hash alg
)
17 CHECK(Gc_rc
, GC_OK
, gc_hash_open(alg
, 0, &digest
->ctx
));
20 enum mog_digest_next
mog_digest_read(struct mog_digest
*digest
, int fd
)
23 char *buf
= mog_fsbuf_get(&len
);
27 ssize_t r
= read(fd
, buf
, len
);
29 if (r
> 0) { /* most likely */
30 gc_hash_write(digest
->ctx
, r
, buf
);
31 if (mog_thr_prepare_quit())
32 return MOG_DIGEST_YIELD
;
34 /* wait for user to call mog_digest_hex() */
35 return MOG_DIGEST_EOF
;
37 assert(r
< 0 && errno
&& "buggy read(2)?");
38 /* may happen on crazy FSes */
41 /* bail on EAGAIN, not possible on regular files */
42 return MOG_DIGEST_ERROR
;
46 return MOG_DIGEST_CONTINUE
;
49 void mog_digest_hex(struct mog_digest
*digest
, char *buf
, size_t len
)
51 static const char hex
[] = "0123456789abcdef";
53 size_t hashlen
= gc_hash_digest_length(digest
->alg
);
54 union { const char *s
; const unsigned char *u
; } result
;
56 result
.s
= gc_hash_read(digest
->ctx
);
58 /* hashlen = 16 for MD5, 20 for SHA-1 */
59 if (digest
->alg
== GC_MD5
)
60 assert(hashlen
== 16 && "bad hashlen");
61 assert(len
>= (hashlen
* 2) && "hex buffer too small");
62 assert(hashlen
!= 0 && "bad hashlen");
65 *out
++ = hex
[*result
.u
>> 4];
66 *out
++ = hex
[*result
.u
& 0x0f];
71 void mog_digest_destroy(struct mog_digest
*digest
)
74 gc_hash_close(digest
->ctx
);