pgpHashAlgo algo; /*!< Used hash algorithm */
};
+#define DIGESTS_MAX 11
+struct rpmDigestBundle_s {
+ int index_min; /*!< Smallest index of active digest */
+ int index_max; /*!< Largest index of active digest */
+ off_t nbytes; /*!< Length of total input data */
+ DIGEST_CTX digests[DIGESTS_MAX]; /*!< Digest contexts indexed by algo */
+};
+
+rpmDigestBundle rpmDigestBundleNew(void)
+{
+ rpmDigestBundle bundle = xcalloc(1, sizeof(*bundle));
+ return bundle;
+}
+
+rpmDigestBundle rpmDigestBundleFree(rpmDigestBundle bundle)
+{
+ if (bundle) {
+ for (int i = bundle->index_min; i <= bundle->index_max ; i++) {
+ if (bundle->digests[i] == NULL)
+ continue;
+ rpmDigestFinal(bundle->digests[i], NULL, NULL, 0);
+ bundle->digests[i] = NULL;
+ }
+ memset(bundle, 0, sizeof(*bundle));
+ free(bundle);
+ }
+ return NULL;
+}
+
+int rpmDigestBundleAdd(rpmDigestBundle bundle, pgpHashAlgo algo,
+ rpmDigestFlags flags)
+{
+ DIGEST_CTX ctx = NULL;
+ if (bundle && algo > 0 && algo < DIGESTS_MAX) {
+ if (bundle->digests[algo] == NULL) {
+ ctx = rpmDigestInit(algo, flags);
+ if (ctx) {
+ bundle->digests[algo] = ctx;
+ if (algo < bundle->index_min) {
+ bundle->index_min = algo;
+ }
+ if (algo > bundle->index_max) {
+ bundle->index_max = algo;
+ }
+ }
+ }
+ }
+ return (ctx != NULL);
+}
+
+int rpmDigestBundleUpdate(rpmDigestBundle bundle, const void *data, size_t len)
+{
+ int rc = 0;
+ if (bundle && data && len > 0) {
+ for (int i = bundle->index_min; i <= bundle->index_max; i++) {
+ DIGEST_CTX ctx = bundle->digests[i];
+ if (ctx == NULL)
+ continue;
+ rc += rpmDigestUpdate(ctx, data, len);
+ }
+ bundle->nbytes += len;
+ }
+ return rc;
+}
+
+int rpmDigestBundleFinal(rpmDigestBundle bundle,
+ pgpHashAlgo algo, void ** datap, size_t * lenp, int asAscii)
+{
+ int rc = 0;
+ if (bundle && algo >= bundle->index_min && algo <= bundle->index_max) {
+ rc = rpmDigestFinal(bundle->digests[algo], datap, lenp, asAscii);
+ bundle->digests[algo] = NULL;
+ }
+ return rc;
+}
+
+DIGEST_CTX rpmDigestBundleDupCtx(rpmDigestBundle bundle, pgpHashAlgo algo)
+{
+ DIGEST_CTX dup = NULL;
+ if (bundle && algo >= bundle->index_min && algo <= bundle->index_max) {
+ dup = rpmDigestDup(bundle->digests[algo]);
+ }
+ return dup;
+}
+
DIGEST_CTX
rpmDigestDup(DIGEST_CTX octx)
{
/** \ingroup rpmpgp
*/
typedef struct DIGEST_CTX_s * DIGEST_CTX;
+typedef struct rpmDigestBundle_s * rpmDigestBundle;
/** \ingroup rpmpgp
*/
void ** datap,
size_t * lenp, int asAscii);
+/** \ingroup rpmpgp
+ * Create a new digest bundle.
+ * @return New digest bundle
+ */
+rpmDigestBundle rpmDigestBundleNew(void);
+
+/** \ingroup rpmpgp
+ * Free a digest bundle and all contained digest contexts.
+ * @param bundle digest bundle
+ * @return NULL always
+ */
+rpmDigestBundle rpmDigestBundleFree(rpmDigestBundle bundle);
+
+/** \ingroup rpmpgp
+ * Add a new type of digest to a bundle.
+ * @param bundle digest bundle
+ * @param algo type of digest
+ * @param flags bit(s) to control digest operation
+ * @return 0 on success
+ */
+int rpmDigestBundleAdd(rpmDigestBundle bundle, pgpHashAlgo algo,
+ rpmDigestFlags flags);
+
+/** \ingroup rpmpgp
+ * Update contexts within bundle with next plain text buffer.
+ * @param bundle digest bundle
+ * @param data next data buffer
+ * @param len no. bytes of data
+ * @return 0 on success
+ */
+int rpmDigestBundleUpdate(rpmDigestBundle bundle, const void *data, size_t len);
+
+/** \ingroup rpmpgp
+ * Return digest from a bundle and destroy context, see rpmDigestFinal().
+ *
+ * @param bundle digest bundle
+ * @param algo type of digest to return
+ * @retval datap address of returned digest
+ * @retval lenp address of digest length
+ * @param asAscii return digest as ascii string?
+ * @return 0 on success
+ */
+int rpmDigestBundleFinal(rpmDigestBundle bundle,
+ pgpHashAlgo algo, void ** datap, size_t * lenp, int asAscii);
+
+/** \ingroup rpmpgp
+ * Duplicate a digest context from a bundle.
+ * @param bundle digest bundle
+ * @param algo type of digest to dup
+ * @return duplicated digest context
+ */
+DIGEST_CTX rpmDigestBundleDupCtx(rpmDigestBundle bundle, pgpHashAlgo algo);
+
#ifdef __cplusplus
}
#endif