diff --git a/SOURCES/cow...cow_signvalidation.diff b/SOURCES/cow...cow_signvalidation.diff
index 3ca1c8e..7408370 100644
--- a/SOURCES/cow...cow_signvalidation.diff
+++ b/SOURCES/cow...cow_signvalidation.diff
@@ -163,7 +163,7 @@ index feda3750c..6972602e0 100644
      Fclose(payload);
      free(tid);
 diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
-index 40a3ab83f..dc1726a18 100644
+index 40a3ab83f..7f856154e 100644
 --- a/lib/rpmchecksig.c
 +++ b/lib/rpmchecksig.c
 @@ -20,6 +20,7 @@
@@ -174,125 +174,117 @@ index 40a3ab83f..dc1726a18 100644
  #include "lib/rpmvs.h"
  
  #include "debug.h"
-@@ -220,6 +221,71 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd,
-     return rc;
+@@ -221,36 +222,24 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd,
  }
  
-+static int rpmpkgVerifySigsTranscoded(FD_t fd){
-+    rpm_loff_t current;
-+    uint64_t magic;
-+    rpm_loff_t offset;
-+    int32_t rc;
-+    size_t len;
-+    uint64_t content_len;
-+    char *content = NULL;
-+
-+    current = Ftell(fd);
-+
-+    if(Fseek(fd, -(sizeof(magic) + 3 * sizeof(offset) ), SEEK_END) < 0) {
-+	rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: failed to seek for offset\n"));
-+	rc = -1;
-+	goto exit;
-+    }
-+
-+    len = sizeof(offset);
-+    if (Fread(&offset, len, 1, fd) != len) {
-+	rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification offset\n"));
-+	rc = -1;
-+	goto exit;
-+    }
-+
-+    if(Fseek(fd,  offset, SEEK_SET) < 0) {
-+	rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to seek signature verification offset\n"));
-+	rc = -1;
-+	goto exit;
-+    }
-+    len = sizeof(rc);
-+    if (Fread(&rc, len, 1, fd) != len) {
-+	rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification RC\n"));
-+	rc = -1;
-+	goto exit;
-+    }
-+
-+    len = sizeof(content_len);
-+    if (Fread(&content_len, len, 1, fd) != len) {
-+	rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content length\n"));
-+	goto exit;
-+    }
-+
-+    content = malloc(content_len + 1);
-+    if(content == NULL) {
-+	rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to allocate memory to read signature content\n"));
-+	goto exit;
-+    }
-+    content[content_len] = 0;
-+    if (Fread(content, content_len, 1, fd) != content_len) {
-+	rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content\n"));
-+	goto exit;
-+    }
-+
-+    rpmlog(RPMLOG_NOTICE, "%s", content);
-+exit:
-+    if(content){
-+	free(content);
-+    }
-+    if (Fseek(fd, current, SEEK_SET) < 0) {
-+	rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: unable to seek back to original location\n"));
-+    }
-+    return rc;
-+
-+}
-+
  static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
- 			   FD_t fd, const char *fn)
+-			   FD_t fd, const char *fn)
++			   FD_t fd, rpmsinfoCb cb, void *cbdata)
  {
-@@ -229,10 +295,14 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
- 			    .verbose = rpmIsVerbose(),
-     };
+     char *msg = NULL;
+-    struct vfydata_s vd = { .seen = 0,
+-			    .bad = 0,
+-			    .verbose = rpmIsVerbose(),
+-    };
      int rc;
 -    struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
  
-     rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd.verbose ? "\n" : "");
- 
+-    rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd.verbose ? "\n" : "");
++
 +    if(isTranscodedRpm(fd) == RPMRC_OK){
-+	return rpmpkgVerifySigsTranscoded(fd);
++	return extentsVerifySigs(fd, 1);
 +    }
-+    struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
 +
++    struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
+ 
      rc = rpmpkgRead(vs, fd, NULL, NULL, &msg);
  
      if (rc)
-@@ -260,6 +330,29 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
+ 	goto exit;
+ 
+-    rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd);
+-
+-    if (!vd.verbose) {
+-	if (vd.seen & RPMSIG_DIGEST_TYPE) {
+-	    rpmlog(RPMLOG_NOTICE, " %s", (vd.bad & RPMSIG_DIGEST_TYPE) ?
+-					_("DIGESTS") : _("digests"));
+-	}
+-	if (vd.seen & RPMSIG_SIGNATURE_TYPE) {
+-	    rpmlog(RPMLOG_NOTICE, " %s", (vd.bad & RPMSIG_SIGNATURE_TYPE) ?
+-					_("SIGNATURES") : _("signatures"));
+-	}
+-	rpmlog(RPMLOG_NOTICE, " %s\n", rc ? _("NOT OK") : _("OK"));
+-    }
++    rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, cb, cbdata);
+ 
+ exit:
+     if (rc && msg)
+@@ -260,15 +249,39 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
      return rc;
  }
  
-+static int rpmpkgVerifySigsFD(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
-+			   FD_t fd, rpmsinfoCb cb, void *cbdata)
-+{
-+    char *msg = NULL;
-+    int rc;
-+    struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
-+
-+    rc = rpmpkgRead(vs, fd, NULL, NULL, &msg);
-+
-+    if (rc)
-+	goto exit;
-+
-+    rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, cb, cbdata);
-+
-+exit:
-+    if (rc && msg)
-+	rpmlog(RPMLOG_ERR, "%s\n", msg);
-+    rpmvsFree(vs);
-+    free(msg);
-+    return rc;
++static void rpmkgVerifySigsPreLogging(struct vfydata_s *vd, const char *fn){
++    rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd->verbose ? "\n" : "");
 +}
 +
