aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2024-01-31 20:24:41 +0100
committerFabian Groffen <grobian@gentoo.org>2024-01-31 20:24:41 +0100
commitbc4321f30bb95ab1c2112f045a4cde811045ed59 (patch)
tree84793e860f7c9da3078663a1ca397a8a4a2485c9
parentlibq/atom: fix atom comparison bug (diff)
downloadportage-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.c137
-rw-r--r--libq/hash.h1
2 files changed, 114 insertions, 24 deletions
diff --git a/libq/hash.c b/libq/hash.c
index 9b36bb9..f3a440f 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 fb4ab5f..ffbd2ef 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