From: Robert Yang <[email protected]>

The patch is from:
https://github.com/libarchive/libarchive/pull/2846

Fixed:
$ oe-selftest -r debuginfod.Debuginfod.test_debuginfod_native

cannot open archive from pipe 
/path/to/tmp-debuginfod/work/x86-64-v3-poky-linux/xz/5.8.2/localpkgfeed/x86_64_v3/bash-locale-vi-5.3-r0.x86_64_v3.rpm
libarchive error: cannot open archive from pipe: Unrecognized archive format
exceptions encountered during archive scan

Signed-off-by: Robert Yang <[email protected]>
---
 ...end_filter-Keep-iterating-even-if-na.patch |   48 +
 ...egister_bidder-Allow-ARCHIVE_STATE_H.patch |   45 +
 ...er-into-a-proper-format-supporting-b.patch | 1723 +++++++++++++++++
 .../libarchive/libarchive_3.8.6.bb            |    3 +
 4 files changed, 1819 insertions(+)
 create mode 100644 
meta/recipes-extended/libarchive/libarchive/0001-archive_read_append_filter-Keep-iterating-even-if-na.patch
 create mode 100644 
meta/recipes-extended/libarchive/libarchive/0002-__archive_read_register_bidder-Allow-ARCHIVE_STATE_H.patch
 create mode 100644 
meta/recipes-extended/libarchive/libarchive/0003-Convert-RPM-reader-into-a-proper-format-supporting-b.patch

diff --git 
a/meta/recipes-extended/libarchive/libarchive/0001-archive_read_append_filter-Keep-iterating-even-if-na.patch
 