++static void rpmkgVerifySigsPostLogging(struct vfydata_s *vd, int rc){
++    if (!vd->verbose) {
++	if (vd->seen & RPMSIG_DIGEST_TYPE) {
++	    rpmlog(RPMLOG_NOTICE, " %s", (vd->bad & RPMSIG_DIGEST_TYPE) ?
++					_("DIGESTS") : _("digests"));
++	}
++	if (vd->seen & RPMSIG_SIGNATURE_TYPE) {
++	    rpmlog(RPMLOG_NOTICE, " %s", (vd->bad & RPMSIG_SIGNATURE_TYPE) ?
++					_("SIGNATURES") : _("signatures"));
++	}
++	rpmlog(RPMLOG_NOTICE, " %s\n", rc ? _("NOT OK") : _("OK"));
++    }
++}
 +
  /* Wrapper around rpmkVerifySigs to preserve API */
  int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd, const char * fn)
  {
-@@ -304,3 +397,53 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv)
+     int rc = 1; /* assume failure */
++    struct vfydata_s vd = { .seen = 0,
++			    .bad = 0,
++			    .verbose = rpmIsVerbose(),
++    };
+     if (ts && qva && fd && fn) {
+ 	rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
+ 	rpmVSFlags vsflags = rpmtsVfyFlags(ts);
+ 	int vfylevel = rpmtsVfyLevel(ts);
+-	rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, fn);
++	rpmkgVerifySigsPreLogging(&vd, fn);
++	rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, vfyCb, &vd);
++	rpmkgVerifySigsPostLogging(&vd, rc);
+     	rpmKeyringFree(keyring);
+     }
+     return rc;
+@@ -290,12 +303,22 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv)
+ 
+     while ((arg = *argv++) != NULL) {
+ 	FD_t fd = Fopen(arg, "r.ufdio");
++	struct vfydata_s vd = { .seen = 0,
++				.bad = 0,
++				.verbose = rpmIsVerbose(),
++	};
+ 	if (fd == NULL || Ferror(fd)) {
+ 	    rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), 
+ 		     arg, Fstrerror(fd));
+ 	    res++;
+-	} else if (rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, arg)) {
++	} else {
++	    rpmkgVerifySigsPreLogging(&vd, arg);
++	    int rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd,
++				      vfyCb, &vd);
++	    rpmkgVerifySigsPostLogging(&vd, rc);
++	    if (rc) {
+ 	    res++;
++	    }
+ 	}
+ 
+ 	Fclose(fd);
+@@ -304,3 +327,53 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv)
      rpmKeyringFree(keyring);
      return res;
  }
@@ -308,7 +300,7 @@ index 40a3ab83f..dc1726a18 100644
 +    struct vfydatafd_s *vd = cbdata;
 +    char *vmsg, *msg;
 +    size_t n;
-+    size_t remainder = BUFSIZ - vd->len;
++    size_t remainder = BUFSIZ - vd->len >= 0 ? BUFSIZ - vd->len : 0;
 +
 +    vmsg = rpmsinfoMsg(sinfo);
 +    rasprintf(&msg, "    %s\n", vmsg);
@@ -336,7 +328,7 @@ index 40a3ab83f..dc1726a18 100644
 +	rpmtsSetVfyLevel(ts, vfylevel);
 +    }
 +
