diff options
author | Fabian Groffen <grobian@gentoo.org> | 2024-01-31 20:24:41 +0100 |
---|---|---|
committer | Fabian Groffen <grobian@gentoo.org> | 2024-01-31 20:24:41 +0100 |
commit | bc4321f30bb95ab1c2112f045a4cde811045ed59 (patch) | |
tree | 84793e860f7c9da3078663a1ca397a8a4a2485c9 | |
parent | libq/atom: fix atom comparison bug (diff) | |
download | portage-utils-bc4321f30bb95ab1c2112f045a4cde811045ed59.tar.gz portage-utils-bc4321f30bb95ab1c2112f045a4cde811045ed59.tar.bz2 portage-utils-bc4321f30bb95ab1c2112f045a4cde811045ed59.zip |
libq/hash: add hash_string function
Alternative to the implementation in PR #21, so as to reuse the same
hashing code.
We could add the interface to compute multiple hashes from the same
string when that's actually necessary.
Signed-off-by: Fabian Groffen <grobian@gentoo.org>
-rw-r--r-- | libq/hash.c | 137 | ||||
-rw-r--r-- | libq/hash.h | 1 |
2 files changed, 114 insertions, 24 deletions
diff --git a/libq/hash.c b/libq/hash.c index 9b36bb9d..f3a440fe 100644 --- a/libq/hash.c +++ b/libq/hash.c @@ -98,29 +98,54 @@ hash_hex(char *out, const unsigned char *buf, const int length) } } -/** - * Computes the hashes for file fname and writes the hex-representation - * for those hashes into the address space pointed to by the return - * pointers for these hashes. The caller should ensure enough space is - * available. Only those hashes which are in the global hashes variable - * are computed, the address space pointed to for non-used hashes are - * left untouched, e.g. they can be NULL. The number of bytes read from - * the file pointed to by fname is returned in the flen argument. - */ -int -hash_multiple_file_fd( - int fd, - char *md5, - char *sha1, - char *sha256, - char *sha512, - char *blak2b, +/* len func(dest,destlen,cbctx) */ +typedef size_t (*read_cb)(char *,size_t,void *); + +static size_t read_stdio(char *dest, size_t destlen, void *ctx) +{ + FILE *io = ctx; + + return fread(dest, 1, destlen, io); +} + +struct bufctx { + const char *buf; + size_t buflen; +}; + +static size_t read_buffer(char *dest, size_t destlen, void *ctx) +{ + struct bufctx *membuf = ctx; + size_t readlen; + + readlen = destlen; + if (readlen > membuf->buflen) + readlen = membuf->buflen; + + memcpy(dest, membuf->buf, readlen); + + /* update buffer to the remainder */ + membuf->buf += readlen; + membuf->buflen -= readlen; + + return readlen; +} + +static int +hash_multiple_internal( + read_cb rcb, + void *ctx, + char *md5, + char *sha1, + char *sha256, + char *sha512, + char *blak2b, size_t *flen, - int hashes) + int hashes) { - FILE *f; - char data[8192]; size_t len; + char data[8192]; + struct md5_ctx m5; struct sha1_ctx s1; struct sha256_ctx s256; @@ -132,8 +157,6 @@ hash_multiple_file_fd( #endif *flen = 0; - if ((f = fdopen(fd, "r")) == NULL) - return -1; md5_init_ctx(&m5); sha1_init_ctx(&s1); @@ -143,7 +166,7 @@ hash_multiple_file_fd( blake2b_init(&bl2b, BLAKE2B_OUTBYTES); #endif - while ((len = fread(data, 1, sizeof(data), f)) > 0) { + while ((len = rcb(data, sizeof(data), ctx)) > 0) { *flen += len; #pragma omp parallel sections { @@ -176,7 +199,6 @@ hash_multiple_file_fd( #endif } } - fclose(f); #pragma omp parallel sections { @@ -227,6 +249,41 @@ hash_multiple_file_fd( return 0; } +/** + * Computes the hashes for file fname and writes the hex-representation + * for those hashes into the address space pointed to by the return + * pointers for these hashes. The caller should ensure enough space is + * available. Only those hashes which are in the global hashes variable + * are computed, the address space pointed to for non-used hashes are + * left untouched, e.g. they can be NULL. The number of bytes read from + * the file pointed to by fname is returned in the flen argument. + */ +int +hash_multiple_file_fd( + int fd, + char *md5, + char *sha1, + char *sha256, + char *sha512, + char *blak2b, + size_t *flen, + int hashes) +{ + FILE *f; + int ret; + + if ((f = fdopen(fd, "r")) == NULL) + return -1; + + ret = hash_multiple_internal(read_stdio, f, + md5, sha1, sha256, sha512, blak2b, + flen, hashes); + + fclose(f); + + return ret; +} + int hash_multiple_file_at_cb( int pfd, @@ -285,3 +342,35 @@ hash_file_at_cb(int pfd, const char *fname, int hash, hash_cb_t cb) return _hash_file_buf; } + +char * +hash_string(const char *buf, ssize_t buflen, int hash) +{ + struct bufctx membuf; + size_t dummy; + + if (buflen < 0) + buflen = (ssize_t)strlen(buf); + + membuf.buf = buf; + membuf.buflen = (size_t)buflen; + + switch (hash) { + case HASH_MD5: + case HASH_SHA1: + case HASH_SHA256: + case HASH_SHA512: + case HASH_BLAKE2B: + if (hash_multiple_internal(read_buffer, &membuf, + _hash_file_buf, _hash_file_buf, + _hash_file_buf, _hash_file_buf, + _hash_file_buf, + &dummy, hash) != 0) + return NULL; + break; + default: + return NULL; + } + + return _hash_file_buf; +} diff --git a/libq/hash.h b/libq/hash.h index fb4ab5f2..ffbd2efa 100644 --- a/libq/hash.h +++ b/libq/hash.h @@ -44,5 +44,6 @@ int hash_multiple_file_at_cb( char *hash_file_at_cb(int pfd, const char *filename, int hash_algo, hash_cb_t cb); #define hash_file(f, h) hash_file_at_cb(AT_FDCWD, f, h, NULL) #define hash_file_at(fd, f, h) hash_file_at_cb(fd, f, h, NULL) +char *hash_string(const char *buf, ssize_t buflen, int hash); #endif |