diff --git a/0031-rpmcow-denylist.patch b/0031-rpmcow-denylist.patch
new file mode 100644
index 0000000..da7aee3
--- /dev/null
+++ b/0031-rpmcow-denylist.patch
@@ -0,0 +1,386 @@
+From: Richard Phibel <richardphibel@meta.com>
+
+Subject: RPM with Copy on Write: add deny list mechanism
+
+commit 3431550e6c92ba4bc6d091cb244f70c158dfbbaa
+Author: Richard Phibel <richardphibel@meta.com>
+Date:   Wed Oct 19 23:05:17 2022 +0200
+
+    RPM with Copy on Write: add deny list mechanism
+    
+    A couple of issues were encountered when using RPM CoW for some
+    packages. This change adds a deny list mechanism to disable RPM CoW for
+    specific packages.
+
+Signed-off-by: Richard Phibel <richardphibel@meta.com>
+
+diff --git a/build/pack.c b/build/pack.c
+index 8d6f74935ebb8a4d65aa2bcb666825a99162be9c..e2f05b6412d3e0d814a1160a0dcdfad5c323a8f8 100644
+--- a/build/pack.c
++++ b/build/pack.c
+@@ -493,7 +493,7 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp,
+     }
+ 
+     /* Write the lead section into the package. */
+-    if (rpmLeadWrite(fd, pkg->header)) {
++    if (rpmLeadWriteFromHeader(fd, pkg->header)) {
+ 	rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"), Fstrerror(fd));
+ 	goto exit;
+     }
+diff --git a/lib/package.c b/lib/package.c
+index 90bd0d8a719353e8965c140b40e2dceef80a2ed1..fd41abbf6b4df07afa2caf1c47d9724765ee84e8 100644
+--- a/lib/package.c
++++ b/lib/package.c
+@@ -412,11 +412,7 @@ rpmRC rpmReadPackageRaw(FD_t fd, Header * sigp, Header * hdrp)
+     Header h = NULL;
+     Header sigh = NULL;
+ 
+-    rpmRC rc = rpmLeadRead(fd, &msg);
+-    if (rc != RPMRC_OK)
+-	goto exit;
+-
+-    rc = hdrblobRead(fd, 1, 0, RPMTAG_HEADERSIGNATURES, sigblob, &msg);
++    rpmRC rc = hdrblobRead(fd, 1, 0, RPMTAG_HEADERSIGNATURES, sigblob, &msg);
+     if (rc != RPMRC_OK)
+ 	goto exit;
+ 
+diff --git a/lib/rpmlead.c b/lib/rpmlead.c
+index 45b1c6f8edacb65549ba8d321de8f6ce8cef4503..82105122724a8efb071aecefdb278ef96ea5e70d 100644
+--- a/lib/rpmlead.c
++++ b/lib/rpmlead.c
+@@ -24,24 +24,6 @@ static unsigned char const lead_magic[] = {
+     RPMLEAD_MAGIC0, RPMLEAD_MAGIC1, RPMLEAD_MAGIC2, RPMLEAD_MAGIC3
+ };
+ 
+-/** \ingroup lead
+- * The lead data structure.
+- * The lead needs to be 8 byte aligned.
+- * @deprecated The lead (except for signature_type) is legacy.
+- * @todo Don't use any information from lead.
+- */
+-struct rpmlead_s {
+-    unsigned char magic[4];
+-    unsigned char major;
+-    unsigned char minor;
+-    short type;
+-    short archnum;
+-    char name[66];
+-    short osnum;
+-    short signature_type;       /*!< Signature header type (RPMSIG_HEADERSIG) */
+-    char reserved[16];      /*!< Pad to 96 bytes -- 8 byte aligned! */
+-};
+-
+ static int rpmLeadFromHeader(Header h, struct rpmlead_s *l)
+ {
+     if (h != NULL) {
+@@ -70,13 +52,23 @@ static int rpmLeadFromHeader(Header h, struct rpmlead_s *l)
+ }
+ 
+ /* The lead needs to be 8 byte aligned */
+-rpmRC rpmLeadWrite(FD_t fd, Header h)
++rpmRC rpmLeadWriteFromHeader(FD_t fd, Header h)
+ {
+     rpmRC rc = RPMRC_FAIL;
+     struct rpmlead_s l;
+ 
+-    if (rpmLeadFromHeader(h, &l)) {
+-	
++    if (rpmLeadFromHeader(h, &l)) {	
++	rc = rpmLeadWrite(fd, l);
++    }
++
++    return rc;
++}
++
++/* The lead needs to be 8 byte aligned */
++rpmRC rpmLeadWrite(FD_t fd, struct rpmlead_s l)
++{
++    rpmRC rc = RPMRC_FAIL;
++
+ 	l.type = htons(l.type);
+ 	l.archnum = htons(l.archnum);
+ 	l.osnum = htons(l.osnum);
+@@ -84,7 +76,6 @@ rpmRC rpmLeadWrite(FD_t fd, Header h)
+ 	    
+ 	if (Fwrite(&l, 1, sizeof(l), fd) == sizeof(l))
+ 	    rc = RPMRC_OK;
+-    }
+ 
+     return rc;
+ }
+@@ -107,6 +98,11 @@ static rpmRC rpmLeadCheck(struct rpmlead_s *lead, char **msg)
+ }
+ 
+ rpmRC rpmLeadRead(FD_t fd, char **emsg)
++{
++    return rpmLeadReadAndReturn(fd, emsg, NULL);
++}
++
++rpmRC rpmLeadReadAndReturn(FD_t fd, char **emsg, struct rpmlead_s * ret)
+ {
+     rpmRC rc = RPMRC_OK;
+     struct rpmlead_s l;
+@@ -136,5 +132,8 @@ rpmRC rpmLeadRead(FD_t fd, char **emsg)
+ 	    free(err);
+     }
+ 
++	if (ret)
++		*ret = l;
++
+     return rc;
+ }
+diff --git a/lib/rpmlead.h b/lib/rpmlead.h
+index 9d86a8d73b3250d3c306b3a3ac4a33486e6920ec..8a592abc1d0e69822f438c4c7b248cce1cb5ee72 100644
+--- a/lib/rpmlead.h
++++ b/lib/rpmlead.h
+@@ -19,13 +19,39 @@ extern "C" {
+ 
+ #define RPMLEAD_SIZE 96         /*!< Don't rely on sizeof(struct) */
+ 
++/** \ingroup lead
++ * The lead data structure.
++ * The lead needs to be 8 byte aligned.
++ * @deprecated The lead (except for signature_type) is legacy.
++ * @todo Don't use any information from lead.
++ */
++struct rpmlead_s {
++    unsigned char magic[4];
++    unsigned char major;
++    unsigned char minor;
++    short type;
++    short archnum;
++    char name[66];
++    short osnum;
++    short signature_type;       /*!< Signature header type (RPMSIG_HEADERSIG) */
++    char reserved[16];      /*!< Pad to 96 bytes -- 8 byte aligned! */
++};
++
+ /** \ingroup lead
+  * Write lead to file handle.
+  * @param fd		file handle
+  * @param h		package header
+  * @return		RPMRC_OK on success, RPMRC_FAIL on error
+  */
+-rpmRC rpmLeadWrite(FD_t fd, Header h);
++rpmRC rpmLeadWriteFromHeader(FD_t fd, Header h);
++
++/** \ingroup lead
++ * Write lead to file handle.
++ * @param fd		file handle
++ * @param l		lead
++ * @return		RPMRC_OK on success, RPMRC_FAIL on error
++ */
++rpmRC rpmLeadWrite(FD_t fd, struct rpmlead_s l);
+ 
+ /** \ingroup lead
+  * Read lead from file handle.
+@@ -35,6 +61,15 @@ rpmRC rpmLeadWrite(FD_t fd, Header h);
+  */
+ rpmRC rpmLeadRead(FD_t fd, char **emsg);
+ 
++/** \ingroup lead
++ * Read lead from file handle and return it.
++ * @param fd		file handle
++ * @param[out] emsg		failure message on error (malloced)
++ * @param[out] ret		address of lead
++ * @return		RPMRC_OK on success, RPMRC_FAIL/RPMRC_NOTFOUND on error
++ */
++rpmRC rpmLeadReadAndReturn(FD_t fd, char **emsg, struct rpmlead_s * ret);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/rpm2extents.c b/rpm2extents.c
+index 7dd5128decb03781411bd714339b3b6e9b805842..702d3765d76faf618992ca112011d2312d7fcdcc 100644
+--- a/rpm2extents.c
++++ b/rpm2extents.c
+@@ -134,6 +134,28 @@ exit:
+     return rc;
+ }
+ 
++/**
++ * Check if package is in deny list.
++ * @param package_name	package name
++ * @return 		true if package is in deny list
++ */
++static inline int isInDenyList(char * package_name)
++{
++    int is_in_deny_list = 0;
++    if (package_name) {
++	char *e_denylist = getenv("LIBREPO_TRANSCODE_RPMS_DENYLIST");
++	char *denytlist_item = strtok(e_denylist, ",");
++	while (denytlist_item) {
++	    if (strstr(package_name, denytlist_item)) {
++		is_in_deny_list = 1;
++		break;
++	    }
++	    denytlist_item = strtok(NULL, ",");
++	}
++    }
++	return is_in_deny_list;
++}
++
+ static rpmRC FDWriteSignaturesValidation(FD_t fdo, int rpmvsrc, char *msg) {
+     size_t len;
+     rpmRC rc = RPMRC_FAIL;
+@@ -239,15 +261,41 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+     uint32_t offset_ix = 0;
+     size_t len;
+     int next = 0;
++	struct rpmlead_s l;
++    rpmfiles files = NULL;
++    rpmfi fi = NULL;
++    char *msg = NULL;
+ 
+     fdo = fdDup(STDOUT_FILENO);
+ 
++    rc = rpmLeadReadAndReturn(fdi, &msg, &l);
++    if (rc != RPMRC_OK)
++	goto exit;
++
++    /* Skip conversion if package is in deny list */
++    if (isInDenyList(l.name)) {
++	if (rpmLeadWrite(fdo, l)) {
++		fprintf(stderr, _("Unable to write package lead: %s\n"),
++		Fstrerror(fdo));
++	    rc = RPMRC_FAIL;
++	    goto exit;
++	}
++
++	ssize_t fdilength = ufdCopy(fdi, fdo);
++	if (fdilength == -1) {
++	    fprintf(stderr, _("process_package cat failed\n"));
++	    rc = RPMRC_FAIL;
++	    goto exit;
++	}
++
++	goto exit;
++    } else {
+     if (rpmReadPackageRaw(fdi, &sigh, &h)) {
+ 	rpmlog(RPMLOG_ERR, _("Error reading package\n"));
+ 	exit(EXIT_FAILURE);
+     }
+ 
+-    if (rpmLeadWrite(fdo, h))
++    if (rpmLeadWriteFromHeader(fdo, h))
+     {
+ 	rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
+ 		Fstrerror(fdo));
+@@ -264,38 +312,41 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+ 	exit(EXIT_FAILURE);
+     }
+ 
+-    /* Retrieve payload size and compression type. */
+-    {
+-	const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
+-	rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
+-    }
++	/* Retrieve payload size and compression type. */
++	{
++	    const char *compr =
++		headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
++	    rpmio_flags =
++		rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
++	}
+ 
+-    gzdi = Fdopen(fdi, rpmio_flags);	/* XXX gzdi == fdi */
+-    free(rpmio_flags);
++	gzdi = Fdopen(fdi, rpmio_flags);	/* XXX gzdi == fdi */
++	free(rpmio_flags);
+ 
+     if (gzdi == NULL) {
+ 	rpmlog(RPMLOG_ERR, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
+ 	exit(EXIT_FAILURE);
+     }
+ 
+-    rpmfiles files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
+-    rpmfi fi = rpmfiNewArchiveReader(gzdi, files,
+-				     RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);
++	files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
++	fi = rpmfiNewArchiveReader(gzdi, files,
++				   RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);
+ 
+-    /* this is encoded in the file format, so needs to be fixed size (for
+-     * now?)
+-     */
+-    diglen = (uint32_t)rpmDigestLength(rpmfiDigestAlgo(fi));
+-    digestSet ds = digestSetCreate(rpmfiFC(fi), digestSetHash, digestSetCmp,
+-				   NULL);
+-    struct digestoffset offsets[rpmfiFC(fi)];
+-    pos = RPMLEAD_SIZE + headerSizeof(sigh, HEADER_MAGIC_YES);
++	/* this is encoded in the file format, so needs to be fixed size (for
++	 * now?)
++	 */
++	diglen = (uint32_t) rpmDigestLength(rpmfiDigestAlgo(fi));
++	digestSet ds =
++	    digestSetCreate(rpmfiFC(fi), digestSetHash, digestSetCmp,
++			    NULL);
++	struct digestoffset offsets[rpmfiFC(fi)];
++	pos = RPMLEAD_SIZE + headerSizeof(sigh, HEADER_MAGIC_YES);
+ 
+-    /* main headers are aligned to 8 byte boundry */
+-    pos += pad_to(pos, 8);
+-    pos += headerSizeof(h, HEADER_MAGIC_YES);
++	/* main headers are aligned to 8 byte boundry */
++	pos += pad_to(pos, 8);
++	pos += headerSizeof(h, HEADER_MAGIC_YES);
+ 
+-    zeros = xcalloc(fundamental_block_size, 1);
++	zeros = xcalloc(fundamental_block_size, 1);
+ 
+     while (next >= 0) {
+ 	next = rpmfiNext(fi);
+@@ -342,8 +393,8 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+     }
+     Fclose(gzdi);	/* XXX gzdi == fdi */
+ 
+-    qsort(offsets, (size_t)offset_ix, sizeof(struct digestoffset),
+-	  digestoffsetCmp);
++	qsort(offsets, (size_t) offset_ix, sizeof(struct digestoffset),
++	      digestoffsetCmp);
+ 
+     validation_pos = pos;
+     ssize_t validation_len = ufdCopy(validationi, fdo);
+@@ -412,6 +463,7 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+ 	rc = RPMRC_FAIL;
+ 	goto exit;
+     }
++	}
+ 
+ exit:
+     rpmfilesFree(files);
+diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
+index b4897f1de444080c8dc6c4913b5f33de20796822..d54e254ff41a0441d04fbcf27f26e4809f563b79 100644
+--- a/sign/rpmgensig.c
++++ b/sign/rpmgensig.c
+@@ -672,7 +672,7 @@ static int rpmSign(const char *rpm, int deleting, int flags)
+ 	}
+ 
+ 	/* Write the lead/signature of the output rpm */
+-	rc = rpmLeadWrite(ofd, h);
++	rc = rpmLeadWriteFromHeader(ofd, h);
+ 	if (rc != RPMRC_OK) {
+ 	    rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n"), trpm,
+ 		Fstrerror(ofd));
+diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at
+index 5135c9cf83d9e75e9d9bc0b84186ab10cc0cbcac..c9c79c5acd22b86704460f295712ce7ab5ee3259 100644
+--- a/tests/rpm2extents.at
++++ b/tests/rpm2extents.at
+@@ -95,6 +95,17 @@ runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64-signed.rpm; echo $?
+ [])
+ AT_CLEANUP
+ 
++# check that package in denylist is not transcoded
++AT_SETUP([rpm2extents denylist])
++AT_KEYWORDS([rpm2extents])
++AT_CHECK([
++export LIBREPO_TRANSCODE_RPMS_DENYLIST="vim,hello,cowsay"
++runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 | runroot_other cmp /data/RPMS/hello-2.0-1.x86_64.rpm -],
++[0],
++[],
++[ignore])
++AT_CLEANUP
++
+ AT_SETUP([rpm2extents install package])
+ AT_KEYWORDS([rpm2extents reflink])
+ AT_SKIP_IF([$REFLINK_DISABLED])
diff --git a/0032-rpmcow-workaround.patch b/0032-rpmcow-workaround.patch
new file mode 100644
index 0000000..69d5178
--- /dev/null
+++ b/0032-rpmcow-workaround.patch
@@ -0,0 +1,385 @@
+From: Richard Phibel <richardphibel@meta.com>
+
+Subject: RPM with Copy on Write: workaround for corrupt signature header
+
+commit 7976c921f60ec5d20c50c4c702ec5636b39210ba
+Author: Richard Phibel <richardphibel@meta.com>
+Date:   Wed Oct 26 18:57:19 2022 +0200
+
+    RPM with Copy on Write: workaround for corrupt signature header
+    
+    Some packages have errors in the signature header. These errors do not
+    prevent installation of the package but cause issues in rpm2extents
+    conversion. This commit implements the same fix as in
+    unloadImmutableRegion.
+
+Signed-off-by: Richard Phibel <richardphibel@meta.com>
+
+diff --git a/rpm2extents.c b/rpm2extents.c
+index 702d3765d76faf618992ca112011d2312d7fcdcc..b641511fff884e3c8fb396f28acbd8e2c736e28a 100644
+--- a/rpm2extents.c
++++ b/rpm2extents.c
+@@ -139,7 +139,7 @@ exit:
+  * @param package_name	package name
+  * @return 		true if package is in deny list
+  */
+-static inline int isInDenyList(char * package_name)
++static inline int isInDenyList(char *package_name)
+ {
+     int is_in_deny_list = 0;
+     if (package_name) {
+@@ -153,7 +153,7 @@ static inline int isInDenyList(char * package_name)
+ 	    denytlist_item = strtok(NULL, ",");
+ 	}
+     }
+-	return is_in_deny_list;
++    return is_in_deny_list;
+ }
+ 
+ static rpmRC FDWriteSignaturesValidation(FD_t fdo, int rpmvsrc, char *msg) {
+@@ -229,6 +229,22 @@ exit:
+     return rc;
+ }
+ 
++static void sanitizeSignatureHeader(Header * sigh)
++{
++    struct rpmtd_s td;
++
++    /* This is inspired by the code in unloadImmutableRegion. See https://github.com/rpm-software-management/rpm/pull/1330 */
++    if (!headerGet(*sigh, RPMTAG_HEADERSIGNATURES, &td, HEADERGET_DEFAULT)) {
++	/* Signature header corrupt/missing */
++	rpmlog(RPMLOG_WARNING, _("Error verifying signature header\n"));
++	rpmtdFreeData(&td);
++	Header nh = headerCopy(*sigh);
++	headerFree(*sigh);
++	*sigh = headerLink(nh);
++	headerFree(nh);
++    }
++}
++
+ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+ {
+     uint32_t diglen;
+@@ -261,7 +277,7 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+     uint32_t offset_ix = 0;
+     size_t len;
+     int next = 0;
+-	struct rpmlead_s l;
++    struct rpmlead_s l;
+     rpmfiles files = NULL;
+     rpmfi fi = NULL;
+     char *msg = NULL;
+@@ -274,43 +290,47 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+ 
+     /* Skip conversion if package is in deny list */
+     if (isInDenyList(l.name)) {
++	rpmlog(RPMLOG_WARNING, _("package %s is in deny list: conversion skipped\n"), l.name);
+ 	if (rpmLeadWrite(fdo, l)) {
+-		fprintf(stderr, _("Unable to write package lead: %s\n"),
+-		Fstrerror(fdo));
++	    rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
++		    Fstrerror(fdo));
+ 	    rc = RPMRC_FAIL;
+ 	    goto exit;
+ 	}
+ 
+ 	ssize_t fdilength = ufdCopy(fdi, fdo);
+ 	if (fdilength == -1) {
+-	    fprintf(stderr, _("process_package cat failed\n"));
++	    rpmlog(RPMLOG_ERR, _("process_package cat failed\n"));
+ 	    rc = RPMRC_FAIL;
+ 	    goto exit;
+ 	}
+ 
+ 	goto exit;
+     } else {
+-    if (rpmReadPackageRaw(fdi, &sigh, &h)) {
+-	rpmlog(RPMLOG_ERR, _("Error reading package\n"));
+-	exit(EXIT_FAILURE);
+-    }
++	if (rpmReadPackageRaw(fdi, &sigh, &h)) {
++	    rpmlog(RPMLOG_ERR, _("Error reading package\n"));
++	    exit(EXIT_FAILURE);
++	}
+ 
+-    if (rpmLeadWriteFromHeader(fdo, h))
+-    {
+-	rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
+-		Fstrerror(fdo));
+-	exit(EXIT_FAILURE);
+-    }
++	sanitizeSignatureHeader(&sigh);
+ 
+-    if (rpmWriteSignature(fdo, sigh)) {
+-	rpmlog(RPMLOG_ERR, _("Unable to write signature: %s\n"), Fstrerror(fdo));
+-	exit(EXIT_FAILURE);
+-    }
++	if (rpmLeadWriteFromHeader(fdo, h)) {
++	    rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
++		   Fstrerror(fdo));
++	    exit(EXIT_FAILURE);
++	}
+ 
+-    if (headerWrite(fdo, h, HEADER_MAGIC_YES)) {
+-	rpmlog(RPMLOG_ERR, _("Unable to write headers: %s\n"), Fstrerror(fdo));
+-	exit(EXIT_FAILURE);
+-    }
++	if (rpmWriteSignature(fdo, sigh)) {
++	    rpmlog(RPMLOG_ERR, _("Unable to write signature: %s\n"),
++		   Fstrerror(fdo));
++	    exit(EXIT_FAILURE);
++	}
++
++	if (headerWrite(fdo, h, HEADER_MAGIC_YES)) {
++	    rpmlog(RPMLOG_ERR, _("Unable to write headers: %s\n"),
++		   Fstrerror(fdo));
++	    exit(EXIT_FAILURE);
++	}
+ 
+ 	/* Retrieve payload size and compression type. */
+ 	{
+@@ -323,10 +343,11 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+ 	gzdi = Fdopen(fdi, rpmio_flags);	/* XXX gzdi == fdi */
+ 	free(rpmio_flags);
+ 
+-    if (gzdi == NULL) {
+-	rpmlog(RPMLOG_ERR, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
+-	exit(EXIT_FAILURE);
+-    }
++	if (gzdi == NULL) {
++	    rpmlog(RPMLOG_ERR, _("cannot re-open payload: %s\n"),
++		   Fstrerror(gzdi));
++	    exit(EXIT_FAILURE);
++	}
+ 
+ 	files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
+ 	fi = rpmfiNewArchiveReader(gzdi, files,
+@@ -348,124 +369,128 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
+ 
+ 	zeros = xcalloc(fundamental_block_size, 1);
+ 
+-    while (next >= 0) {
+-	next = rpmfiNext(fi);
+-	if (next == RPMERR_ITER_END) {
+-	    rc = RPMRC_OK;
+-	    break;
++	while (next >= 0) {
++	    next = rpmfiNext(fi);
++	    if (next == RPMERR_ITER_END) {
++		rc = RPMRC_OK;
++		break;
++	    }
++	    mode = rpmfiFMode(fi);
++	    if (!S_ISREG(mode) || !rpmfiArchiveHasContent(fi)) {
++		/* not a regular file, or the archive doesn't contain any content
++		 * for this entry.
++		 */
++		continue;
++	    }
++	    digest = rpmfiFDigest(fi, NULL, NULL);
++	    if (digestSetGetEntry(ds, digest, NULL)) {
++		/* This specific digest has already been included, so skip it. */
++		continue;
++	    }
++	    pad = pad_to(pos, fundamental_block_size);
++	    if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
++		rpmlog(RPMLOG_ERR, _("Unable to write padding\n"));
++		rc = RPMRC_FAIL;
++		goto exit;
++	    }
++	    /* round up to next fundamental_block_size */
++	    pos += pad;
++	    digestSetAddEntry(ds, digest);
++	    offsets[offset_ix].digest = digest;
++	    offsets[offset_ix].pos = pos;
++	    offset_ix++;
++	    size = rpmfiFSize(fi);
++	    rc = rpmfiArchiveReadToFile(fi, fdo, 0);
++	    if (rc != RPMRC_OK) {
++		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;
+ 	}
+-	mode = rpmfiFMode(fi);
+-	if (!S_ISREG(mode) || !rpmfiArchiveHasContent(fi)) {
+-	    /* not a regular file, or the archive doesn't contain any content
+-	     * for this entry.
+-	    */
+-	    continue;
++	Fclose(gzdi);		/* XXX gzdi == fdi */
++
++	qsort(offsets, (size_t) offset_ix, sizeof(struct digestoffset),
++	      digestoffsetCmp);
++
++	validation_pos = pos;
++	ssize_t validation_len = ufdCopy(validationi, fdo);
++	if (validation_len == -1) {
++	    rpmlog(RPMLOG_ERR, _("validation output ufdCopy failed\n"));
++	    rc = RPMRC_FAIL;
++	    goto exit;
+ 	}
+-	digest = rpmfiFDigest(fi, NULL, NULL);
+-	if (digestSetGetEntry(ds, digest, NULL)) {
+-	    /* This specific digest has already been included, so skip it. */
+-	    continue;
++
++	digest_table_pos = validation_pos + validation_len;
++
++	len = sizeof(offset_ix);
++	if (Fwrite(&offset_ix, len, 1, fdo) != len) {
++	    rpmlog(RPMLOG_ERR, _("Unable to write length of table\n"));
++	    rc = RPMRC_FAIL;
++	    goto exit;
+ 	}
+-	pad = pad_to(pos, fundamental_block_size);
+-	if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
+-	    rpmlog(RPMLOG_ERR, _("Unable to write padding\n"));
++	len = sizeof(diglen);
++	if (Fwrite(&diglen, len, 1, fdo) != len) {
++	    rpmlog(RPMLOG_ERR, _("Unable to write length of digest\n"));
+ 	    rc = RPMRC_FAIL;
+ 	    goto exit;
+ 	}
+-	/* round up to next fundamental_block_size */
+-	pos += pad;
+-	digestSetAddEntry(ds, digest);
+-	offsets[offset_ix].digest = digest;
+-	offsets[offset_ix].pos = pos;
+-	offset_ix++;
+-	size = rpmfiFSize(fi);
+-	rc = rpmfiArchiveReadToFile(fi, fdo, 0);
+-	if (rc != RPMRC_OK) {
+-	    char *errstr = rpmfileStrerror(rc);
+-	    rpmlog(RPMLOG_ERR,
+-		   _("rpmfiArchiveReadToFile failed while extracting "\
+-		   "\"%s\" with RC %d: %s\n"),
+-		   rpmfiFN(fi), rc, errstr);
+-	    free(errstr);
++	len = sizeof(rpm_loff_t);
++	for (int x = 0; x < offset_ix; x++) {
++	    if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen) {
++		rpmlog(RPMLOG_ERR, _("Unable to write digest\n"));
++		rc = RPMRC_FAIL;
++		goto exit;
++	    }
++	    if (Fwrite(&offsets[x].pos, len, 1, fdo) != len) {
++		rpmlog(RPMLOG_ERR, _("Unable to write offset\n"));
++		rc = RPMRC_FAIL;
++		goto exit;
++	    }
++	}
++	digest_pos =
++	    (digest_table_pos + sizeof(offset_ix) + sizeof(diglen) +
++	     offset_ix * (diglen + sizeof(rpm_loff_t))
++	    );
++
++	ssize_t digest_len = ufdCopy(digestori, fdo);
++	if (digest_len == -1) {
++	    rpmlog(RPMLOG_ERR, _("digest table ufdCopy failed\n"));
++	    rc = RPMRC_FAIL;
+ 	    goto exit;
+ 	}
+-	pos += size;
+-    }
+-    Fclose(gzdi);	/* XXX gzdi == fdi */
+-
+-	qsort(offsets, (size_t) offset_ix, sizeof(struct digestoffset),
+-	      digestoffsetCmp);
+ 
+-    validation_pos = pos;
+-    ssize_t validation_len = ufdCopy(validationi, fdo);
+-    if (validation_len == -1) {
+-	rpmlog(RPMLOG_ERR, _("validation output ufdCopy failed\n"));
+-	rc = RPMRC_FAIL;
+-	goto exit;
+-    }
+-
+-    digest_table_pos = validation_pos + validation_len;
++	/* 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.
++	 */
+ 
+-    len = sizeof(offset_ix);
+-    if (Fwrite(&offset_ix, len, 1, fdo) != len) {
+-	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) {
+-	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) {
+-	    rpmlog(RPMLOG_ERR, _("Unable to write digest\n"));
++	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) {
++	    rpmlog(RPMLOG_ERR, _("Unable to write final padding\n"));
+ 	    rc = RPMRC_FAIL;
+ 	    goto exit;
+ 	}
+-	if (Fwrite(&offsets[x].pos, len, 1, fdo) != len) {
+-	    rpmlog(RPMLOG_ERR, _("Unable to write offset\n"));
++	zeros = _free(zeros);
++	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;
+ 	}
+     }
+-    digest_pos = (
+-	digest_table_pos + sizeof(offset_ix) + sizeof(diglen) +
+-	offset_ix * (diglen + sizeof(rpm_loff_t))
+-    );
+-
+-    ssize_t digest_len = ufdCopy(digestori, fdo);
+-    if (digest_len == -1) {
+-	rpmlog(RPMLOG_ERR, _("digest table ufdCopy failed\n"));
+-	rc = RPMRC_FAIL;
+-	goto exit;
+-    }
+-
+-    /* 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.
+-    */
+ 
+-    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) {
+-	rpmlog(RPMLOG_ERR, _("Unable to write final padding\n"));
+-	rc = RPMRC_FAIL;
+-	goto exit;
+-    }
+-    zeros = _free(zeros);
+-    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;
+-    }
+-	}
+-
+-exit:
++  exit:
+     rpmfilesFree(files);
+     rpmfiFree(fi);
+     headerFree(h);
diff --git a/rpm.spec b/rpm.spec
index 0edc5a1..d4ff062 100644
--- a/rpm.spec
+++ b/rpm.spec
@@ -42,7 +42,7 @@
 
 %global rpmver 4.16.1.3
 #global snapver rc1
-%global rel 19.1
+%global rel 19.2
 %global sover 9
 
 %global srcver %{rpmver}%{?snapver:-%{snapver}}
@@ -181,6 +181,8 @@ Patch9927: 0027-rpmchecksig-Refactor-rpmpkgVerifySigs-with-custom-ve.patch
 Patch9928: 0028-reflink-remove-requirement-for-executable-stack-flag.patch
 Patch9929: 0029-extentsVerifySigs-Make-it-optional-to-print-the-sign.patch
 Patch9930: 0030-rpmcow-Make-rpm-i-install-package-without-the-need-o.patch
+Patch9931: 0031-rpmcow-denylist.patch
+Patch9932: 0032-rpmcow-workaround.patch
 Provides: rpm(pr1470)
 Provides: rpm(pr1470_1)
 
@@ -812,6 +814,9 @@ fi
 %{_datadir}/selinux/packages/rpm_hs.pp.bz2
 
 %changelog
+* Wed Nov 30 2022 Richard Phibel <richardphibel@meta.com> - 4.16.1.3-19.2
+- Add deny list support and workaround for RPM CoW
+
 * Sat Oct 29 2022 Richard Phibel <richardphibel@fb.com> - 4.16.1.3-19.1
 - Merge upstream changes for Hyperscale