-+    if (!rpmpkgVerifySigsFD(keyring, vfylevel, vsflags, fdi, vfyFDCb, &vd)) {
++    if (!rpmpkgVerifySigs(keyring, vfylevel, vsflags, fdi, vfyFDCb, &vd)) {
 +	rc = RPMRC_OK;
 +    }
 +    *msg = strdup(vd.msg);
@@ -369,22 +361,83 @@ index 906fe9951..7ff48b37a 100644
  #endif
 diff --git a/lib/rpmextents.c b/lib/rpmextents.c
 new file mode 100644
-index 000000000..015277751
+index 000000000..ac43264af
 --- /dev/null
 +++ b/lib/rpmextents.c
-@@ -0,0 +1,46 @@
+@@ -0,0 +1,110 @@
 +
 +#include "system.h"
 +
 +#include <rpm/rpmlog.h>
 +#include <rpm/rpmio.h>
++#include <string.h>
++#include <errno.h>
++
 +
 +#include "lib/rpmextents_internal.h"
 +
-+rpmRC isTranscodedRpm(FD_t fd) {
++
++int extentsVerifySigs(FD_t fd, int print_content){
++    rpm_loff_t current;
++    int32_t rc;
++    size_t len;
++    uint64_t content_len;
++    char *content = NULL;
++    struct extents_footer_t footer;
++
++    current = Ftell(fd);
++
++    if(extentsFooterFromFD(fd, &footer) != RPMRC_OK) {
++	rc = -1;
++	goto exit;
++    }
++    if(Fseek(fd, footer.offsets.checksig_offset, SEEK_SET) < 0) {
++	rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to seek signature verification offset\n"));
++	rc = -1;
++	goto exit;
++    }
++    len = sizeof(rc);
++    if (Fread(&rc, len, 1, fd) != len) {
++	rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to read Signature Verification RC\n"));
++	rc = -1;
++	goto exit;
++    }
++
++    if(print_content) {
++	len = sizeof(content_len);
++	if (Fread(&content_len, len, 1, fd) != len) {
++	    rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to read signature content length\n"));
++	    goto exit;
++	}
++
++	content = rmalloc(content_len + 1);
++	if(content == NULL) {
++	    rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to allocate memory to read signature content\n"));
++	    goto exit;
++	}
++	content[content_len] = 0;
++	if (Fread(content, content_len, 1, fd) != content_len) {
++	    rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to read signature content\n"));
++	    goto exit;
++	}
++
++	rpmlog(RPMLOG_NOTICE, "%s", content);
++    }
++exit:
++    if(content){
++	rfree(content);
++    }
++    if (Fseek(fd, current, SEEK_SET) < 0) {
++	rpmlog(RPMLOG_ERR, _("extentsVerifySigs: unable to seek back to original location\n"));
++    }
++    return rc;
++
++}
++
++rpmRC extentsFooterFromFD(FD_t fd, struct extents_footer_t *footer) {
++
 +    rpmRC rc = RPMRC_NOTFOUND;
 +    rpm_loff_t current;
-+    extents_magic_t magic;
 +    size_t len;
 +
 +    // If the file is not seekable, we cannot detect whether or not it is transcoded.
@@ -393,19 +446,17 @@ index 000000000..015277751
 +    }
 +    current = Ftell(fd);
 +
-+    if(Fseek(fd, -(sizeof(magic)), SEEK_END) < 0) {
-+	rpmlog(RPMLOG_ERR, _("isTranscodedRpm: failed to seek for magic\n"));
++    len = sizeof(struct extents_footer_t);
++    if(Fseek(fd, -len, SEEK_END) < 0) {
 +	rc = RPMRC_FAIL;
 +	goto exit;
 +    }
-+    len = sizeof(magic);
-+    if (Fread(&magic, len, 1, fd) != len) {
-+	rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read magic\n"));
++    if (Fread(footer, len, 1, fd) != len) {
++	rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read footer\n"));
 +	rc = RPMRC_FAIL;
 +	goto exit;
 +    }
-+    if (magic != EXTENTS_MAGIC) {
-+	rpmlog(RPMLOG_DEBUG, _("isTranscodedRpm: not transcoded\n"));
++    if (footer->magic != EXTENTS_MAGIC) {
 +	rc = RPMRC_NOTFOUND;
 +	goto exit;
 +    }
@@ -418,13 +469,18 @@ index 000000000..015277751
 +    return rc;
 +}
 +
++rpmRC isTranscodedRpm(FD_t fd) {
++    struct extents_footer_t footer;
++    return extentsFooterFromFD(fd, &footer);
++}
++
 +
 diff --git a/lib/rpmextents_internal.h b/lib/rpmextents_internal.h
 new file mode 100644
-index 000000000..57cecfc31
+index 000000000..0a3318c8e
 --- /dev/null
 +++ b/lib/rpmextents_internal.h
-@@ -0,0 +1,22 @@
+@@ -0,0 +1,58 @@
 +#ifndef _RPMEXTENTS_INTERNAL_H
 +#define _RPMEXTENTS_INTERNAL_H
 +
@@ -434,6 +490,10 @@ index 000000000..57cecfc31
 +
 +#include <stdint.h>
 +
++/** \ingroup rpmextents
++ * RPM extents library
++ */
++
 +/* magic value at end of file (64 bits) that indicates this is a transcoded
 + * rpm.
 + */
@@ -441,12 +501,44 @@ index 000000000..57cecfc31
 +
 +typedef uint64_t extents_magic_t;
 +
++struct __attribute__ ((__packed__)) extents_footer_offsets_t {
++    off64_t checksig_offset;
++    off64_t table_offset;
++    off64_t csum_offset;
++};
++
++struct __attribute__ ((__packed__)) extents_footer_t {
++    struct extents_footer_offsets_t offsets;
++    extents_magic_t magic;
++};
++
++/** \ingroup rpmextents
++ * Checks the results of the signature verification ran during transcoding.
++ * @param fd	The FD_t of the transcoded RPM
++ * @param print_content Whether or not to print the result from rpmsig
++ * @return	The number of checks that `rpmvsVerify` failed during transcoding.
++ */
++int extentsVerifySigs(FD_t fd, int print_content);
++
++/** \ingroup rpmextents
++ * Read the RPM Extents footer from a file descriptor.
++ * @param fd		The FD_t of the transcoded RPM
++ * @param[out] footer	A pointer to an allocated extents_footer_t with a copy of the footer.
++ * @return		RPMRC_OK on success, RPMRC_NOTFOUND if not a transcoded file, RPMRC_FAIL on any failure.
++ */
++rpmRC extentsFooterFromFD(FD_t fd, struct extents_footer_t *footer);
++
++/** \ingroup rpmextents
++ * Check if a RPM is a transcoded RPM
++ * @param fd	The FD_t of the transcoded RPM
++ * return	RPMRC_OK on success, RPMRC_NOTFOUND if not a transcoded file, RPMRC_FAIL on any failure.
++ */
 +rpmRC isTranscodedRpm(FD_t fd);
 +
 +#ifdef __cplusplus
 +}
 +#endif
-+#endif
++#endif /* _RPMEXTENTS_INTERNAL_H */
 diff --git a/lib/rpmplugin.h b/lib/rpmplugin.h
 index fd81aec8d..6dbbcff35 100644
 --- a/lib/rpmplugin.h
@@ -581,8 +673,50 @@ index 39762c376..88807c53c 100644
  #ifdef __cplusplus
  }
  #endif
+diff --git a/lib/transaction.c b/lib/transaction.c
+index 36c2a7a64..a476a5365 100644
+--- a/lib/transaction.c
++++ b/lib/transaction.c
+@@ -37,6 +37,7 @@
+ #include "lib/rpmfi_internal.h"	/* only internal apis */
+ #include "lib/rpmte_internal.h"	/* only internal apis */
+ #include "lib/rpmts_internal.h"
++#include "lib/rpmextents_internal.h"
+ #include "lib/rpmvs.h"
+ #include "rpmio/rpmhook.h"
+ #include "lib/rpmtriggers.h"
+@@ -1255,10 +1256,16 @@
+ 	    .signature = RPMRC_NOTFOUND,
+ 	    .vfylevel = vfylevel,
+ 	};
++	int verified = 0;
+ 	rpmRC prc = RPMRC_FAIL;
+ 
+ 	rpmtsNotify(ts, p, RPMCALLBACK_VERIFY_PROGRESS, oc++, total);
+ 	FD_t fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_OPEN_FILE, 0, 0);
++	if(fd != NULL && isTranscodedRpm(fd) == RPMRC_OK) {
++	    /* Transcoded RPMs are validated at transcoding time */
++	    prc = RPMRC_OK;
++	    verified = 1;
++	} else {
+ 	if (fd != NULL) {
+ 	    prc = rpmpkgRead(vs, fd, NULL, NULL, &vd.msg);
+ 	    rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
+@@ -1267,8 +1274,11 @@
+ 	if (prc == RPMRC_OK)
+ 	    prc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd);
+ 
++	    verified = vd.signature == RPMRC_OK;
++	}
++
+ 	/* Record verify result, signatures only for now */
+-	rpmteSetVerified(p, vd.signature == RPMRC_OK);
++	rpmteSetVerified(p, verified);
+ 
+ 	if (prc)
+ 	    rpmteAddProblem(p, RPMPROB_VERIFY, NULL, vd.msg, 0);
 diff --git a/plugins/reflink.c b/plugins/reflink.c
-index 513887604..4fc1d74d1 100644
+index 513887604..69e6b51e6 100644
 --- a/plugins/reflink.c
 +++ b/plugins/reflink.c
 @@ -13,6 +13,7 @@
