From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-1596105-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits))
	(No client certificate requested)
	by finch.gentoo.org (Postfix) with ESMTPS id 7B76315838C
	for <garchives@archives.gentoo.org>; Wed, 31 Jan 2024 19:29:28 +0000 (UTC)
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id B2171E2B75;
	Wed, 31 Jan 2024 19:29:27 +0000 (UTC)
Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits))
	(No client certificate requested)
	by pigeon.gentoo.org (Postfix) with ESMTPS id 8B171E2B75
	for <gentoo-commits@lists.gentoo.org>; Wed, 31 Jan 2024 19:29:27 +0000 (UTC)
Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id 921923431F2
	for <gentoo-commits@lists.gentoo.org>; Wed, 31 Jan 2024 19:29:26 +0000 (UTC)
Received: from localhost.localdomain (localhost [IPv6:::1])
	by oystercatcher.gentoo.org (Postfix) with ESMTP id 26FAD105D
	for <gentoo-commits@lists.gentoo.org>; Wed, 31 Jan 2024 19:29:25 +0000 (UTC)
From: "Fabian Groffen" <grobian@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Fabian Groffen" <grobian@gentoo.org>
Message-ID: <1706729081.bc4321f30bb95ab1c2112f045a4cde811045ed59.grobian@gentoo>
Subject: [gentoo-commits] proj/portage-utils:master commit in: libq/
X-VCS-Repository: proj/portage-utils
X-VCS-Files: libq/hash.c libq/hash.h
X-VCS-Directories: libq/
X-VCS-Committer: grobian
X-VCS-Committer-Name: Fabian Groffen
X-VCS-Revision: bc4321f30bb95ab1c2112f045a4cde811045ed59
X-VCS-Branch: master
Date: Wed, 31 Jan 2024 19:29:25 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply
X-Archives-Salt: 10b0b7e9-38b9-43fd-8246-ce01f8249d4f
X-Archives-Hash: ce8b0d18b76eb825a45fc6ceb6461c90

commit:     bc4321f30bb95ab1c2112f045a4cde811045ed59
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Wed Jan 31 19:24:41 2024 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Wed Jan 31 19:24:41 2024 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=bc4321f3

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 <AT> gentoo.org>

 libq/hash.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++-----------
 libq/hash.h |   1 +
 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