194

I have an rpm and I want to treat it like a tarball. I want to extract the contents into a directory so I can inspect the contents. I am familiar with the querying commands of an uninstalled package. I do not simply want a list of the contents of the rpm. i.e.

$ rpm -qpl foo.rpm

I want to inspect the contents of several files contained in the rpm. I do not want to install the rpm. I am also aware of the rpms ability to do additional modifictions in the %post sections, and how to check for those. i.e.

$ rpm -qp --scripts foo.rpm

However in this case that is of no concern to me.

Jeff Sheffield
  • 5,768
  • 3
  • 25
  • 32

19 Answers19

230

Did you try the rpm2cpio commmand? See the example below:

$ rpm2cpio php-5.1.4-1.esp1.x86_64.rpm | cpio -idmv

/etc/httpd/conf.d/php.conf  
./etc/php.d  
./etc/php.ini  
./usr/bin/php  
./usr/bin/php-cgi  
etc 
legoscia
  • 39,593
  • 22
  • 116
  • 167
linux_fanatic
  • 4,767
  • 3
  • 19
  • 20
  • 40
    I'm amazed that Linux distributions do not provide a wrapper executable to make this easier (eg rpmextract bla.rpm), as this is a very common operation. User should not need to care about the intermediary cpio format. – Alan Evangelista Sep 24 '14 at 22:32
  • 3
    Don't be amazed, @AlanEvangelista, this is par for the course. – ngreen Oct 30 '14 at 19:59
  • this needs root access for installing rpm2cpio :( – törzsmókus Feb 09 '15 at 07:40
  • 15
    @AlanEvangelista I'm amazed that rpm is such bad format. Comparing to other like deb which are just simple archives adhering to UNIX philosophy. – Trismegistos Mar 03 '15 at 11:07
  • @törzsmókus Spin up a VM and unpack it. – MirroredFate Dec 19 '16 at 21:39
  • @MirroredFate doesn't this seems bad to you; if you've just check the rpm content, VM needs to be created ! – Sumit Murari Sep 07 '17 at 07:28
  • 1
    @SumitMurari Of course it is bad. I was just offering a solution to törzsmókus' predicament. – MirroredFate Oct 02 '17 at 17:53
  • On OS X $ brew install rpm2cpio , then it's called `rpm2cpio.pl` – rogerdpack May 14 '19 at 20:39
  • 7
    In my case I was getting `cpio: Malformed number` errors with this command. What worked for me is running `rpm2archive xorg-x11-server-1.20.11-1.fc33.src.rpm`, and then `tar -xzvf xorg-x11-server-1.20.11-1.fc33.src.rpm.tgz` to extract into the current dir. – Hi-Angel Jul 11 '21 at 14:00
  • 1
    The cpio payload of the rpm package can be compressed which can make it hard to extract the cpio payload if you do not know which compressor was used to build the rpm. Assuming the rpm package is available in the current directory, the compressor name and the flags that were used during compression can be printed on the command line with the command `rpm -qp --qf "%{PAYLOADCOMPRESSOR} %{PAYLOADFLAGS}\n" ` – Jerome WAGNER Sep 27 '21 at 15:46
  • 4
    @Hi-Angel It's because RHEL 9 uses a payload compression (zstd), I added an answer, this is another method to extract it: `rpm2cpio foo.rpm | zstd -d | cpio -idmv` – G. C. Oct 31 '22 at 10:32
89
$ mkdir packagecontents; cd packagecontents
$ rpm2cpio ../foo.rpm | cpio -idmv
$ find . 

For Reference: the cpio arguments are

-i = extract
-d = make directories
-m = preserve modification time
-v = verbose

I found the answer over here: lontar's answer

Community
  • 1
  • 1
Jeff Sheffield
  • 5,768
  • 3
  • 25
  • 32
  • 2
    "rpm2cpio foo.rpm | cpio -idmv" works for me. It is sufficient to extract the contents of the rpm at current path. – parasrish Apr 21 '16 at 07:24
38

For those who do not have rpm2cpio, here is the ancient rpm2cpio.sh script that extracts the payload from a *.rpm package.

Reposted for posterity … and the next generation.

Invoke like this: ./rpm2cpio.sh .rpm | cpio -dimv

#!/bin/sh

pkg=$1
if [ "$pkg" = "" -o ! -e "$pkg" ]; then
    echo "no package supplied" 1>&2
    exit 1
fi

leadsize=96
o=`expr $leadsize + 8`
set `od -j $o -N 8 -t u1 $pkg`
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
# echo "sig il: $il dl: $dl"

sigsize=`expr 8 + 16 \* $il + $dl`
o=`expr $o + $sigsize + \( 8 - \( $sigsize \% 8 \) \) \% 8 + 8`
set `od -j $o -N 8 -t u1 $pkg`
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
# echo "hdr il: $il dl: $dl"

hdrsize=`expr 8 + 16 \* $il + $dl`
o=`expr $o + $hdrsize`
EXTRACTOR="dd if=$pkg ibs=$o skip=1"

COMPRESSION=`($EXTRACTOR |file -) 2>/dev/null`
if echo $COMPRESSION |grep -q gzip; then
        DECOMPRESSOR=gunzip
elif echo $COMPRESSION |grep -q bzip2; then
        DECOMPRESSOR=bunzip2
elif echo $COMPRESSION |grep -iq xz; then # xz and XZ safe
        DECOMPRESSOR=unxz
elif echo $COMPRESSION |grep -q cpio; then
        DECOMPRESSOR=cat
else
        # Most versions of file don't support LZMA, therefore we assume
        # anything not detected is LZMA
        DECOMPRESSOR=`which unlzma 2>/dev/null`
        case "$DECOMPRESSOR" in
            /* ) ;;
            *  ) DECOMPRESSOR=`which lzmash 2>/dev/null`
             case "$DECOMPRESSOR" in
                     /* ) DECOMPRESSOR="lzmash -d -c" ;;
                     *  ) DECOMPRESSOR=cat ;;
                 esac
                 ;;
        esac
fi

$EXTRACTOR 2>/dev/null | $DECOMPRESSOR
carpinchosaurio
  • 1,175
  • 21
  • 44
Jeff Johnson
  • 2,310
  • 13
  • 23
32

Sometimes you can encounter an issue with intermediate RPM archive:

cpio: Malformed number
cpio: Malformed number
cpio: Malformed number
. . .
cpio: premature end of archive

That means it could be packed, these days it is LZMA2 compression as usual, by xz:

rpm2cpio <file>.rpm | xz -d | cpio -idmv

otherwise you could try:

rpm2cpio <file>.rpm | lzma -d | cpio -idmv
rook
  • 5,880
  • 4
  • 39
  • 51
13

Most distributions have installed the GUI app file-roller which unpacks tar, zip, rpm and many more.

file-roller --extract-here package.rpm

This will extract the contents in the current directory.

erik
  • 2,278
  • 1
  • 23
  • 30
7

7-zip understands most kinds of archives, including rpm and the included cpio.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
6

As reported here: https://bugzilla.redhat.com/show_bug.cgi?id=2058426

RHEL 9 uses a payload compression (zstd)

rpm2cpio foo.rpm | zstd -d | cpio -idmv
G. C.
  • 387
  • 2
  • 6
5

You can simply do tar -xvf <rpm file> as well!

gvlasov
  • 18,638
  • 21
  • 74
  • 110
Melissa
  • 125
  • 1
  • 1
  • 1
    Unable to reproduce that with an .rpm package. You might want to correct your answer. – gvlasov Feb 10 '15 at 20:49
  • 11
    This works on OS X - or any other system that uses a variant of `tar` which uses `libarchive` under the hood. – Glenjamin Dec 01 '15 at 09:01
  • 4
    I got the error: This does not look like a tar archive. – hostingutilities.com Apr 13 '18 at 05:27
  • This worked for me on MacOS 10.14.1 with bsdtar 2.8.3 - libarchive 2.8.3. It might depend on which type of compression was used. The rpm2cpio.sh script seems to check for several types of compression before passing it to the right tool for extraction. – 2xj Dec 05 '18 at 20:20
  • 1
    Since SO's edit functionality won't let me add 3 characters to fix the answer, it should be added that this requires libarchive's `bsdtar`. Homebrew on Mac links `tar` to it by default but on other OSs `tar` means GNU tar. – Atemu Sep 18 '19 at 20:54
5

The powerful text-based file manager mc (Midnight Commander, vaguely reminding the Norton Commander of old DOS times) has the built-in capability of inspecting and unpacking .rpm and .rpms files, just "open" the .rpm(s) file within mc and select CONTENTS.cpio: for an rpm you get access to the install tree, for an rpms you get access to the .spec file and all the source packages.

Davide Cesari
  • 51
  • 1
  • 2
4

To debug / inspect your rpm I suggest to use redline which is a java program

Usage :

java -cp redline-1.2.1-jar-with-dependencies.jar org.redline_rpm.Scanner foo.rpm

Download : https://github.com/craigwblake/redline/releases

Ronan Quillevere
  • 3,699
  • 1
  • 29
  • 44
3

In NixOS, there is rpmextract. It is a wrapper around rpm2cpio, exactly as @Alan Evangelista wanted. https://github.com/NixOS/nixpkgs/tree/master/pkgs/tools/archivers/rpmextract

user7610
  • 25,267
  • 15
  • 124
  • 150
2

In OpenSuse at least, the unrpm command comes with the build package.

In a suitable directory (because this is an archive bomb):

unrpm file.rpm
user2394284
  • 5,520
  • 4
  • 32
  • 38
2

On Manjaro using KDE, Ark can handle it.

JasonPlutext
  • 15,352
  • 4
  • 44
  • 84
1

The "DECOMPRESSION" test fails on CygWin, one of the most potentiaally useful platforms for it, due to the "grep" check for "xz" being case sensitive. The result of the "COMPRESSION:" check is:

COMPRESSION='/dev/stdin: XZ compressed data'

Simply replacing 'grep -q' with 'grep -q -i' everywhere seems to resolve the issue well.

I've done a few updates, particularly adding some comments and using "case" instead of stacked "if" statements, and included that fix below

#!/bin/sh
#
# rpm2cpio.sh - extract 'cpio' contents of RPM
#
# Typical usage: rpm2cpio.sh rpmname | cpio -idmv
#

if [ "$# -ne 1" ]; then
    echo "Usage: $0 file.rpm" 1>&2
    exit 1
fi

rpm="$1"
if [ -e "$rpm" ]; then
    echo "Error: missing $rpm"
fi


leadsize=96
o=`expr $leadsize + 8`
set `od -j $o -N 8 -t u1 $rpm`
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
# echo "sig il: $il dl: $dl"

sigsize=`expr 8 + 16 \* $il + $dl`
o=`expr $o + $sigsize + \( 8 - \( $sigsize \% 8 \) \) \% 8 + 8`
set `od -j $o -N 8 -t u1 $rpm`
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
# echo "hdr il: $il dl: $dl"

hdrsize=`expr 8 + 16 \* $il + $dl`
o=`expr $o + $hdrsize`
EXTRACTOR="dd if=$rpm ibs=$o skip=1"

COMPRESSION=`($EXTRACTOR |file -) 2>/dev/null`
DECOMPRESSOR="cat"

case $COMPRESSION in
    *gzip*|*GZIP*)
        DECOMPRESSOR=gunzip
        ;;
    *bzip2*|*BZIP2*)
        DECOMPRESSOR=bunzip2
        ;;
    *xz*|*XZ*)
        DECOMPRESSOR=unxz
        ;;
    *cpio*|*cpio*)
        ;;
    *)
        # Most versions of file don't support LZMA, therefore we assume
        # anything not detected is LZMA
        DECOMPRESSOR="`which unlzma 2>/dev/null`"
        case "$DECOMPRESSOR" in
            /*)
                DECOMPRESSOR="$DECOMPRESSOR"
                ;;
            *)
                DECOMPRESSOR=`which lzmash 2>/dev/null`
                case "$DECOMPRESSOR" in
                    /* )
                        DECOMPRESSOR="lzmash -d -c"
                        ;;
                    *  )
                        echo "Warning: DECOMPRESSOR not found, assuming 'cat'" 1>&2
                        ;;
                esac
                ;;
        esac
esac

$EXTRACTOR 2>/dev/null | $DECOMPRESSOR
Walkman
  • 67
  • 1
  • 2
  • 8
1

Copy the .rpm file in a separate folder then run the following command $ yourfile.rpm | cpio -idmv

apurbojha
  • 97
  • 1
  • 4
1

If your system has rpm2archive installed, you can run:

rpm2archive package.rpm

This converts rpm package into a compressed tar archive package.rpm.tgz. Now you can extract it using:

tar -xvf package.rpm.tgz

This was earlier noted by Hi-Angel in his comment.

Sources:

  1. rpm2archive man page
  2. It was released with rpm 4.12.0-alpha (it's fairly new)
  3. On Debian and its derivatives, it is included with rpm2cpio package.
TBourne
  • 11
  • 4
1

If you have tried the rpm2cpio.sh script above and it didn't work, you can save the follwing script and invoke like this: rpm2cpio.sh rpmname | cpio -idmv, it workes on my CentOS 7.

#!/bin/sh -efu

fatal() {
    echo "$*" >&2
    exit 1
}

pkg="$1"
[ -n "$pkg" ] && [ -e "$pkg" ] ||
    fatal "No package supplied"

_dd() {
    local o="$1"; shift
    dd if="$pkg" skip="$o" iflag=skip_bytes status=none $*
}

calcsize() {

    case "$(_dd $1 bs=4 count=1 | tr -d '\0')" in
        "$(printf '\216\255\350')"*) ;; # '\x8e\xad\xe8'
        *) fatal "File doesn't look like rpm: $pkg" ;;
    esac

    offset=$(($1 + 8))

    local i b b0 b1 b2 b3 b4 b5 b6 b7

    i=0
    while [ $i -lt 8 ]; do
        # add . to not loose \n
        # strip \0 as it gets dropped with warning otherwise
        b="$(_dd $(($offset + $i)) bs=1 count=1 | tr -d '\0' ; echo .)"
        b=${b%.}    # strip . again

        [ -z "$b" ] &&
            b="0" ||
            b="$(exec printf '%u\n' "'$b")"
        eval "b$i=\$b"
        i=$(($i + 1))
    done

    rsize=$((8 + ((($b0 << 24) + ($b1 << 16) + ($b2 << 8) + $b3) << 4) + ($b4 << 24) + ($b5 << 16) + ($b6 << 8) + $b7))
    offset=$(($offset + $rsize))
}

case "$(_dd 0 bs=4 count=1 | tr -d '\0')" in
    "$(printf '\355\253\356\333')"*) ;; # '\xed\xab\xee\xdb'
    *) fatal "File doesn't look like rpm: $pkg" ;;
esac

calcsize 96
sigsize=$rsize

calcsize $(($offset + (8 - ($sigsize % 8)) % 8))
hdrsize=$rsize

case "$(_dd $offset bs=2 count=1 | tr -d '\0')" in
    "$(printf '\102\132')") _dd $offset | bunzip2 ;; # '\x42\x5a'
    "$(printf '\037\213')") _dd $offset | gunzip  ;; # '\x1f\x8b'
    "$(printf '\375\067')") _dd $offset | xzcat   ;; # '\xfd\x37'
    "$(printf '\135')") _dd $offset | unlzma      ;; # '\x5d\x00'
    "$(printf '\050\265')") _dd $offset | unzstd  ;; # '\x28\xb5'
    *) fatal "Unrecognized payload compression format in rpm file: $pkg" ;;
esac
xavierzhao
  • 780
  • 9
  • 18
0

If you have rpmdevtools installed, you can also extract the RPM package file with just one command:

rpmdev-extract foo.rpm
user2009388
  • 179
  • 1
  • 11
-1

simply run this:

$rpm -ivh package_name.rpm

if you don't have super user permissions, use sudo -i command then execute this.
if you don't have rpm package, install rpm package.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • Seems not working for me. I got the following error: warning: rstudio-server-rhel-2021.09.2-382-x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID e331692f: NOKEY error: can't create transaction lock on /var/lib/rpm/.rpm.lock (Permission denied) – Haizi Jan 17 '22 at 16:30
  • Caution! This does not only extract the RPM, but also installs it on the system. – user2009388 Jan 13 '23 at 17:50