@@ -614,7 +748,7 @@ index 513887604..4fc1d74d1 100644
  struct reflink_state_s {
      /* Stuff that's used across rpms */
      long fundamental_block_size;
-@@ -58,6 +54,7 @@ struct reflink_state_s {
+@@ -58,10 +54,55 @@ struct reflink_state_s {
      FD_t fd;
      rpmfiles files;
      inodeIndexHash inodeIndexes;
@@ -622,7 +756,55 @@ index 513887604..4fc1d74d1 100644
  };
  
  typedef struct reflink_state_s * reflink_state;
-@@ -96,51 +93,35 @@ static void reflink_cleanup(rpmPlugin plugin) {
+ 
++/*
++ * bsearch_r: implements a re-entrant version of stdlib's bsearch.
++ * code taken and adapted from /usr/include/bits/stdlib-bsearch.h
++ */
++inline void *
++bsearch_r (const void *__key, const void *__base, size_t __nmemb, size_t __size,
++	 __compar_d_fn_t __compar, void *__arg)
++{
++  size_t __l, __u, __idx;
++  const void *__p;
++  int __comparison;
++
++  __l = 0;
++  __u = __nmemb;
++  while (__l < __u)
++    {
++      __idx = (__l + __u) / 2;
++      __p = (const void *) (((const char *) __base) + (__idx * __size));
++      __comparison = (*__compar) (__key, __p, __arg);
++      if (__comparison < 0)
++	__u = __idx;
++      else if (__comparison > 0)
++	__l = __idx + 1;
++      else
++	{
++#if __GNUC_PREREQ(4, 6)
++# pragma GCC diagnostic push
++# pragma GCC diagnostic ignored "-Wcast-qual"
++#endif
++	  return (void *) __p;
++#if __GNUC_PREREQ(4, 6)
++# pragma GCC diagnostic pop
++#endif
++	}
++    }
++
++  return NULL;
++}
++
++static int cmpdigest(const void *k1, const void *k2, void *data) {
++    rpmlog(RPMLOG_DEBUG, _("reflink: cmpdigest k1=%p k2=%p\n"), k1, k2);
++    return memcmp(k1, k2, *(int *)data);
++}
++
+ static int inodeCmp(rpm_ino_t a, rpm_ino_t b)
+ {
+     return (a != b);
+@@ -96,51 +137,35 @@ static void reflink_cleanup(rpmPlugin plugin) {
  }
  
  static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) {
@@ -690,7 +872,7 @@ index 513887604..4fc1d74d1 100644
  	rpmlog(RPMLOG_ERR, _("reflink: failed to seek for tail %p\n"),
  	       state->fd);
  	return RPMRC_FAIL;
-@@ -182,7 +163,7 @@ static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) {
+@@ -182,7 +207,7 @@ static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) {
  	    return RPMRC_FAIL;
  	}
  	state->inodeIndexes = inodeIndexHashCreate(
@@ -699,7 +881,33 @@ index 513887604..4fc1d74d1 100644
  	);
      }
  
-@@ -239,13 +220,13 @@ rpm_loff_t find(const unsigned char *digest, reflink_state state) {
+@@ -217,21 +242,13 @@ static rpmRC reflink_psm_post(rpmPlugin plugin, rpmte te, int res)
+ rpm_loff_t find(const unsigned char *digest, reflink_state state);
+ 
+ rpm_loff_t find(const unsigned char *digest, reflink_state state) {
+-# if defined(__GNUC__)
+-    /* GCC nested function because bsearch's comparison function can't access
+-     * state-keysize otherwise
+-     */
+-    int cmpdigest(const void *k1, const void *k2) {
+-	rpmlog(RPMLOG_DEBUG, _("reflink: cmpdigest k1=%p k2=%p\n"), k1, k2);
+-	return memcmp(k1, k2, state->keysize);
+-    }
+-# endif
+     rpmlog(RPMLOG_DEBUG,
+-	   _("reflink: bsearch(key=%p, base=%p, nmemb=%d, size=%lu)\n"),
++	   _("reflink: bsearch_r(key=%p, base=%p, nmemb=%d, size=%lu)\n"),
+ 	   digest, state->table, state->keys,
+ 	   state->keysize + sizeof(rpm_loff_t));
+-    char *entry = bsearch(digest, state->table, state->keys,
+-			  state->keysize + sizeof(rpm_loff_t), cmpdigest);
++    char *entry = bsearch_r(digest, state->table, state->keys,
++			    state->keysize + sizeof(rpm_loff_t), cmpdigest,
++			    &state->keysize);
+     if (entry == NULL) {
+ 	return NOT_FOUND;
+     }
+@@ -239,13 +256,13 @@ rpm_loff_t find(const unsigned char *digest, reflink_state state) {
      return offset;
  }
  
@@ -715,7 +923,7 @@ index 513887604..4fc1d74d1 100644
  
      reflink_state state = rpmPluginGetData(plugin);
      if (state->table == NULL) {
-@@ -262,18 +243,15 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
+@@ -262,18 +279,15 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
  	/* check for hard link entry in table. GetEntry overwrites hlix with
  	 * the address of the first match.
  	 */
@@ -738,7 +946,7 @@ index 513887604..4fc1d74d1 100644
  	    return RPMRC_PLUGIN_CONTENTS;
  	}
  	/* if we didn't hard link, then we'll track this inode as being
-@@ -281,7 +259,7 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
+@@ -281,7 +295,7 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
  	 */
  	if (rpmfiFNlink(fi) > 1) {
  	    /* minor optimization: only store files with more than one link */
@@ -747,7 +955,7 @@ index 513887604..4fc1d74d1 100644
  	}
  	/* derived from wfd_open in fsm.c */
  	mode_t old_umask = umask(0577);
-@@ -366,10 +344,21 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
+@@ -366,10 +380,21 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
      return RPMRC_OK;
  }
  
@@ -771,7 +979,7 @@ index 513887604..4fc1d74d1 100644
 +    .fsm_file_archive_reader = reflink_fsm_file_archive_reader,
  };
 diff --git a/rpm2extents.c b/rpm2extents.c
-index c111be0a2..a326e3857 100644
+index c111be0a2..7dd5128de 100644
 --- a/rpm2extents.c
 +++ b/rpm2extents.c
 @@ -2,7 +2,9 @@
@@ -807,7 +1015,7 @@ index c111be0a2..a326e3857 100644
  struct digestoffset {
      const unsigned char * digest;
      rpm_loff_t pos;
-@@ -51,38 +50,47 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit)
+@@ -51,38 +50,49 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit)
      return (unit - (pos % unit)) % unit;
  }
  