b/meta/recipes-extended/libarchive/libarchive/0001-archive_read_append_filter-Keep-iterating-even-if-na.patch
new file mode 100644
index 0000000000..8e236cedc8
--- /dev/null
+++ 
b/meta/recipes-extended/libarchive/libarchive/0001-archive_read_append_filter-Keep-iterating-even-if-na.patch
@@ -0,0 +1,48 @@
+From 26401df2e74e6d72e86fab165445949c9dd3eba9 Mon Sep 17 00:00:00 2001
+From: Davide Beatrici <[email protected]>
+Date: Sat, 21 Feb 2026 02:55:40 +0100
+Subject: [PATCH 1/3] archive_read_append_filter(): Keep iterating even if name
+ is null
+
+While working on the RPM format I noticed the zstd filter failed to append.
+
+Turns out there are two unknown filters that are registered with a null name:
+
+bidder candidate bzip2
+bidder candidate compress (.Z)
+bidder candidate gzip
+bidder candidate lzip
+bidder candidate lzma
+bidder candidate xz
+bidder candidate uu
+bidder candidate lrzip
+bidder candidate (null)
+bidder candidate (null)
+bidder candidate lz4
+bidder candidate zstd
+
+I'm not sure if anonymous filters are expected behavior, but I believe this 
change doesn't hurt.
+
+Upstream-Status: Submitted [https://github.com/libarchive/libarchive/pull/2846]
+
+Signed-off-by: Robert Yang <[email protected]>
+---
+ libarchive/archive_read_append_filter.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libarchive/archive_read_append_filter.c 
b/libarchive/archive_read_append_filter.c
+index cd88df11..9475b704 100644
+--- a/libarchive/archive_read_append_filter.c
++++ b/libarchive/archive_read_append_filter.c
+@@ -117,7 +117,7 @@ archive_read_append_filter(struct archive *_a, int code)
+     bidder = a->bidders;
+     for (i = 1; i < number_bidders; i++, bidder++)
+     {
+-      if (!bidder->name || !strcmp(bidder->name, str))
++      if (bidder->name && !strcmp(bidder->name, str))
+         break;
+     }
+     if (!bidder->name || strcmp(bidder->name, str))
+-- 
+2.49.0
+
diff --git 
a/meta/recipes-extended/libarchive/libarchive/0002-__archive_read_register_bidder-Allow-ARCHIVE_STATE_H.patch
 
b/meta/recipes-extended/libarchive/libarchive/0002-__archive_read_register_bidder-Allow-ARCHIVE_STATE_H.patch
new file mode 100644
index 0000000000..3ddfedb27c
--- /dev/null
+++ 
b/meta/recipes-extended/libarchive/libarchive/0002-__archive_read_register_bidder-Allow-ARCHIVE_STATE_H.patch
@@ -0,0 +1,45 @@
+From 8eafdb93fd551bfed7184bc7519f5d455811cefb Mon Sep 17 00:00:00 2001
+From: Davide Beatrici <[email protected]>
+Date: Sat, 21 Feb 2026 05:33:36 +0100
+Subject: [PATCH 2/3] __archive_read_register_bidder(): Allow
+ ARCHIVE_STATE_HEADER, check if already registered
+
+This allows formats to apply filters when they know what they need.
+
+In the case of RPM, that's after parsing the (uncompressed) header.
+
+Upstream-Status: Submitted [https://github.com/libarchive/libarchive/pull/2846]
+
+Signed-off-by: Robert Yang <[email protected]>
+---
+ libarchive/archive_read.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c
+index c9b9d598..bc6305ae 100644
+--- a/libarchive/archive_read.c
++++ b/libarchive/archive_read.c
+@@ -1232,13 +1232,18 @@ __archive_read_register_bidder(struct archive_read *a,
+       int i, number_slots;
+ 
+       archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC,
+-          ARCHIVE_STATE_NEW, "__archive_read_register_bidder");
++          ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER,
++              "__archive_read_register_bidder");
+ 
+       number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]);
+ 
+       for (i = 0; i < number_slots; i++) {
+-              if (a->bidders[i].vtable != NULL)
++              if (a->bidders[i].vtable != NULL) {
++                      if (a->bidders[i].vtable == vtable)
++                              /* Already registered. */
++                              return (ARCHIVE_OK);
+                       continue;
++              }
+               memset(a->bidders + i, 0, sizeof(a->bidders[0]));
+               bidder = (a->bidders + i);
+               bidder->data = bidder_data;
+-- 
+2.49.0
+
diff --git 
a/meta/recipes-extended/libarchive/libarchive/0003-Convert-RPM-reader-into-a-proper-format-supporting-b.patch
 
b/meta/recipes-extended/libarchive/libarchive/0003-Convert-RPM-reader-into-a-proper-format-supporting-b.patch
new file mode 100644
index 0000000000..b231042f93
--- /dev/null
+++ 
b/meta/recipes-extended/libarchive/libarchive/0003-Convert-RPM-reader-into-a-proper-format-supporting-b.patch
@@ -0,0 +1,1723 @@
+From b31625af1c540e26da4c387eb0a6a81f7cf9b5a9 Mon Sep 17 00:00:00 2001
+From: Davide Beatrici <[email protected]>
+Date: Wed, 4 Mar 2026 22:58:41 +0100
+Subject: [PATCH 3/3] Convert RPM reader into a proper format, supporting both
+ stripped CPIO and SVR4
+
+Upstream-Status: Submitted [https://github.com/libarchive/libarchive/pull/2846]
+
+Signed-off-by: Robert Yang <[email protected]>
+---
+ Makefile.am                                   |    2 +-
+ contrib/android/Android.mk                    |    2 +-
+ libarchive/CMakeLists.txt                     |    2 +-
+ libarchive/archive.h                          |    5 +-
+ libarchive/archive_read_append_filter.c       |    4 -
+ libarchive/archive_read_private.h             |    2 +-
+ libarchive/archive_read_set_format.c          |    3 +
+ libarchive/archive_read_support_filter_all.c  |    2 -
+ .../archive_read_support_filter_by_code.c     |    2 -
+ libarchive/archive_read_support_filter_rpm.c  |  294 -----
+ libarchive/archive_read_support_format_all.c  |    1 +
+ libarchive/archive_read_support_format_rpm.c  | 1126 +++++++++++++++++
+ libarchive/test/test_archive_read_support.c   |    2 +-
+ .../test_read_format_cpio_svr4_bzip2_rpm.c    |    4 +-
+ .../test_read_format_cpio_svr4_gzip_rpm.c     |    6 +-
+ libarchive/test/test_read_format_huge_rpm.c   |    4 +-
+ 16 files changed, 1142 insertions(+), 319 deletions(-)
+ delete mode 100644 libarchive/archive_read_support_filter_rpm.c
+ create mode 100644 libarchive/archive_read_support_format_rpm.c
+
+diff --git a/Makefile.am b/Makefile.am
+index b6bf5482..ec4cf678 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -183,7 +183,6 @@ libarchive_la_SOURCES= \
+       libarchive/archive_read_support_filter_lzop.c \
+       libarchive/archive_read_support_filter_none.c \
+       libarchive/archive_read_support_filter_program.c \
+-      libarchive/archive_read_support_filter_rpm.c \
+       libarchive/archive_read_support_filter_uu.c \
+       libarchive/archive_read_support_filter_xz.c \
+       libarchive/archive_read_support_filter_zstd.c \
+@@ -200,6 +199,7 @@ libarchive_la_SOURCES= \
+       libarchive/archive_read_support_format_rar.c \
+       libarchive/archive_read_support_format_rar5.c \
+       libarchive/archive_read_support_format_raw.c \
++      libarchive/archive_read_support_format_rpm.c \
+       libarchive/archive_read_support_format_tar.c \
+       libarchive/archive_read_support_format_warc.c \
+       libarchive/archive_read_support_format_xar.c \
+diff --git a/contrib/android/Android.mk b/contrib/android/Android.mk
+index 20e46a69..dc54c6b5 100644
+--- a/contrib/android/Android.mk
++++ b/contrib/android/Android.mk
+@@ -74,7 +74,6 @@ libarchive_src_files := libarchive/archive_acl.c \
+                                               
libarchive/archive_read_support_filter_lzop.c \
+                                               
libarchive/archive_read_support_filter_none.c \
+                                               
libarchive/archive_read_support_filter_program.c \
+-                                              
libarchive/archive_read_support_filter_rpm.c \
+                                               
libarchive/archive_read_support_filter_uu.c \
+                                               
libarchive/archive_read_support_filter_xz.c \
+                                               
libarchive/archive_read_support_filter_zstd.c \
+@@ -91,6 +90,7 @@ libarchive_src_files := libarchive/archive_acl.c \
+                                               
libarchive/archive_read_support_format_rar.c \
+                                               
libarchive/archive_read_support_format_rar5.c \
+                                               
libarchive/archive_read_support_format_raw.c \
++                                              
libarchive/archive_read_support_format_rpm.c \
+                                               
libarchive/archive_read_support_format_tar.c \
+                                               
libarchive/archive_read_support_format_warc.c \
+                                               
libarchive/archive_read_support_format_xar.c \
+diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt
+index 4fb91713..19134451 100644
+--- a/libarchive/CMakeLists.txt
++++ b/libarchive/CMakeLists.txt
+@@ -92,7 +92,6 @@ SET(libarchive_SOURCES
+   archive_read_support_filter_lzop.c
+   archive_read_support_filter_none.c
+   archive_read_support_filter_program.c
+-  archive_read_support_filter_rpm.c
+   archive_read_support_filter_uu.c
+   archive_read_support_filter_xz.c
+   archive_read_support_filter_zstd.c
+@@ -109,6 +108,7 @@ SET(libarchive_SOURCES
+   archive_read_support_format_rar.c
+   archive_read_support_format_rar5.c
+   archive_read_support_format_raw.c
++  archive_read_support_format_rpm.c
+   archive_read_support_format_tar.c
+   archive_read_support_format_warc.c
+   archive_read_support_format_xar.c
+diff --git a/libarchive/archive.h b/libarchive/archive.h
+index de472a18..7d776699 100644
+--- a/libarchive/archive.h
++++ b/libarchive/archive.h
+@@ -312,7 +312,7 @@ typedef const char *archive_passphrase_callback(struct 
archive *,
+ #define       ARCHIVE_FILTER_LZMA     5
+ #define       ARCHIVE_FILTER_XZ       6
+ #define       ARCHIVE_FILTER_UU       7
+-#define       ARCHIVE_FILTER_RPM      8
++/*#define     ARCHIVE_FILTER_RPM      8*/
+ #define       ARCHIVE_FILTER_LZIP     9
+ #define       ARCHIVE_FILTER_LRZIP    10
+ #define       ARCHIVE_FILTER_LZOP     11
+@@ -383,6 +383,7 @@ typedef const char *archive_passphrase_callback(struct 
archive *,
+ #define       ARCHIVE_FORMAT_7ZIP                     0xE0000
+ #define       ARCHIVE_FORMAT_WARC                     0xF0000
+ #define       ARCHIVE_FORMAT_RAR_V5                   0x100000
++#define       ARCHIVE_FORMAT_RPM                      0x110000
+ 
+ /*
+  * Codes returned by archive_read_format_capabilities().
+@@ -476,7 +477,6 @@ __LA_DECL int archive_read_support_filter_program(struct 
archive *,
+ __LA_DECL int archive_read_support_filter_program_signature
+               (struct archive *, const char * /* cmd */,
+                                   const void * /* match */, size_t);
+-__LA_DECL int archive_read_support_filter_rpm(struct archive *);
+ __LA_DECL int archive_read_support_filter_uu(struct archive *);
+ __LA_DECL int archive_read_support_filter_xz(struct archive *);
+ __LA_DECL int archive_read_support_filter_zstd(struct archive *);
+@@ -497,6 +497,7 @@ __LA_DECL int archive_read_support_format_mtree(struct 
archive *);
+ __LA_DECL int archive_read_support_format_rar(struct archive *);
+ __LA_DECL int archive_read_support_format_rar5(struct archive *);
+ __LA_DECL int archive_read_support_format_raw(struct archive *);
++__LA_DECL int archive_read_support_format_rpm(struct archive *);
+ __LA_DECL int archive_read_support_format_tar(struct archive *);
+ __LA_DECL int archive_read_support_format_warc(struct archive *);
+ __LA_DECL int archive_read_support_format_xar(struct archive *);
+diff --git a/libarchive/archive_read_append_filter.c 
b/libarchive/archive_read_append_filter.c
+index 9475b704..23e6a79c 100644
+--- a/libarchive/archive_read_append_filter.c
++++ b/libarchive/archive_read_append_filter.c
+@@ -80,10 +80,6 @@ archive_read_append_filter(struct archive *_a, int code)
+       strcpy(str, "uu");
+       r1 = archive_read_support_filter_uu(_a);
+       break;
+-    case ARCHIVE_FILTER_RPM:
+-      strcpy(str, "rpm");
+-      r1 = archive_read_support_filter_rpm(_a);
+-      break;
+     case ARCHIVE_FILTER_LZ4:
+       strcpy(str, "lz4");
+       r1 = archive_read_support_filter_lz4(_a);
+diff --git a/libarchive/archive_read_private.h 
b/libarchive/archive_read_private.h
+index 0c374f48..7efcf51a 100644
+--- a/libarchive/archive_read_private.h
++++ b/libarchive/archive_read_private.h
+@@ -205,7 +205,7 @@ struct archive_read {
+               int     (*cleanup)(struct archive_read *);
+               int     (*format_capabilties)(struct archive_read *);
+               int     (*has_encrypted_entries)(struct archive_read *);
+-      }       formats[16];
++      }       formats[18];
+       struct archive_format_descriptor        *format; /* Active format. */
+ 
+       /*
+diff --git a/libarchive/archive_read_set_format.c 
b/libarchive/archive_read_set_format.c
+index 552ab12d..6a176e3b 100644
+--- a/libarchive/archive_read_set_format.c
++++ b/libarchive/archive_read_set_format.c
+@@ -81,6 +81,9 @@ archive_read_set_format(struct archive *_a, int code)
+     case ARCHIVE_FORMAT_RAW:
+       str = "raw";
+       break;
++    case ARCHIVE_FORMAT_RPM:
++      str = "rpm";
++      break;
+     case ARCHIVE_FORMAT_TAR:
+       str = "tar";
+       break;
+diff --git a/libarchive/archive_read_support_filter_all.c 
b/libarchive/archive_read_support_filter_all.c
+index cb46d120..0f91e326 100644
+--- a/libarchive/archive_read_support_filter_all.c
++++ b/libarchive/archive_read_support_filter_all.c
+@@ -60,8 +60,6 @@ archive_read_support_filter_all(struct archive *a)
+       archive_read_support_filter_xz(a);
+       /* The decode code doesn't use an outside library. */
+       archive_read_support_filter_uu(a);
+-      /* The decode code doesn't use an outside library. */
+-      archive_read_support_filter_rpm(a);
+       /* The decode code always uses "lrzip -q -d" command-line. */
+       archive_read_support_filter_lrzip(a);
+       /* Lzop decompress falls back to "lzop -d" command-line. */
+diff --git a/libarchive/archive_read_support_filter_by_code.c 
b/libarchive/archive_read_support_filter_by_code.c
+index 4c8b6cb5..1c9a405b 100644
+--- a/libarchive/archive_read_support_filter_by_code.c
++++ b/libarchive/archive_read_support_filter_by_code.c
+@@ -49,8 +49,6 @@ archive_read_support_filter_by_code(struct archive *a, int 
filter_code)
+               return archive_read_support_filter_xz(a);
+       case ARCHIVE_FILTER_UU:
+               return archive_read_support_filter_uu(a);
+-      case ARCHIVE_FILTER_RPM:
+-              return archive_read_support_filter_rpm(a);
+       case ARCHIVE_FILTER_LZIP:
+               return archive_read_support_filter_lzip(a);
+       case ARCHIVE_FILTER_LRZIP:
+diff --git a/libarchive/archive_read_support_filter_rpm.c 
b/libarchive/archive_read_support_filter_rpm.c
+deleted file mode 100644
+index 25ace4a2..00000000
+--- a/libarchive/archive_read_support_filter_rpm.c
++++ /dev/null
+@@ -1,294 +0,0 @@
+-/*-
+- * Copyright (c) 2009 Michihiro NAKAJIMA
+- * All rights reserved.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- *    notice, this list of conditions and the following disclaimer.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- *    notice, this list of conditions and the following disclaimer in the
+- *    documentation and/or other materials provided with the distribution.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- */
+-
+-#include "archive_platform.h"
+-
+-#ifdef HAVE_ERRNO_H
+-#include <errno.h>
+-#endif
+-#ifdef HAVE_STDLIB_H
+-#include <stdlib.h>
+-#endif
+-
+-#include "archive.h"
+-#include "archive_endian.h"
+-#include "archive_private.h"
+-#include "archive_read_private.h"
+-
+-struct rpm {
+-      int64_t          total_in;
+-      uint64_t         hpos;
+-      uint64_t         hlen;
+-      unsigned char    header[16];
+-      enum {
+-              ST_LEAD,        /* Skipping 'Lead' section. */
+-              ST_HEADER,      /* Reading 'Header' section;
+-                               * first 16 bytes. */
+-              ST_HEADER_DATA, /* Skipping 'Header' section. */
+-              ST_PADDING,     /* Skipping padding data after the
+-                               * 'Header' section. */
+-              ST_ARCHIVE      /* Reading 'Archive' section. */
+-      }                state;
+-      int              first_header;
+-};
+-#define RPM_LEAD_SIZE         96      /* Size of 'Lead' section. */
+-#define RPM_MIN_HEAD_SIZE     16      /* Minimum size of 'Head'. */
+-
+-static int    rpm_bidder_bid(struct archive_read_filter_bidder *,
+-                  struct archive_read_filter *);
+-static int    rpm_bidder_init(struct archive_read_filter *);
+-
+-static ssize_t        rpm_filter_read(struct archive_read_filter *,
+-                  const void **);
+-static int    rpm_filter_close(struct archive_read_filter *);
+-
+-static inline size_t rpm_limit_bytes(uint64_t, size_t);
+-
+-#if ARCHIVE_VERSION_NUMBER < 4000000
+-/* Deprecated; remove in libarchive 4.0 */
+-int
+-archive_read_support_compression_rpm(struct archive *a)
+-{
+-      return archive_read_support_filter_rpm(a);
+-}
+-#endif
+-
+-static const struct archive_read_filter_bidder_vtable
+-rpm_bidder_vtable = {
+-      .bid = rpm_bidder_bid,
+-      .init = rpm_bidder_init,
+-};
+-
+-int
+-archive_read_support_filter_rpm(struct archive *_a)
+-{
+-      struct archive_read *a = (struct archive_read *)_a;
+-
+-      return __archive_read_register_bidder(a, NULL, "rpm",
+-                      &rpm_bidder_vtable);
+-}
+-
+-static int
+-rpm_bidder_bid(struct archive_read_filter_bidder *self,
+-    struct archive_read_filter *filter)
+-{
+-      const unsigned char *b;
+-      ssize_t avail;
+-      int bits_checked;
+-
+-      (void)self; /* UNUSED */
+-
+-      b = __archive_read_filter_ahead(filter, 8, &avail);
+-      if (b == NULL)
+-              return (0);
+-
+-      bits_checked = 0;
+-      /*
+-       * Verify Header Magic Bytes : 0XED 0XAB 0XEE 0XDB
+-       */
+-      if (memcmp(b, "\xED\xAB\xEE\xDB", 4) != 0)
+-              return (0);
+-      bits_checked += 32;
+-      /*
+-       * Check major version.
+-       */
+-      if (b[4] != 3 && b[4] != 4)
+-              return (0);
+-      bits_checked += 8;
+-      /*
+-       * Check package type; binary or source.
+-       */
+-      if (b[6] != 0)
+-              return (0);
+-      bits_checked += 8;
+-      if (b[7] != 0 && b[7] != 1)
+-              return (0);
+-      bits_checked += 8;
+-
+-      return (bits_checked);
+-}
+-
+-static const struct archive_read_filter_vtable
+-rpm_reader_vtable = {
+-      .read = rpm_filter_read,
+-      .close = rpm_filter_close,
+-};
+-
+-static int
+-rpm_bidder_init(struct archive_read_filter *self)
+-{
+-      struct rpm   *rpm;
+-
+-      self->code = ARCHIVE_FILTER_RPM;
+-      self->name = "rpm";
+-
+-      rpm = calloc(1, sizeof(*rpm));
+-      if (rpm == NULL) {
+-              archive_set_error(&self->archive->archive, ENOMEM,
+-                  "Can't allocate data for rpm");
+-              return (ARCHIVE_FATAL);
+-      }
+-
+-      self->data = rpm;
+-      rpm->state = ST_LEAD;
+-      self->vtable = &rpm_reader_vtable;
+-
+-      return (ARCHIVE_OK);
+-}
+-
+-static inline size_t
+-rpm_limit_bytes(uint64_t bytes, size_t max)
+-{
+-      return (bytes > max ? max : (size_t)bytes);
+-}
+-
+-static ssize_t
+-rpm_filter_read(struct archive_read_filter *self, const void **buff)
+-{
+-      struct rpm *rpm;
+-      const unsigned char *b;
+-      ssize_t avail_in, total, used;
+-      size_t n;
+-      uint64_t section;
+-      uint64_t bytes;
+-
+-      rpm = (struct rpm *)self->data;
+-      *buff = NULL;
+-      total = avail_in = 0;
+-      b = NULL;
+-      used = 0;
+-      do {
+-              if (b == NULL) {
+-                      b = __archive_read_filter_ahead(self->upstream, 1,
+-                          &avail_in);
+-                      if (b == NULL) {
+-                              if (avail_in < 0)
+-                                      return (ARCHIVE_FATAL);
+-                              else
+-                                      break;
+-                      }
+-              }
+-
+-              switch (rpm->state) {
+-              case ST_LEAD:
+-                      if (rpm->total_in + avail_in < RPM_LEAD_SIZE)
+-                              used += avail_in;
+-                      else {
+-                              n = (size_t)(RPM_LEAD_SIZE - rpm->total_in);
+-                              used += n;
+-                              b += n;
+-                              rpm->state = ST_HEADER;
+-                              rpm->hpos = 0;
+-                              rpm->hlen = 0;
+-                              rpm->first_header = 1;
+-                      }
+-                      break;
+-              case ST_HEADER:
+-                      n = rpm_limit_bytes(RPM_MIN_HEAD_SIZE - rpm->hpos,
+-                          avail_in - used);
+-                      memcpy(rpm->header+rpm->hpos, b, n);
+-                      b += n;
+-                      used += n;
+-                      rpm->hpos += n;
+-
+-                      if (rpm->hpos == RPM_MIN_HEAD_SIZE) {
+-                              if (rpm->header[0] != 0x8e ||
+-                                  rpm->header[1] != 0xad ||
+-                                  rpm->header[2] != 0xe8 ||
+-                                  rpm->header[3] != 0x01) {
+-                                      if (rpm->first_header) {
+-                                              archive_set_error(
+-                                                  &self->archive->archive,
+-                                                  ARCHIVE_ERRNO_FILE_FORMAT,
+-                                                  "Unrecognized rpm header");
+-                                              return (ARCHIVE_FATAL);
+-                                      }
+-                                      rpm->state = ST_ARCHIVE;
+-                                      *buff = rpm->header;
+-                                      total = RPM_MIN_HEAD_SIZE;
+-                                      break;
+-                              }
+-                              /* Calculate 'Header' length. */
+-                              section = archive_be32dec(rpm->header+8);
+-                              bytes = archive_be32dec(rpm->header+12);
+-                              rpm->hlen = rpm->hpos + section * 16 + bytes;
+-                              rpm->state = ST_HEADER_DATA;
+-                              rpm->first_header = 0;
+-                      }
+-                      break;
+-              case ST_HEADER_DATA:
+-                      n = rpm_limit_bytes(rpm->hlen - rpm->hpos,
+-                          avail_in - used);
+-                      b += n;
+-                      used += n;
+-                      rpm->hpos += n;
+-                      if (rpm->hpos == rpm->hlen)
+-                              rpm->state = ST_PADDING;
+-                      break;
+-              case ST_PADDING:
+-                      while (used < avail_in) {
+-                              if (*b != 0) {
+-                                      /* Read next header. */
+-                                      rpm->state = ST_HEADER;
+-                                      rpm->hpos = 0;
+-                                      rpm->hlen = 0;
+-                                      break;
+-                              }
+-                              b++;
+-                              used++;
+-                      }
+-                      break;
+-              case ST_ARCHIVE:
+-                      *buff = b;
+-                      total = avail_in;
+-                      used = avail_in;
+-                      break;
+-              }
+-              if (used == avail_in) {
+-                      rpm->total_in += used;
+-                      __archive_read_filter_consume(self->upstream, used);
+-                      b = NULL;
+-                      used = 0;
+-              }
+-      } while (total == 0 && avail_in > 0);
+-
+-      if (used > 0 && b != NULL) {
+-              rpm->total_in += used;
+-              __archive_read_filter_consume(self->upstream, used);
+-      }
+-      return (total);
+-}
+-
+-static int
+-rpm_filter_close(struct archive_read_filter *self)
+-{
+-      struct rpm *rpm;
+-
+-      rpm = (struct rpm *)self->data;
+-      free(rpm);
+-
+-      return (ARCHIVE_OK);
+-}
+-
+diff --git a/libarchive/archive_read_support_format_all.c 
b/libarchive/archive_read_support_format_all.c
+index 3b53c9ad..067f2745 100644
+--- a/libarchive/archive_read_support_format_all.c
++++ b/libarchive/archive_read_support_format_all.c
+@@ -58,6 +58,7 @@ archive_read_support_format_all(struct archive *a)
+       archive_read_support_format_empty(a);
+       archive_read_support_format_lha(a);
+       archive_read_support_format_mtree(a);
++      archive_read_support_format_rpm(a);
+       archive_read_support_format_tar(a);
+       archive_read_support_format_xar(a);
+       archive_read_support_format_warc(a);
+diff --git a/libarchive/archive_read_support_format_rpm.c 
b/libarchive/archive_read_support_format_rpm.c
+new file mode 100644
+index 00000000..fe0e5009
+--- /dev/null
++++ b/libarchive/archive_read_support_format_rpm.c
+@@ -0,0 +1,1126 @@
++/*-
++ * Copyright (c) 2026 Davide Beatrici
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "archive_platform.h"
++
++#ifdef HAVE_ERRNO_H
++#include <errno.h>
++#endif
++
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++#ifdef HAVE_STRING_H
++#include <string.h>
++#endif
++
++#include "archive.h"
++#include "archive_endian.h"
++#include "archive_entry.h"
++#include "archive_entry_locale.h"
++#include "archive_private.h"
++#include "archive_read_private.h"
++
++#define MAX_NFILES            100000
++#define STR_SIZE_LIMIT        (1024 * 1024)   /* 1 MiB */
++
++#define LEAD_MAGIC            "\xed\xab\xee\xdb"
++#define HEADER_MAGIC  "\x8e\xad\xe8\x01\x00\x00\x00\x00"
++
++#define CPIO_END_MARK         "TRAILER!!!"
++#define CPIO_END_MARK_SIZE    10
++
++#define CPIO_HEADER_STR_SIZE          16
++#define CPIO_HEADER_SVR_SIZE          110
++#define CPIO_HEADER_SVR_PATH_OFF      94
++
++#define CPIO_MAGIC_SIZE                       6
++#define CPIO_MAGIC_STR                        "07070X"
++#define CPIO_MAGIC_SVR4_CRC           "070702"
++#define CPIO_MAGIC_SVR4_NOCRC "070701"
++
++#define TAG_FILESIZES         1028
++#define TAG_FILEMODES         1030
++#define TAG_FILERDEVS         1033
++#define TAG_FILEMTIMES                1034
++#define TAG_FILEUSERNAMES     1039
++#define TAG_FILEGROUPNAMES    1040
++#define TAG_FILEDEVICES               1095
++#define TAG_FILEINODES                1096
++
++#define TAG_DIRINDEXES        1116
++#define TAG_BASENAMES 1117
++#define TAG_DIRNAMES  1118
++
++#define TAG_PAYLOADCOMPRESSOR 1125
++
++#define TAG_LONGFILESIZES     5008
++
++enum rpm_cpio_format {
++      CPIO_UNKNOWN,
++      CPIO_STR,
++      CPIO_SVR4_CRC,
++      CPIO_SVR4_NOCRC
++};
++
++struct rpm_file_info {
++      char            *pathname;
++      char            *uname;
++      char            *gname;
++      uint64_t        size;
++      uint16_t        mode;
++      int32_t         dev;
++      int16_t         rdev;
++      uint32_t        mtime;
++      uint32_t        ino;
++};
++
++struct rpm_inode_info {
++      uint32_t                                n_files;
++      struct rpm_file_info    **files;
++      uint32_t                                n_processed;
++};
++
++struct rpm_inode_temp_entry {
++      uint64_t ino;
++      struct rpm_file_info **files;
++      uint32_t n_files;
++      size_t capacity;
++      struct rpm_inode_temp_entry *next;
++};
++
++struct rpm_lead {
++    unsigned char     magic[4];
++    unsigned char     major, minor;
++    short                     type;
++    short                     archnum;
++    char                      name[66];
++    short                     osnum;
++    short                     signature_type;
++    char                      reserved[16];
++};
++
++struct rpm_header {
++      unsigned char   magic[8];
++      uint32_t                n_entries;
++      uint32_t                data_size;
++};
++
++struct rpm_entry {
++      uint32_t        tag;
++      uint32_t        type;
++      int32_t         offset;
++      uint32_t        count;
++};
++
++struct rpm {
++      enum {
++              ST_LEAD,
++              ST_HEADER,
++              ST_PADDING,
++              ST_ARCHIVE
++      }       state;
++      uint8_t first_header;
++
++      char    *compressor;
++
++      uint32_t                                n_files;
++      uint32_t                                n_inodes;
++      struct rpm_file_info    *files;
++      struct rpm_inode_info   *inodes;
++
++      struct inode_hash_entry {
++              uint64_t ino;
++              struct rpm_inode_info *info;
++              struct inode_hash_entry *next;
++      }       **inode_hash;
++
++      size_t  inode_hash_size;
++
++      ssize_t  entry_bytes_remaining;
++      ssize_t  entry_bytes_unconsumed;
++      ssize_t  entry_offset;
++      ssize_t  entry_padding;
++};
++
++static int archive_read_format_rpm_bid(struct archive_read *, int);
++static int archive_read_format_rpm_read_header(struct archive_read *,
++      struct archive_entry *);
++static int archive_read_format_rpm_read_data(struct archive_read *,
++      const void **, size_t *, int64_t *);
++static int archive_read_format_rpm_read_data_skip(struct archive_read *);
++static int archive_read_format_rpm_cleanup(struct archive_read *);
++
++static int rpm_add_entry(struct archive_read *, struct archive_entry *);
++static int    rpm_parse_main_header(struct archive_read *,
++      const struct rpm_header *header);
++
++static struct rpm_inode_info *rpm_get_inode(struct archive_read *, uint32_t);
++static enum rpm_cpio_format rpm_get_cpio_format(struct archive_read *);
++static uint8_t rpm_is_eof(struct archive_read *);
++
++static uint16_t       rpm_be16_at(const void *buf_start,
++      const void *buf_end, const size_t off);
++static uint32_t       rpm_be32_at(const void *buf_start,
++      const void *buf_end, const size_t off);
++static uint64_t       rpm_be64_at(const void *buf_start,
++      const void *buf_end, const size_t off);
++
++static inline size_t  rpm_limit_bytes(size_t, size_t);
++static char   *rpm_strndup(struct archive_read *, const char *, size_t);
++static char   *rpm_strread(struct archive_read *, size_t);
++static void   rpm_strcat(struct archive_string *, const void *, const void *);
++static const char     *rpm_strlist_at(const char *, const void *,
++      uint64_t, uint64_t);
++
++static void   rpm_free_inode_temp_hash(struct rpm_inode_temp_entry **, 
size_t);
++
++int
++archive_read_support_format_rpm(struct archive *_a)
++{
++      struct archive_read *a = (struct archive_read *)_a;
++      struct rpm *rpm;
++      int r;
++
++      archive_check_magic(_a, ARCHIVE_READ_MAGIC,
++          ARCHIVE_STATE_NEW, "archive_read_support_format_rpm");
++
++      rpm = calloc(1, sizeof(*rpm));
++      if (!rpm) {
++              archive_set_error(&a->archive,
++                      ENOMEM,
++                      "Can't allocate rpm data");
++              return ARCHIVE_FATAL;
++      }
++
++      r = __archive_read_register_format(a,
++          rpm,
++          "rpm",
++          archive_read_format_rpm_bid,
++          NULL,
++          archive_read_format_rpm_read_header,
++          archive_read_format_rpm_read_data,
++          archive_read_format_rpm_read_data_skip,
++          NULL,
++          archive_read_format_rpm_cleanup,
++          NULL,
++          NULL);
++
++      if (r != ARCHIVE_OK)
++              free(rpm);
++
++      return ARCHIVE_OK;
++}
++
++static int
++archive_read_format_rpm_bid(struct archive_read *a, int best_bid)
++{
++      const unsigned char *p;
++
++      (void)best_bid;
++
++      if ((p = __archive_read_ahead(a, sizeof(LEAD_MAGIC) - 1, NULL)) == NULL)
++              return -1;
++
++      if (memcmp(p, LEAD_MAGIC, sizeof(LEAD_MAGIC) - 1) == 0)
++              return 48;
++      else
++              return ARCHIVE_WARN;
++}
++
++static int
++archive_read_format_rpm_read_header(struct archive_read *a,
++    struct archive_entry *entry)
++{
++      struct rpm *rpm = a->format->data;
++      const unsigned char *p;
++      int r;
++
++      a->archive.archive_format = ARCHIVE_FORMAT_RPM;
++
++      for (;;) {
++              switch (rpm->state) {
++              case ST_LEAD: {
++                      const struct rpm_lead *lead = __archive_read_ahead(a, 
sizeof(*lead), NULL);
++                      if (lead == NULL) {
++                              archive_set_error(&a->archive,
++                                      ARCHIVE_ERRNO_FILE_FORMAT,
++                                      "Truncated lead");
++                              return ARCHIVE_FATAL;
++                      }
++
++                      if (memcmp(lead->magic, LEAD_MAGIC, 
sizeof(lead->magic)) != 0) {
++                              archive_set_error(&a->archive,
++                                      ARCHIVE_ERRNO_FILE_FORMAT,
++                                      "Unrecognized lead");
++                              return ARCHIVE_FATAL;
++                      }
++
++                      __archive_read_consume(a, sizeof(*lead));
++
++                      rpm->state = ST_HEADER;
++                      rpm->first_header = 1;
++                      break;
++              }
++              case ST_HEADER: {
++                      struct rpm_header header;
++
++                      p = __archive_read_ahead(a, sizeof(header), NULL);
++                      if (p == NULL) {
++                              archive_set_error(&a->archive,
++                                      ARCHIVE_ERRNO_FILE_FORMAT,
++                                      "Truncated header");
++                              return ARCHIVE_FATAL;
++                      }
++
++                      memcpy(&header, p, sizeof(header));
++
++                      if (memcmp(header.magic, HEADER_MAGIC, 
sizeof(header.magic)) != 0) {
++                              archive_set_error(&a->archive,
++                                      ARCHIVE_ERRNO_FILE_FORMAT,
++                                      "Unrecognized header");
++                              return ARCHIVE_FATAL;
++                      }
++
++                      header.n_entries = archive_be32dec(&header.n_entries);
++                      header.data_size = archive_be32dec(&header.data_size);
++
++                      __archive_read_consume(a, sizeof(header));
++
++                      r = rpm_parse_main_header(a, &header);
++                      if (r != ARCHIVE_OK)
++                              return r;
++
++                      rpm->state = ST_PADDING;
++                      break;
++              }
++              case ST_PADDING: {
++                      for (;;) {
++                              p = __archive_read_ahead(a, 1, NULL);
++                              if (p == NULL) {
++                                      archive_set_error(&a->archive,
++                                              ARCHIVE_ERRNO_FILE_FORMAT,
++                                              "Truncated padding");
++                                      return ARCHIVE_FATAL;
++                              }
++
++                              if (*p != 0)
++                                      break;
++
++                              __archive_read_consume(a, 1);
++                      }
++
++                      if (rpm->first_header) {
++                              rpm->first_header = 0;
++                              rpm->state = ST_HEADER;
++                      } else {
++                              enum rpm_cpio_format cpio_format;
++
++                              if (!rpm->compressor) {
++                                      /* No compression. */
++                              } else if (strcmp(rpm->compressor, "zstd") == 
0) {
++                                      r = 
archive_read_append_filter(&a->archive, ARCHIVE_FILTER_ZSTD);
++                              } else if (strcmp(rpm->compressor, "xz") == 0) {
++                                      archive_read_append_filter(&a->archive, 
ARCHIVE_FILTER_XZ);
++                              } else if (strcmp(rpm->compressor, "gzip") == 
0) {
++                                      archive_read_append_filter(&a->archive, 
ARCHIVE_FILTER_GZIP);
++                              } else if (strcmp(rpm->compressor, "bzip2") == 
0) {
++                                      archive_read_append_filter(&a->archive, 
ARCHIVE_FILTER_BZIP2);
++                              } else if (strcmp(rpm->compressor, "lzma") == 
0) {
++                                      archive_read_append_filter(&a->archive, 
ARCHIVE_FILTER_LZMA);
++                              } else {
++                                      archive_set_error(&a->archive,
++                                              ARCHIVE_ERRNO_FILE_FORMAT,
++                                              "Unrecognized compressor: %s", 
rpm->compressor);
++                                      return ARCHIVE_FATAL;
++                              }
++
++                              if (r != ARCHIVE_OK) {
++                                      archive_set_error(&a->archive, r, 
"Cannot append %s filter",
++                                              rpm->compressor);
++                                      return r;
++                              }
++
++                              cpio_format = rpm_get_cpio_format(a);
++                              switch (cpio_format) {
++                              case CPIO_STR:
++                                      a->archive.archive_format_name = "RPM 
(stripped CPIO)";
++                                      break;
++                              case CPIO_SVR4_CRC:
++                                      a->archive.archive_format_name = "RPM 
(SVR4 cpio with CRC)";
++                                      break;
++                              case CPIO_SVR4_NOCRC:
++                                      a->archive.archive_format_name = "RPM 
(SVR4 cpio with no CRC)";
++                                      break;
++                              case CPIO_UNKNOWN:
++                              default:
++                                      return ARCHIVE_FATAL;
++                              }
++
++                              rpm->state = ST_ARCHIVE;
++                      }
++                      break;
++              }
++              case ST_ARCHIVE:
++                      return rpm_add_entry(a, entry);
++              }
++      }
++}
++
++static int
++archive_read_format_rpm_read_data(struct archive_read *a,
++    const void **buff, size_t *size, int64_t *offset)
++{
++      struct rpm *rpm = a->format->data;
++      ssize_t bytes_read;
++
++      if (rpm->entry_bytes_unconsumed > 0) {
++              __archive_read_consume(a, rpm->entry_bytes_unconsumed);
++              rpm->entry_bytes_unconsumed = 0;
++      }
++
++      if (rpm->entry_bytes_remaining > 0) {
++              *buff = __archive_read_ahead(a, 1, &bytes_read);
++              if (bytes_read <= 0)
++                      return ARCHIVE_FATAL;
++
++              if (bytes_read > rpm->entry_bytes_remaining)
++                      bytes_read = (ssize_t)rpm->entry_bytes_remaining;
++
++              *size = bytes_read;
++              rpm->entry_bytes_unconsumed = bytes_read;
++              *offset = rpm->entry_offset;
++              rpm->entry_offset += bytes_read;
++              rpm->entry_bytes_remaining -= bytes_read;
++
++              return ARCHIVE_OK;
++      } else {
++              if (rpm->entry_padding !=
++                      __archive_read_consume(a, rpm->entry_padding)) {
++                      return ARCHIVE_FATAL;
++              }
++
++              rpm->entry_padding = 0;
++              *buff = NULL;
++              *size = 0;
++              *offset = rpm->entry_offset;
++
++              return ARCHIVE_EOF;
++      }
++}
++
++static int
++archive_read_format_rpm_read_data_skip(struct archive_read *a)
++{
++      struct rpm *rpm = a->format->data;
++      const ssize_t to_skip = rpm->entry_bytes_remaining + rpm->entry_padding
++              + rpm->entry_bytes_unconsumed;
++
++      if (to_skip != __archive_read_consume(a, to_skip))
++              return ARCHIVE_FATAL;
++
++      rpm->entry_bytes_remaining = 0;
++      rpm->entry_padding = 0;
++      rpm->entry_bytes_unconsumed = 0;
++
++      return ARCHIVE_OK;
++}
++
++static int
++archive_read_format_rpm_cleanup(struct archive_read *a)
++{
++      struct rpm *rpm = a->format->data;
++      size_t i;
++
++      free(rpm->compressor);
++
++      if (rpm->inode_hash) {
++              for (i = 0; i < rpm->inode_hash_size; ++i) {
++                      free(rpm->inode_hash[i]);
++              }
++
++              free(rpm->inode_hash);
++      }
++
++      if (rpm->inodes != NULL) {
++              for (i = 0; i < rpm->n_inodes; i++) {
++                      free(rpm->inodes[i].files);
++              }
++
++              free(rpm->inodes);
++      }
++
++      if (rpm->files != NULL) {
++              for (i = 0; i < rpm->n_files; i++) {
++                      free(rpm->files[i].pathname);
++                      free(rpm->files[i].uname);
++                      free(rpm->files[i].gname);
++              }
++
++              free(rpm->files);
++      }
++
++      free(rpm);
++
++      a->format->data = NULL;
++
++      return ARCHIVE_OK;
++}
++
++static int
++rpm_add_entry(struct archive_read *a, struct archive_entry *entry)
++{
++      struct rpm *rpm = a->format->data;
++      struct rpm_file_info *file = NULL;
++      struct rpm_inode_info *inode;
++      uint64_t idx_ino;
++      const void *p;
++
++      const enum rpm_cpio_format cpio_format = rpm_get_cpio_format(a);
++
++      p = __archive_read_ahead(a, CPIO_HEADER_STR_SIZE, NULL);
++      if (!p) {
++              archive_set_error(&a->archive,
++                      ARCHIVE_ERRNO_FILE_FORMAT,
++                      "Premature EOF");
++              return ARCHIVE_FATAL;
++      }
++
++      char hex_str[9] = {0};
++      memcpy(hex_str, p + CPIO_MAGIC_SIZE, sizeof(idx_ino));
++      idx_ino = strtoull(hex_str, NULL, 16);
++
++      switch (cpio_format) {
++      case CPIO_STR:
++              __archive_read_consume(a, CPIO_HEADER_STR_SIZE);
++
++              if (rpm_is_eof(a))
++                      return ARCHIVE_EOF;
++
++              if (idx_ino >= rpm->n_files) {
++                      archive_set_error(&a->archive,
++                              ARCHIVE_ERRNO_FILE_FORMAT,
++                              "File index %" PRIu64 " out of range (max %u)", 
idx_ino, rpm->n_files - 1);
++                      return ARCHIVE_FATAL;
++              }
++
++              file = &rpm->files[idx_ino];
++              inode = rpm_get_inode(a, file->ino);
++              if (!inode)
++                      return ARCHIVE_FATAL;
++
++              break;
++      case CPIO_SVR4_CRC:
++      case CPIO_SVR4_NOCRC: {
++              size_t i;
++              uint64_t size;
++              char *path;
++
++              p = __archive_read_ahead(a, CPIO_HEADER_SVR_SIZE, NULL);
++              if (!p) {
++                      archive_set_error(&a->archive,
++                              ARCHIVE_ERRNO_FILE_FORMAT,
++                              "Truncated SVR4 header");
++                      return ARCHIVE_FATAL;
++              }
++
++              memcpy(hex_str, p + CPIO_HEADER_SVR_PATH_OFF, sizeof(size));
++
++              __archive_read_consume(a, CPIO_HEADER_SVR_SIZE);
++
++              if (rpm_is_eof(a))
++                      return ARCHIVE_EOF;
++
++              inode = rpm_get_inode(a, idx_ino);
++              if (!inode)
++                      return ARCHIVE_FATAL;
++
++              size = strtoull(hex_str, NULL, 16);
++
++              path = rpm_strread(a, size);
++              if (!path)
++                      return ARCHIVE_FATAL;
++
++              for (i = 0; i < inode->n_files; ++i) {
++                      if (strcmp(inode->files[i]->pathname, path) == 0) {
++                              file = inode->files[i];
++                              break;
++                      }
++              }
++
++              free(path);
++
++              if (!file) {
++                      archive_set_error(&a->archive,
++                              ARCHIVE_ERRNO_FILE_FORMAT,
++                              "Path not found");
++                      return ARCHIVE_FATAL;
++              }
++
++              /* Pad name to 2 more than a multiple of 4. */
++              size += (2 - size) & 3;
++              __archive_read_consume(a, size);
++
++              break;
++      }
++      default:
++              return ARCHIVE_FATAL;
++      }
++
++      archive_entry_set_pathname_utf8(entry, file->pathname);
++      archive_entry_set_uname_utf8(entry, file->uname);
++      archive_entry_set_gname_utf8(entry, file->gname);
++      archive_entry_set_dev(entry, file->dev);
++      archive_entry_set_ino(entry, file->ino);
++      archive_entry_set_mode(entry, file->mode);
++      archive_entry_set_rdev(entry, file->rdev);
++      archive_entry_set_mtime(entry, file->mtime, 0);
++      archive_entry_set_nlink(entry, inode->n_files);
++
++      /* Hardlink: only last entry carries payload */
++      if (++inode->n_processed == inode->n_files)
++              rpm->entry_bytes_remaining = file->size;
++      else
++              rpm->entry_bytes_remaining = 0;
++
++      /* Pad file contents to a multiple of 4. */
++      rpm->entry_padding = 3 & -rpm->entry_bytes_remaining;
++      rpm->entry_offset = 0;
++      rpm->entry_bytes_unconsumed = 0;
++
++      if (S_ISLNK(file->mode)) {
++              char *target = rpm_strread(a, file->size);
++              if (!target)
++                      return ARCHIVE_FATAL;
++
++              __archive_read_consume(a, rpm->entry_bytes_remaining);
++              rpm->entry_bytes_remaining = 0;
++
++              archive_entry_set_symlink_utf8(entry, target);
++
++              free(target);
++      }
++
++      archive_entry_set_size(entry, rpm->entry_bytes_remaining);
++
++      return ARCHIVE_OK;
++}
++
++static int
++rpm_parse_main_header(struct archive_read *a, const struct rpm_header *header)
++{
++      struct rpm *rpm = a->format->data;
++
++      struct rpm_header_parse {
++              uint32_t         n_files;
++
++              const char       *basenames;
++              uint32_t         n_basenames;
++
++              const char       *dirnames;
++              uint32_t         n_dirnames;
++
++              const char       *usernames;
++              uint32_t         n_usernames;
++
++              const char       *groupnames;
++              uint32_t         n_groupnames;
++
++              union {
++                      const int64_t   *filesizes64;
++                      const int32_t   *filesizes32;
++              };
++              uint8_t is_filesizes64;
++
++              const int32_t   *dirindexes;
++              const int16_t   *filemodes;
++              const int32_t   *filedevices;
++              const int16_t   *filerdevs;
++              const int32_t   *filemtimes;
++              const int32_t   *fileinodes;
++      } hp;
++
++      const struct rpm_entry *entries;
++      struct rpm_inode_temp_entry **temp_hash;
++      size_t hlen, temp_hash_size = 1;
++      uint64_t i, ino = 0;
++
++      memset(&hp, 0, sizeof(hp));
++
++      hlen = sizeof(struct rpm_entry)
++               * (size_t)header->n_entries
++               + (size_t)header->data_size;
++
++      entries = __archive_read_ahead(a, hlen, NULL);
++      if (entries == NULL)
++              return ARCHIVE_EOF;
++
++      if (rpm->first_header) {
++              __archive_read_consume(a, hlen);
++              return ARCHIVE_OK;
++      }
++
++      for (i = 0; i < header->n_entries; i++) {
++              uint32_t tag, cnt;
++              int32_t off;
++              const void *p;
++
++              tag = archive_be32dec(&entries[i].tag);
++              off = archive_be32dec(&entries[i].offset);
++              cnt = archive_be32dec(&entries[i].count);
++
++              if (off < 0 || (uint32_t)off >= header->data_size)
++                      continue;
++
++              p = (const uint8_t *)&entries[header->n_entries] + off;
++
++              switch (tag) {
++              case TAG_PAYLOADCOMPRESSOR:
++                      rpm->compressor = rpm_strndup(a, p ? p : "", 0);
++                      break;
++              case TAG_BASENAMES:
++                      hp.basenames = p;
++                      hp.n_basenames = cnt;
++                      break;
++              case TAG_DIRNAMES:
++                      hp.dirnames = p;
++                      hp.n_dirnames = cnt;
++                      break;
++              case TAG_FILEUSERNAMES:
++                      hp.usernames = p;
++                      hp.n_usernames = cnt;
++                      break;
++              case TAG_FILEGROUPNAMES:
++                      hp.groupnames = p;
++                      hp.n_groupnames = cnt;
++                      break;
++              case TAG_LONGFILESIZES:
++                      hp.filesizes64 = p;
++                      hp.n_files = cnt;
++                      hp.is_filesizes64 = 1;
++                      break;
++              case TAG_FILESIZES:
++                      /* This tag should never appear when Longfilesizes is 
present,
++                       * but checking doesn't hurt. */
++                      if (!hp.is_filesizes64) {
++                              hp.filesizes32 = p;
++                              hp.n_files = cnt;
++                      }
++                      break;
++              case TAG_DIRINDEXES:
++                      hp.dirindexes = p;
++                      break;
++              case TAG_FILEINODES:
++                      hp.fileinodes = p;
++                      break;
++              case TAG_FILEMODES:
++                      hp.filemodes = p;
++                      break;
++              case TAG_FILEDEVICES:
++                      hp.filedevices = p;
++                      break;
++              case TAG_FILERDEVS:
++                      hp.filerdevs = p;
++                      break;
++              case TAG_FILEMTIMES:
++                      hp.filemtimes = p;
++                      break;
++              }
++      }
++
++      if (hp.n_files >= MAX_NFILES) {
++              archive_set_error(&a->archive,
++                      ARCHIVE_ERRNO_FILE_FORMAT,
++                      "n_files out of range");
++              return ARCHIVE_FATAL;
++      }
++
++      rpm->files = calloc(hp.n_files, sizeof(*rpm->files));
++      if (rpm->files == NULL) {
++              archive_set_error(&a->archive,
++                      ENOMEM,
++                      "Can't allocate files data");
++              return ARCHIVE_FATAL;
++      }
++
++      rpm->n_files = hp.n_files;
++
++      while (temp_hash_size < hp.n_files * 2)
++              temp_hash_size <<= 1;
++
++      temp_hash = calloc(temp_hash_size, sizeof(*temp_hash));
++      if (!temp_hash) {
++              archive_set_error(&a->archive,
++                      ENOMEM,
++                      "Can't allocate temp hash");
++              return ARCHIVE_FATAL;
++      }
++
++      for (i = 0; i < hp.n_files; i++) {
++              const void *hbuf_end = (const uint8_t *)entries + hlen;
++              struct rpm_file_info *file = &rpm->files[i];
++              struct rpm_inode_temp_entry *group;
++              struct archive_string as;
++              const char *dname, *bname, *uname, *gname;
++              size_t bucket;
++
++              if (hp.dirindexes != NULL) {
++                      const uint32_t diri = rpm_be32_at(hp.dirindexes, 
hbuf_end, i);
++
++                      if (diri >= hp.n_dirnames) {
++                              rpm_free_inode_temp_hash(temp_hash, 
temp_hash_size);
++                              archive_set_error(&a->archive,
++                                      ARCHIVE_ERRNO_FILE_FORMAT,
++                                      "dirindex out of range");
++                              return ARCHIVE_FATAL;
++                      }
++
++                      dname = rpm_strlist_at(hp.dirnames, hbuf_end, diri, 
hp.n_dirnames);
++              } else
++                      dname = NULL;
++
++              bname = rpm_strlist_at(hp.basenames, hbuf_end, i, 
hp.n_basenames);
++              uname = rpm_strlist_at(hp.usernames, hbuf_end, i, 
hp.n_usernames);
++              gname = rpm_strlist_at(hp.groupnames, hbuf_end, i, 
hp.n_groupnames);
++
++              archive_string_init(&as);
++              archive_strappend_char(&as, '.');
++              rpm_strcat(&as, dname, hbuf_end);
++              rpm_strcat(&as, bname, hbuf_end);
++              file->pathname = strdup(as.s);
++              archive_string_free(&as);
++
++              file->uname = rpm_strndup(a, uname ? uname : "", 0);
++              file->gname = rpm_strndup(a, gname ? gname : "", 0);
++
++              if (hp.is_filesizes64)
++                      file->size = rpm_be64_at(hp.filesizes64, hbuf_end, i);
++              else
++                      file->size = rpm_be32_at(hp.filesizes32, hbuf_end, i);
++              file->mode = rpm_be16_at(hp.filemodes, hbuf_end, i);
++              file->dev = rpm_be32_at(hp.filedevices, hbuf_end, i);
++              file->rdev = rpm_be16_at(hp.filerdevs, hbuf_end, i);
++              file->mtime = rpm_be32_at(hp.filemtimes, hbuf_end, i);
++              file->ino = rpm_be32_at(hp.fileinodes, hbuf_end, i);
++
++              bucket = file->ino & (temp_hash_size - 1);
++              group = temp_hash[bucket];
++
++              while (group) {
++                      if (group->ino == file->ino)
++                              break;
++
++                      group = group->next;
++              }
++
++              if (!group) {
++                      group = calloc(1, sizeof(*group));
++                      if (!group) {
++                              rpm_free_inode_temp_hash(temp_hash, 
temp_hash_size);
++                              archive_set_error(&a->archive,
++                                      ENOMEM,
++                                      "Can't allocate inode group");
++                              return ARCHIVE_FATAL;
++                      }
++
++                      group->ino = file->ino;
++                      group->files = NULL;
++                      group->n_files = 0;
++                      group->capacity = 0;
++
++                      group->next = temp_hash[bucket];
++                      temp_hash[bucket] = group;
++              }
++
++              if (group->n_files >= group->capacity) {
++                      group->capacity = group->capacity ? group->capacity * 2 
: 8;
++                      void *prev_ptr = group->files;
++
++                      group->files = realloc(group->files, group->capacity * 
sizeof(*group->files));
++                      if (!group->files) {
++                              free(prev_ptr);
++                              rpm_free_inode_temp_hash(temp_hash, 
temp_hash_size);
++                              archive_set_error(&a->archive,
++                                      ENOMEM,
++                                      "Can't grow inode file list");
++                              return ARCHIVE_FATAL;
++                      }
++              }
++
++              group->files[group->n_files++] = file;
++      }
++
++      rpm->n_inodes = 0;
++      for (i = 0; i < temp_hash_size; i++) {
++              for (struct rpm_inode_temp_entry *e = temp_hash[i]; e; e = 
e->next)
++                      rpm->n_inodes++;
++      }
++
++      rpm->inodes = calloc(rpm->n_inodes, sizeof(*rpm->inodes));
++      if (!rpm->inodes) {
++              rpm_free_inode_temp_hash(temp_hash, temp_hash_size);
++              archive_set_error(&a->archive,
++                      ENOMEM,
++                      "Can't allocate inodes array");
++              return ARCHIVE_FATAL;
++      }
++
++      for (i = 0; i < temp_hash_size; i++) {
++              struct rpm_inode_temp_entry *e = temp_hash[i];
++              while (e) {
++                      struct rpm_inode_info *info = &rpm->inodes[ino++];
++                      info->n_files = e->n_files;
++                      info->files = e->files;
++                      info->n_processed = 0;
++
++                      struct rpm_inode_temp_entry *next = e->next;
++                      free(e);
++                      e = next;
++              }
++      }
++
++      free(temp_hash);
++
++      rpm->inode_hash_size = 1;
++      while (rpm->inode_hash_size < rpm->n_inodes * 2)
++              rpm->inode_hash_size <<= 1;
++
++      rpm->inode_hash = calloc(rpm->inode_hash_size, 
sizeof(*rpm->inode_hash));
++      if (!rpm->inode_hash) {
++              archive_set_error(&a->archive,
++                      ENOMEM,
++                      "Can't allocate inode hash");
++              return ARCHIVE_FATAL;
++      }
++
++      for (i = 0; i < rpm->n_inodes; i++) {
++              uint64_t raw = rpm->inodes[i].files[0]->ino;
++              size_t bucket = raw & (rpm->inode_hash_size - 1);
++
++              struct inode_hash_entry *e = malloc(sizeof(*e));
++              if (!e) {
++                      archive_set_error(&a->archive,
++                              ENOMEM,
++                              "Can't allocate inode hash entry");
++                      return ARCHIVE_FATAL;
++              }
++
++              e->ino = raw;
++              e->info = &rpm->inodes[i];
++              e->next = rpm->inode_hash[bucket];
++              rpm->inode_hash[bucket] = e;
++      }
++
++      __archive_read_consume(a, hlen);
++
++      return ARCHIVE_OK;
++}
++
++static struct rpm_inode_info *
++rpm_get_inode(struct archive_read *a, const uint32_t ino)
++{
++      const struct rpm *rpm = a->format->data;
++      struct inode_hash_entry *e;
++      size_t bucket;
++
++      if (!rpm->inode_hash)
++              return NULL;
++
++      bucket = ino & (rpm->inode_hash_size - 1);
++
++      for (e = rpm->inode_hash[bucket]; e; e = e->next)
++              if (e->ino == ino)
++                      return e->info;
++
++      return NULL;
++}
++
++static enum rpm_cpio_format
++rpm_get_cpio_format(struct archive_read *a)
++{
++      const char *magic = __archive_read_ahead(a, CPIO_MAGIC_SIZE, NULL);
++      if (!magic) {
++              archive_set_error(&a->archive,
++                      ARCHIVE_ERRNO_FILE_FORMAT,
++                      "Premature EOF");
++              return ARCHIVE_FATAL;
++      }
++
++      if (memcmp(magic, CPIO_MAGIC_STR, CPIO_MAGIC_SIZE) == 0)
++              return CPIO_STR;
++      else if (memcmp(magic, CPIO_MAGIC_SVR4_CRC, CPIO_MAGIC_SIZE) == 0)
++              return CPIO_SVR4_CRC;
++      else if (memcmp(magic, CPIO_MAGIC_SVR4_NOCRC, CPIO_MAGIC_SIZE) == 0)
++              return CPIO_SVR4_NOCRC;
++      else {
++              archive_set_error(&a->archive,
++                      ARCHIVE_ERRNO_FILE_FORMAT,
++                      "Unrecognized magic");
++              return CPIO_UNKNOWN;
++      }
++}
++
++static uint8_t
++rpm_is_eof(struct archive_read *a)
++{
++      const void *p = __archive_read_ahead(a, CPIO_END_MARK_SIZE, NULL);
++      if (!p)
++              return 1;
++
++      return memcmp(p, CPIO_END_MARK, CPIO_END_MARK_SIZE) == 0;
++}
++
++static uint16_t
++rpm_be16_at(const void *buf_start, const void *buf_end, size_t off)
++{
++      off *= sizeof(uint16_t);
++
++      if (!buf_start || (buf_end <= buf_start) ||
++              (size_t)(buf_end - buf_start) < (off + sizeof(uint16_t)))
++              return 0;
++
++      return archive_be16dec(buf_start + off);
++}
++
++static uint32_t
++rpm_be32_at(const void *buf_start, const void *buf_end, size_t off)
++{
++      off *= sizeof(uint32_t);
++
++      if (!buf_start || (buf_end <= buf_start) ||
++              (size_t)(buf_end - buf_start) < (off + sizeof(uint32_t)))
++              return 0;
++
++      return archive_be32dec(buf_start + off);
++}
++
++static uint64_t
++rpm_be64_at(const void *buf_start, const void *buf_end, size_t off)
++{
++      off *= sizeof(uint64_t);
++
++      if (!buf_start || (buf_end <= buf_start) ||
++              (size_t)(buf_end - buf_start) < (off + sizeof(uint64_t)))
++              return 0;
++
++      return archive_be64dec(buf_start + off);
++}
++
++static inline size_t
++rpm_limit_bytes(const size_t bytes, const size_t max)
++{
++      return (bytes > max ? max : bytes);
++}
++
++static char *
++rpm_strndup(struct archive_read *a, const char *s, size_t len)
++{
++      if (s == NULL)
++              return NULL;
++
++      if (len == 0)
++              len = strnlen(s, STR_SIZE_LIMIT);
++
++      if (len > STR_SIZE_LIMIT) {
++              archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
++                      "String too long (malformed?)");
++              return NULL;
++      }
++
++      return strndup(s, len);
++}
++
++static char *
++rpm_strread(struct archive_read *a, size_t len) {
++      const void *p;
++
++      if (len > STR_SIZE_LIMIT) {
++              archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
++                      "String too long");
++              return NULL;
++      }
++
++      p = __archive_read_ahead(a, len, NULL);
++      if (!p) {
++              archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
++                      "Truncated string");
++              return NULL;
++      }
++
++      return rpm_strndup(a, p, len);
++}
++
++static void
++rpm_strcat(struct archive_string *a, const void *s, const void *buf_end)
++{
++      if (!s || s >= buf_end)
++              return;
++
++      archive_strncat(a, s, rpm_limit_bytes(buf_end - s, STR_SIZE_LIMIT));
++}
++
++static const char *
++rpm_strlist_at(const char *p, const void *end, uint64_t i, uint64_t n)
++{
++      uint64_t k;
++
++      if (p == NULL || i >= n || (const char *)end < p)
++              return NULL;
++
++      for (k = 0; k < n; k++) {
++              const uint64_t max_len = rpm_limit_bytes((const char *)end - p,
++                      STR_SIZE_LIMIT);
++              const uint64_t len = strnlen(p, max_len);
++              if (len == max_len)
++                      /* Unterminated or absurdly long string. */
++                      return NULL;
++
++              if (k == i)
++                      return p;
++
++              p += len + 1;
++
++              if (p >= (const char *)end)
++                      return NULL;
++      }
++
++      return NULL;
++}
++
++static void
++rpm_free_inode_temp_hash(struct rpm_inode_temp_entry **hash, const size_t 
hash_size)
++{
++      for (size_t i = 0; i < hash_size; i++) {
++              struct rpm_inode_temp_entry *e = hash[i];
++              while (e) {
++                      struct rpm_inode_temp_entry *next = e->next;
++                      free(e->files);
++                      free(e);
++                      e = next;
++              }
++      }
++
++      free(hash);
++}
+diff --git a/libarchive/test/test_archive_read_support.c 
b/libarchive/test/test_archive_read_support.c
+index b0c92802..bc256a17 100644
+--- a/libarchive/test/test_archive_read_support.c
++++ b/libarchive/test/test_archive_read_support.c
+@@ -91,6 +91,7 @@ DEFINE_TEST(test_archive_read_support)
+       test_filter_or_format(archive_read_support_format_iso9660);
+       test_filter_or_format(archive_read_support_format_lha);
+       test_filter_or_format(archive_read_support_format_mtree);
++      test_filter_or_format(archive_read_support_format_rpm);
+       test_filter_or_format(archive_read_support_format_tar);
+       test_filter_or_format(archive_read_support_format_xar);
+       test_filter_or_format(archive_read_support_format_zip);
+@@ -140,7 +141,6 @@ DEFINE_TEST(test_archive_read_support)
+       test_filter_or_format(archive_read_support_filter_lzip);
+       test_filter_or_format(archive_read_support_filter_lzma);
+       test_filter_or_format(archive_read_support_filter_none);
+-      test_filter_or_format(archive_read_support_filter_rpm);
+       test_filter_or_format(archive_read_support_filter_uu);
+       test_filter_or_format(archive_read_support_filter_xz);
+ }
+diff --git a/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c 
b/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c
+index cff64d72..c775e6f4 100644
+--- a/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c
++++ b/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c
+@@ -97,8 +97,6 @@ DEFINE_TEST(test_read_format_cpio_svr4_bzip2_rpm)
+               return;
+         }
+       assertEqualIntA(a, ARCHIVE_OK, r);
+-      assertEqualIntA(a, ARCHIVE_OK,
+-          archive_read_support_filter_rpm(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+       extract_reference_file(name);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2));
+@@ -121,7 +119,7 @@ DEFINE_TEST(test_read_format_cpio_svr4_bzip2_rpm)
+       /* Verify that the format detection worked. */
+       assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_BZIP2);
+       assertEqualString(archive_filter_name(a, 0), "bzip2");
+-      assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);
++      assertEqualInt(archive_format(a), ARCHIVE_FORMAT_RPM);
+ 
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+diff --git a/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c 
b/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c
+index 345760c1..913dc793 100644
+--- a/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c
++++ b/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c
+@@ -97,8 +97,6 @@ DEFINE_TEST(test_read_format_cpio_svr4_gzip_rpm)
+               return;
+         }
+       assertEqualIntA(a, ARCHIVE_OK, r);
+-      assertEqualIntA(a, ARCHIVE_OK,
+-          archive_read_support_filter_rpm(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+       extract_reference_file(name);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2));
+@@ -121,8 +119,8 @@ DEFINE_TEST(test_read_format_cpio_svr4_gzip_rpm)
+       /* Verify that the format detection worked. */
+       assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_GZIP);
+       assertEqualString(archive_filter_name(a, 0), "gzip");
+-      assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);
+- 
++      assertEqualInt(archive_format(a), ARCHIVE_FORMAT_RPM);
++
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+ }
+diff --git a/libarchive/test/test_read_format_huge_rpm.c 
b/libarchive/test/test_read_format_huge_rpm.c
+index 729c1e18..b56dfbed 100644
+--- a/libarchive/test/test_read_format_huge_rpm.c
++++ b/libarchive/test/test_read_format_huge_rpm.c
+@@ -40,9 +40,7 @@ DEFINE_TEST(test_read_format_huge_rpm)
+       assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+ 
+       /* Verify that the format detection worked. */
+-      assertEqualInt(ARCHIVE_FILTER_RPM, archive_filter_code(a, 0));
+-      assertEqualString("rpm", archive_filter_name(a, 0));
+-      assertEqualInt(ARCHIVE_FORMAT_EMPTY, archive_format(a));
++      assertEqualInt(ARCHIVE_FORMAT_RPM, archive_format(a));
+ 
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+-- 
+2.49.0
+
diff --git a/meta/recipes-extended/libarchive/libarchive_3.8.6.bb 
b/meta/recipes-extended/libarchive/libarchive_3.8.6.bb
index d579cdb65a..4e1f6b08b5 100644
--- a/meta/recipes-extended/libarchive/libarchive_3.8.6.bb
+++ b/meta/recipes-extended/libarchive/libarchive_3.8.6.bb
@@ -31,6 +31,9 @@ EXTRA_OECONF += "--enable-largefile --without-iconv"
 
 SRC_URI = "https://libarchive.org/downloads/libarchive-${PV}.tar.gz \
            file://run-ptest \
+           
file://0001-archive_read_append_filter-Keep-iterating-even-if-na.patch \
+           
file://0002-__archive_read_register_bidder-Allow-ARCHIVE_STATE_H.patch \
+           
file://0003-Convert-RPM-reader-into-a-proper-format-supporting-b.patch \
           "
 UPSTREAM_CHECK_URI = "https://www.libarchive.org/";
 
-- 
2.49.0

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#232963): 
https://lists.openembedded.org/g/openembedded-core/message/232963
Mute This Topic: https://lists.openembedded.org/mt/118279446/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to