@@ -858,8 +1066,10 @@ index c111be0a2..a326e3857 100644
  
      len = sizeof(fdilength);
 -    if (Fwrite(&fdilength, len, 1, validationo) != len) {
+-	fprintf(stderr, _("Unable to write input length %zd\n"), fdilength);
 +    if (Fwrite(&fdilength, len, 1, fdo) != len) {
- 	fprintf(stderr, _("Unable to write input length %zd\n"), fdilength);
++	rpmlog(RPMLOG_ERR, _("Unable to write input length %zd: %d, %s\n"),
++	       fdilength, errno, strerror(errno));
  	goto exit;
      }
      len = sizeof(algos_len);
@@ -867,44 +1077,54 @@ index c111be0a2..a326e3857 100644
 -	fprintf(stderr, _("Unable to write number of validation digests\n"));
 +    if (Fwrite(&algos_len, len, 1, fdo) != len) {
 +	algo_digest_len = (uint32_t)filedigest_len;
-+	fprintf(stderr, _("Unable to write number of digests\n"));
++	rpmlog(RPMLOG_ERR, _("Unable to write number of digests: %d, %s\n"),
++	       errno, strerror(errno));
  	goto exit;
      }
      for (algo = 0; algo < algos_len; algo++) {
-@@ -93,24 +101,24 @@ static int digestor(
+@@ -93,25 +103,29 @@ static int digestor(
  	algo_digest_len = (uint32_t)filedigest_len;
  
  	len = sizeof(algo_name_len);
 -	if (Fwrite(&algo_name_len, len, 1, validationo) != len) {
-+	if (Fwrite(&algo_name_len, len, 1, fdo) != len) {
- 	    fprintf(stderr,
+-	    fprintf(stderr,
 -		    _("Unable to write validation algo name length\n"));
-+		    _("Unable to write digest algo name length\n"));
++	if (Fwrite(&algo_name_len, len, 1, fdo) != len) {
++	    rpmlog(RPMLOG_ERR,
++		   _("Unable to write digest algo name length: %d, %s\n"),
++		   errno, strerror(errno));
  	    goto exit;
  	}
  	len = sizeof(algo_digest_len);
 -	if (Fwrite(&algo_digest_len, len, 1, validationo) != len) {
-+	if (Fwrite(&algo_digest_len, len, 1, fdo) != len) {
- 	    fprintf(stderr,
+-	    fprintf(stderr,
 -		    _("Unable to write number of bytes for validation digest\n"));
-+		    _("Unable to write number of bytes for digest\n"));
++	if (Fwrite(&algo_digest_len, len, 1, fdo) != len) {
++	    rpmlog(RPMLOG_ERR,
++		   _("Unable to write number of bytes for digest: %d, %s\n"),
++		   errno, strerror(errno));
  	     goto exit;
  	}
 -	if (Fwrite(algo_name, algo_name_len, 1, validationo) != algo_name_len) {
 -	    fprintf(stderr, _("Unable to write validation algo name\n"));
 +	if (Fwrite(algo_name, algo_name_len, 1, fdo) != algo_name_len) {
-+	    fprintf(stderr, _("Unable to write digest algo name\n"));
++	    rpmlog(RPMLOG_ERR, _("Unable to write digest algo name: %d, %s\n"),
++		   errno, strerror(errno));
  	    goto exit;
  	}
 -	if (Fwrite(filedigest, algo_digest_len, 1, validationo ) != algo_digest_len) {
-+	if (Fwrite(filedigest, algo_digest_len, 1, fdo ) != algo_digest_len) {
- 	    fprintf(stderr,
+-	    fprintf(stderr,
 -		    _("Unable to write validation digest value %u, %zu\n"),
-+		    _("Unable to write digest value %u, %zu\n"),
- 		    algo_digest_len, filedigest_len);
+-		    algo_digest_len, filedigest_len);
++	if (Fwrite(filedigest, algo_digest_len, 1, fdo ) != algo_digest_len) {
++	    rpmlog(RPMLOG_ERR,
++		   _("Unable to write digest value %u, %zu: %d, %s\n"),
++		   algo_digest_len, filedigest_len,
++		   errno, strerror(errno));
  	    goto exit;
  	}
-@@ -120,7 +128,69 @@ static int digestor(
+     }
+@@ -120,7 +134,80 @@ static int digestor(
      return rc;
  }
  
@@ -914,22 +1134,29 @@ index c111be0a2..a326e3857 100644
 +    rpmRC rc = RPMRC_FAIL;
 +
 +    if(rpmvsrc){
-+	fprintf(stderr, _("Error verifying package signatures\n"));
++	rpmlog(RPMLOG_WARNING,
++	       _("Error verifying package signatures:\n%s\n"), msg);
 +    }
 +
 +    len = sizeof(rpmvsrc);
 +    if (Fwrite(&rpmvsrc, len, 1, fdo) != len) {
-+	fprintf(stderr, _("Unable to write signature verification RC code %d\n"), rpmvsrc);
++	rpmlog(RPMLOG_ERR,
++	       _("Unable to write signature verification RC code %d: %d, %s\n"),
++	       rpmvsrc, errno, strerror(errno));
 +	goto exit;
 +    }
 +    size_t content_len = msg ? strlen(msg) : 0;
 +    len = sizeof(content_len);
 +    if (Fwrite(&content_len, len, 1, fdo) != len) {
-+	fprintf(stderr, _("Unable to write signature verification output length %zd\n"), content_len);
++	rpmlog(RPMLOG_ERR,
++	       _("Unable to write signature verification output length %zd: %d, %s\n"),
++	       content_len, errno, strerror(errno));
 +	goto exit;
 +    }
 +    if (Fwrite(msg, content_len, 1, fdo) != content_len) {
-+	fprintf(stderr, _("Unable to write signature verification output %s\n"), msg);
++	rpmlog(RPMLOG_ERR,
++	       _("Unable to write signature verification output %s: %d, %s\n"),
++	       msg, errno, strerror(errno));
 +	goto exit;
 +    }
 +
@@ -955,12 +1182,16 @@ index c111be0a2..a326e3857 100644
 +
 +    // Write result of digest computation
 +    if(FDWriteDigests(fdi, digesto, algos, algos_len) != RPMRC_OK) {
-+	fprintf(stderr, _("Failed to write digests"));
++	rpmlog(RPMLOG_ERR, _("Failed to write digests: %d, %s\n"),
++	       errno, strerror(errno));
 +	goto exit;
 +    }
 +
 +    // Write result of signature validation.
 +    if(FDWriteSignaturesValidation(sigo, rpmvsrc, msg)) {
++	rpmlog(RPMLOG_ERR,
++	       _("Failed to write signature verification result: %d, %s\n"),
++	       errno, strerror(errno));
 +	goto exit;
 +    }
 +    rc = RPMRC_OK;
@@ -975,7 +1206,7 @@ index c111be0a2..a326e3857 100644
  {
      uint32_t diglen;
      /* GNU C extension: can use diglen from outer context */
-@@ -148,7 +218,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+@@ -148,7 +235,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
      rpm_mode_t mode;
      char *rpmio_flags = NULL, *zeros;
      const unsigned char *digest;
@@ -984,14 +1215,75 @@ index c111be0a2..a326e3857 100644
      uint32_t offset_ix = 0;
      size_t len;
      int next = 0;
-@@ -253,6 +323,16 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+@@ -156,24 +243,24 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+     fdo = fdDup(STDOUT_FILENO);
+ 
+     if (rpmReadPackageRaw(fdi, &sigh, &h)) {
+-	fprintf(stderr, _("Error reading package\n"));
++	rpmlog(RPMLOG_ERR, _("Error reading package\n"));
+ 	exit(EXIT_FAILURE);
+     }
+ 
+     if (rpmLeadWrite(fdo, h))
+     {
+-	fprintf(stderr, _("Unable to write package lead: %s\n"),
++	rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
+ 		Fstrerror(fdo));
+ 	exit(EXIT_FAILURE);
+     }
+ 
+     if (rpmWriteSignature(fdo, sigh)) {
+-	fprintf(stderr, _("Unable to write signature: %s\n"), Fstrerror(fdo));
++	rpmlog(RPMLOG_ERR, _("Unable to write signature: %s\n"), Fstrerror(fdo));
+ 	exit(EXIT_FAILURE);
+     }
+ 
+     if (headerWrite(fdo, h, HEADER_MAGIC_YES)) {
+-	fprintf(stderr, _("Unable to write headers: %s\n"), Fstrerror(fdo));
++	rpmlog(RPMLOG_ERR, _("Unable to write headers: %s\n"), Fstrerror(fdo));
+ 	exit(EXIT_FAILURE);
+     }
+ 
+@@ -187,7 +274,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+     free(rpmio_flags);
+ 
+     if (gzdi == NULL) {
+-	fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
++	rpmlog(RPMLOG_ERR, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
+ 	exit(EXIT_FAILURE);
+     }
+ 
+@@ -230,7 +317,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+ 	}
+ 	pad = pad_to(pos, fundamental_block_size);
+ 	if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
+-	    fprintf(stderr, _("Unable to write padding\n"));
++	    rpmlog(RPMLOG_ERR, _("Unable to write padding\n"));
+ 	    rc = RPMRC_FAIL;
+ 	    goto exit;
+ 	}
+@@ -243,7 +330,12 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+ 	size = rpmfiFSize(fi);
+ 	rc = rpmfiArchiveReadToFile(fi, fdo, 0);
+ 	if (rc != RPMRC_OK) {
+-	    fprintf(stderr, _("rpmfiArchiveReadToFile failed with %d\n"), rc);
++	    char *errstr = rpmfileStrerror(rc);
++	    rpmlog(RPMLOG_ERR,
++		   _("rpmfiArchiveReadToFile failed while extracting "\
++		   "\"%s\" with RC %d: %s\n"),
++		   rpmfiFN(fi), rc, errstr);
++	    free(errstr);
+ 	    goto exit;
+ 	}
+ 	pos += size;
+@@ -253,42 +345,53 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
      qsort(offsets, (size_t)offset_ix, sizeof(struct digestoffset),
  	  digestoffsetCmp);
  
 +    validation_pos = pos;
 +    ssize_t validation_len = ufdCopy(validationi, fdo);
 +    if (validation_len == -1) {
-+	fprintf(stderr, _("validation output ufdCopy failed\n"));
++	rpmlog(RPMLOG_ERR, _("validation output ufdCopy failed\n"));
 +	rc = RPMRC_FAIL;
 +	goto exit;
 +    }
@@ -1000,8 +1292,30 @@ index c111be0a2..a326e3857 100644
 +
      len = sizeof(offset_ix);
      if (Fwrite(&offset_ix, len, 1, fdo) != len) {
- 	fprintf(stderr, _("Unable to write length of table\n"));
-@@ -278,17 +358,18 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+-	fprintf(stderr, _("Unable to write length of table\n"));
++	rpmlog(RPMLOG_ERR, _("Unable to write length of table\n"));
+ 	rc = RPMRC_FAIL;
+ 	goto exit;
+     }
+     len = sizeof(diglen);
+     if (Fwrite(&diglen, len, 1, fdo) != len) {
+-	fprintf(stderr, _("Unable to write length of digest\n"));
++	rpmlog(RPMLOG_ERR, _("Unable to write length of digest\n"));
+ 	rc = RPMRC_FAIL;
+ 	goto exit;
+     }
+     len = sizeof(rpm_loff_t);
+     for (int x = 0; x < offset_ix; x++) {
+ 	if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen) {
+-	    fprintf(stderr, _("Unable to write digest\n"));
++	    rpmlog(RPMLOG_ERR, _("Unable to write digest\n"));
+ 	    rc = RPMRC_FAIL;
+ 	    goto exit;
+ 	}
+ 	if (Fwrite(&offsets[x].pos, len, 1, fdo) != len) {
+-	    fprintf(stderr, _("Unable to write offset\n"));
++	    rpmlog(RPMLOG_ERR, _("Unable to write offset\n"));
+ 	    rc = RPMRC_FAIL;
  	    goto exit;
  	}
      }
@@ -1014,9 +1328,10 @@ index c111be0a2..a326e3857 100644
  
 -    ssize_t validation_len = ufdCopy(validationi, fdo);
 -    if (validation_len == -1) {
+-	fprintf(stderr, _("digest table ufdCopy failed\n"));
 +    ssize_t digest_len = ufdCopy(digestori, fdo);
 +    if (digest_len == -1) {
- 	fprintf(stderr, _("digest table ufdCopy failed\n"));
++	rpmlog(RPMLOG_ERR, _("digest table ufdCopy failed\n"));
  	rc = RPMRC_FAIL;
  	goto exit;
      }
@@ -1024,33 +1339,38 @@ index c111be0a2..a326e3857 100644
      /* add more padding so the last file can be cloned. It doesn't matter that
       * the table and validation etc are in this space. In fact, it's pretty
       * efficient if it is.
-@@ -302,17 +383,22 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+@@ -297,25 +400,15 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+     pad = pad_to((validation_pos + validation_len + 2 * sizeof(rpm_loff_t) +
+ 		 sizeof(uint64_t)), fundamental_block_size);
+     if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
+-	fprintf(stderr, _("Unable to write final padding\n"));
++	rpmlog(RPMLOG_ERR, _("Unable to write final padding\n"));
+ 	rc = RPMRC_FAIL;
  	goto exit;
      }
      zeros = _free(zeros);
 -    if (Fwrite(&pos, len, 1, fdo) != len) {
-+    if (Fwrite(&validation_pos, len, 1, fdo) != len) {
-+	fprintf(stderr, _("Unable to write offset of validation output\n"));
-+	rc = RPMRC_FAIL;
-+	goto exit;
-+    }
-+    if (Fwrite(&digest_table_pos, len, 1, fdo) != len) {
- 	fprintf(stderr, _("Unable to write offset of digest table\n"));
- 	rc = RPMRC_FAIL;
- 	goto exit;
-     }
+-	fprintf(stderr, _("Unable to write offset of digest table\n"));
+-	rc = RPMRC_FAIL;
+-	goto exit;
+-    }
 -    if (Fwrite(&validation_pos, len, 1, fdo) != len) {
-+    if (Fwrite(&digest_pos, len, 1, fdo) != len) {
- 	fprintf(stderr, _("Unable to write offset of validation table\n"));
+-	fprintf(stderr, _("Unable to write offset of validation table\n"));
+-	rc = RPMRC_FAIL;
+-	goto exit;
+-    }
+-    uint64_t magic = MAGIC;
+-    len = sizeof(magic);
+-    if (Fwrite(&magic, len, 1, fdo) != len) {
+-	fprintf(stderr, _("Unable to write magic\n"));
++    struct extents_footer_t footer = {.offsets = {validation_pos, digest_table_pos, digest_pos}, .magic = EXTENTS_MAGIC};
++    len = sizeof(footer);
++    if (Fwrite(&footer, len, 1, fdo) != len) {
++	rpmlog(RPMLOG_ERR, _("Unable to write footer\n"));
  	rc = RPMRC_FAIL;
  	goto exit;
      }
--    uint64_t magic = MAGIC;
-+    extents_magic_t magic = EXTENTS_MAGIC;
-     len = sizeof(magic);
-     if (Fwrite(&magic, len, 1, fdo) != len) {
- 	fprintf(stderr, _("Unable to write magic\n"));
-@@ -327,104 +413,200 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
+@@ -327,104 +420,202 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
      return rc;
  }
  
@@ -1075,7 +1395,9 @@ index c111be0a2..a326e3857 100644
 +	    for(int i=0; i < len; i++) {
 +		wrbytes = Fwrite(buf, sizeof(buf[0]), rdbytes, fds[i]);
 +		if (wrbytes != rdbytes) {
-+		    fprintf(stderr, "Error wriing to FD %d: %s\n", i, Fstrerror(fds[i]));
++		    rpmlog(RPMLOG_ERR,
++			   _("Error wriing to FD %d: %s\n"),
++			   i, Fstrerror(fds[i]));
 +		    total = -1;
 +		    break;
 +		}
@@ -1119,7 +1441,7 @@ index c111be0a2..a326e3857 100644
 -		_("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
 -	exit(EXIT_FAILURE);
 +     if (pipe(processorpipefd) == -1) {
-+	fprintf(stderr, _("Processor pipe failure\n"));
++	rpmlog(RPMLOG_ERR, _("Processor pipe failure\n"));
 +	return RPMRC_FAIL;
      }
  
@@ -1132,7 +1454,7 @@ index c111be0a2..a326e3857 100644
 -	    exit(EXIT_FAILURE);
 -	}
 +    if (pipe(validatorpipefd) == -1) {
-+	fprintf(stderr, _("Validator pipe failure\n"));
++	rpmlog(RPMLOG_ERR, _("Validator pipe failure\n"));
 +	return RPMRC_FAIL;
      }
  
@@ -1141,7 +1463,7 @@ index c111be0a2..a326e3857 100644
 -	fprintf(stderr, _("Main pipe failure\n"));
 -	exit(EXIT_FAILURE);
 +    if (pipe(meta_digestpipefd) == -1) {
-+	fprintf(stderr, _("Meta digest pipe failure\n"));
++	rpmlog(RPMLOG_ERR, _("Meta digest pipe failure\n"));
 +	return RPMRC_FAIL;
      }
 -    if (pipe(metapipefd) == -1) {
@@ -1149,7 +1471,7 @@ index c111be0a2..a326e3857 100644
 -	exit(EXIT_FAILURE);
 +
 +    if (pipe(meta_rpmsignpipefd) == -1) {
-+	fprintf(stderr, _("Meta rpm signature pipe failure\n"));
++	rpmlog(RPMLOG_ERR, _("Meta rpm signature pipe failure\n"));
 +	return RPMRC_FAIL;
      }
 -    cpid = fork();
@@ -1179,7 +1501,7 @@ index c111be0a2..a326e3857 100644
 +	close(meta_rpmsignpipefd[1]);
 +	rc = validator(fdi, digesto, sigo, algos, algos_len);
 +	if(rc != RPMRC_OK) {
-+	    fprintf(stderr, _("Validator failed\n"));
++	    rpmlog(RPMLOG_ERR, _("Validator failed with RC %d\n"), rc);
 +	}
  	Fclose(fdi);
 +	Fclose(digesto);
@@ -1222,7 +1544,7 @@ index c111be0a2..a326e3857 100644
 +
 +	    rc = process_package(fdi, digestori, sigi);
 +	    if(rc != RPMRC_OK) {
-+		fprintf(stderr, _("Validator failed\n"));
++		rpmlog(RPMLOG_ERR, _("Package processor failed: %d\n"), rc);
  	    }
 -	}
 -	w = waitpid(cpid, &wstatus, 0);
@@ -1271,19 +1593,19 @@ index c111be0a2..a326e3857 100644
 +	    rc = RPMRC_OK;
 +	    offt = ufdTee(fdi, fds, 2);
 +	    if(offt == -1){
-+		fprintf(stderr, _("Failed to tee RPM\n"));
++		rpmlog(RPMLOG_ERR, _("Failed to tee RPM\n"));
 +		rc = RPMRC_FAIL;
 +	    }
 +	    Fclose(fds[0]);
 +	    Fclose(fds[1]);
 +	    w = waitpid(cpids[0], &wstatus, 0);
 +	    if (w == -1) {
-+		fprintf(stderr, _("waitpid cpids[0] failed\n"));
++		rpmlog(RPMLOG_ERR, _("waitpid cpids[0] failed\n"));
 +		rc = RPMRC_FAIL;
 +	    }
 +	    w = waitpid(cpids[1], &wstatus, 0);
 +	    if (w == -1) {
-+		fprintf(stderr, _("waitpid cpids[1] failed\n"));
++		rpmlog(RPMLOG_ERR, _("waitpid cpids[1] failed\n"));
 +		rc = RPMRC_FAIL;
 +	    }
  	}
@@ -1306,8 +1628,8 @@ index c111be0a2..a326e3857 100644
 +    poptSetOtherOptionHelp(optCon, "[OPTIONS]* <DIGESTALGO>");
 +
 +    if (poptPeekArg(optCon) == NULL) {
-+	fprintf(stderr,
-+		_("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
++	rpmlog(RPMLOG_ERR,
++	       _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
 +	poptPrintUsage(optCon, stderr, 0);
 +	exit(EXIT_FAILURE);
 +    }
@@ -1319,9 +1641,9 @@ index c111be0a2..a326e3857 100644
 +    for (int x = 0; x < nb_algos; x++) {
 +	if (pgpStringVal(PGPVAL_HASHALGO, args[x], &algos[x]) != 0)
 +	{
-+	    fprintf(stderr,
-+		    _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
-+		    args[x]);
++	    rpmlog(RPMLOG_ERR,
++		   _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
++		   args[x]);
 +	    exit(EXIT_FAILURE);
  	}
      }
@@ -1484,10 +1806,10 @@ index c3189d327..a110564e2 100644
      (unset RPM_CONFIGDIR RPM_POPTEXEC_PATH; cd ${RPMTEST} && \
 diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at
 new file mode 100644
-index 000000000..29165c1b9
+index 000000000..5135c9cf8
 --- /dev/null
 +++ b/tests/rpm2extents.at
-@@ -0,0 +1,141 @@
+@@ -0,0 +1,140 @@
 +#    rpm2extents.at: Some very basic checks
 +#
 +#    Copyright (C) 2022  Manu Bretelle <chantr4@gmail.com>
@@ -1592,43 +1914,42 @@ index 000000000..29165c1b9
 +RPMDB_INIT
 +
 +runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64.rpm 2> /dev/null
-+runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm
++runroot_plugins rpm -i --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm
++test -f ${RPMTEST}/usr/bin/hello
 +],
 +[0],
 +[],
 +[])
 +AT_CLEANUP
 +
-+AT_SETUP([reflink hardlink package])
-+AT_KEYWORDS([reflink hardlink])
-+AT_SKIP_IF([$REFLINK_DISABLED])
++AT_SETUP([reflink ignores non-transcoded package])
++AT_KEYWORDS([reflink])
 +AT_CHECK([
 +RPMDB_INIT
 +
-+PKG=hlinktest-1.0-1.noarch.rpm
-+runroot_other cat /data/RPMS/${PKG} | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/${PKG} 2> /dev/null
-+runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/${PKG}
++runroot_plugins rpm -i --nodeps --undefine=%__transaction_dbus_announce /data/RPMS/hello-2.0-1.x86_64.rpm && exit $?
++# Check that the file is properly installed in chroot
++test -f ${RPMTEST}/usr/bin/hello
 +],
 +[0],
 +[],
 +[])
 +AT_CLEANUP
 +
-+AT_SETUP([rpm2extents install package])
-+AT_KEYWORDS([rpm2extents reflink])
++AT_SETUP([reflink hardlink package])
++AT_KEYWORDS([reflink hardlink])
 +AT_SKIP_IF([$REFLINK_DISABLED])
 +AT_CHECK([
 +RPMDB_INIT
 +
-+runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64.rpm 2> /dev/null
-+runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm
++PKG=hlinktest-1.0-1.noarch.rpm
++runroot_other cat /data/RPMS/${PKG} | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/${PKG} 2> /dev/null
++runroot_plugins rpm -i --nodeps --undefine=%__transaction_dbus_announce /tmp/${PKG}
 +],
 +[0],
 +[],
 +[])
 +AT_CLEANUP
-+
-+
 diff --git a/tests/rpmtests.at b/tests/rpmtests.at
 index a1adab8e0..205fed6a3 100644
 --- a/tests/rpmtests.at
diff --git a/SPECS/rpm.spec b/SPECS/rpm.spec
index 2243c83..9cb5f43 100644
--- a/SPECS/rpm.spec
+++ b/SPECS/rpm.spec
@@ -42,7 +42,7 @@
 
 %global rpmver 4.14.3
 #global snapver rc2
-%global rel 21.5
+%global rel 21.6
 
 %global srcver %{version}%{?snapver:-%{snapver}}
 %global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x}
@@ -799,6 +799,10 @@ make check || cat tests/rpmtests.log
 %doc doc/librpm/html/*
 
 %changelog
+* Fri Mar 25 2022 Manu Bretelle <chantra@fb.com> - 4.14.3-21.6
+- Make `rpm -i` work without `--nodigest`
+- Remove need of executable stack for reflink plugin
+
 * Fri Mar 04 2022 Manu Bretelle <chantra@fb.com> - 4.14.3-21.5
 - Backport GH#1040 to allow ndb DB query on read-only FS