Find and extract one file from rpm package

Extracting a configuration file (or any other single file) from a package which is not installed is not a standard operation on rpm based systems, but with the following few steps, a file can be extracted without installing the package on the system.

Find what needs to be extracted

Extracting a file from an rpm requires you to know which rpm contains the file that you want. To find the rpm which contains a certain file use the “yum provides” command as described in yum – install package that contains a specific file.

Advertisements

To list all files in an rpm which has not been installed or downloaded, the “repoquery(1)” command can be used. This command is part of the “yum-utils” package.

$ yum install yum-utils

With the yum-utils(1) installed a set of useful commands is available, including the “repoquery” command.

$ repoquery --list openscap-utils
/usr/bin/oscap-chroot
/usr/bin/oscap-docker
/usr/bin/oscap-ssh
/usr/bin/oscap-vm
/usr/bin/scap-as-rpm
/usr/lib/python2.7/site-packages/oscap_docker_python/__init__.py
/usr/lib/python2.7/site-packages/oscap_docker_python/__init__.pyc
/usr/lib/python2.7/site-packages/oscap_docker_python/__init__.pyo
/usr/lib/python2.7/site-packages/oscap_docker_python/get_cve_input.py
/usr/lib/python2.7/site-packages/oscap_docker_python/get_cve_input.pyc
/usr/lib/python2.7/site-packages/oscap_docker_python/get_cve_input.pyo
/usr/lib/python2.7/site-packages/oscap_docker_python/oscap_docker_util.py
/usr/lib/python2.7/site-packages/oscap_docker_python/oscap_docker_util.pyc
/usr/lib/python2.7/site-packages/oscap_docker_python/oscap_docker_util.pyo
/usr/share/doc/openscap-utils-1.2.10
/usr/share/doc/openscap-utils-1.2.10/oscap-scan.cron
/usr/share/man/man8/oscap-chroot.8.gz
/usr/share/man/man8/oscap-docker.8.gz
/usr/share/man/man8/oscap-ssh.8.gz
/usr/share/man/man8/oscap-vm.8.gz
/usr/share/man/man8/scap-as-rpm.8.gz

The above example shows the repoquery command with the “–list” option to list the files from the rpm package. The command requires only the package name. This command shows the list of files without downloading or installing the rpm package.

Retrieving the rpm package

To retrieve the rpm package without installing it, yumdownloader(1) (which is also part of yum-utils) can be used. The command requires a package name and optionally a destination directory for the downloaded package.

$ yumdownloader --destdir=/home/user/ openscap-utils
Loaded plugins: etckeeper, fastestmirror, priorities
Loading mirror speeds from cached hostfile
 * base: mirror.easyname.at
 * epel: mirror.inode.at
 * extras: mirror.easyname.at
 * updates: mirror.easyname.at
1 packages excluded due to repository priority protections
openscap-utils-1.2.10-3.el7_3.x86_64.rpm                      |  35 kB  00:00:00

If you prefer the manual download option, the repoquery utility can lead you to the package by showing its download location. The “–location” option instructs repoquery to printout the URL to the package. The wget(1) or curl(1) utility can be used to download the returned URL.

$ repoquery --location openscap-utils
http://mirror1.hs-esslingen.de/pub/Mirrors/centos/6/os/x86_64/Packages/openscap-utils-1.2.13-2.el6.x86_64.rpm

Regardless of the method used, the result will be a downloaded rpm in the specified destination directory.

Extracting the file

As with the download of the rpm, there are two options when it comes to extracting the file from the rpm.

Option 1: cpio

Propably the more elegant way of extracting a file, at least in my opinion, is the use of cpio(1). Cpio is an archive utility which allows to extract files from a few archive formats and needs to be installed as separate package.

$ yum install cpio

Combined with the rpm2cpio(8) utility, which comes pre-installed as part of the “rpm” packagemanager, cpio can extract all files or a single file from an rpm.

$ rpm2cpio openscap-utils-1.2.10-3.el7_3.x86_64.rpm | cpio -t
./usr/bin/oscap-chroot
./usr/bin/oscap-docker
./usr/bin/oscap-ssh
./usr/bin/oscap-vm
./usr/bin/scap-as-rpm
./usr/lib/python2.7/site-packages/oscap_docker_python/__init__.py
./usr/lib/python2.7/site-packages/oscap_docker_python/get_cve_input.py
./usr/lib/python2.7/site-packages/oscap_docker_python/oscap_docker_util.py
./usr/share/doc/openscap-utils-1.2.10
./usr/share/doc/openscap-utils-1.2.10/oscap-scan.cron
./usr/share/man/man8/oscap-chroot.8.gz
./usr/share/man/man8/oscap-docker.8.gz
./usr/share/man/man8/oscap-ssh.8.gz
./usr/share/man/man8/oscap-vm.8.gz
./usr/share/man/man8/scap-as-rpm.8.gz
./usr/lib/python2.7/site-packages/oscap_docker_python/__init__.pyc
./usr/lib/python2.7/site-packages/oscap_docker_python/__init__.pyo
./usr/lib/python2.7/site-packages/oscap_docker_python/get_cve_input.pyc
./usr/lib/python2.7/site-packages/oscap_docker_python/get_cve_input.pyo
./usr/lib/python2.7/site-packages/oscap_docker_python/oscap_docker_util.pyc
./usr/lib/python2.7/site-packages/oscap_docker_python/oscap_docker_util.pyo
144 blocks

The above uses rpm2cpio to convert the rpm into an archive format used by cpio. Using the -t option in the cpio command will list all files of the archive. This is helpful to pick the file to extract from the rpm.

At this point, it’s worth saying a little about cpio. The short arguments to cpio are not as intuitive as they cound be. The utility is operating in a so called “copy-in” mode to extract files and “copy-out” to add files to an archive. Wrong way around? It seems to me as if the intention was to name these modes as the operation is seen by the file-system.
– “copy-in” to the file system from the archive (-i).
– “copy-out” of the file-system and into the archive (-o).

With the below command, the rpm is converted into the cpio archive format and cpio is set into the “copy-in” mode using the “-i” option. With the -d option, cpio is allowed to create any directories needed to extract the file(s) given.

$ rpm2cpio openscap-utils-1.2.10-3.el7_3.x86_64.rpm | cpio -idv ./usr/bin/oscap-ssh
./usr/bin/oscap-ssh
78 blocks

The file name must be provided exactly as it is listed above with the “-t” option. Including the path and the “./”. Without the exact path, cpio will not extract the file(s). With the “-d” option, cpio creates the directory structure to extract the file if needed. The “-v” option can be added to see which files where extracted.

Cpio will extract the named file(s) into the current directory while keeping the directory structure of the archive. In the example above, the file will be extracted to the current directory in the “usr/bin/” subdirectory.

Option 2: rpmpeek

With rpmpeek(1), the name tells you exactly what it is. This little utility extracts the rpm into a temporary directory, allows you to execute any command in this directory and then deletes the directory again.

$ rpmpeek openscap-utils-1.2.13-2.el6.x86_64.rpm find .
.
./usr
./usr/bin
./usr/bin/oscap-vm
./usr/bin/oscap-chroot
./usr/bin/oscap-ssh
./usr/bin/scap-as-rpm
./usr/share
./usr/share/man
./usr/share/man/man8
./usr/share/man/man8/oscap-vm.8.gz
./usr/share/man/man8/oscap-chroot.8.gz
./usr/share/man/man8/scap-as-rpm.8.gz
./usr/share/man/man8/oscap-ssh.8.gz
./usr/share/doc
./usr/share/doc/openscap-utils-1.2.13
./usr/share/doc/openscap-utils-1.2.13/oscap-scan.cron
./etc
./etc/rc.d
./etc/rc.d/init.d
./etc/rc.d/init.d/oscap-scan
./etc/sysconfig
./etc/sysconfig/oscap-scan
./.fakedata

The above command allows to “peek” into the rpm downloaded earlier by using the find command to list all files contained in the rpm.

To extract the required file(s), a copy or move statement can be provided to the rpmpeek utility which copies the required files out of the temporary directory.

$ rpmpeek openscap-utils-1.2.13-2.el6.x86_64.rpm cp -rv usr/bin/* ~/
`usr/bin/oscap-vm' -> `/home/user/oscap-vm'
`usr/bin/oscap-chroot' -> `/home/user/oscap-chroot'
`usr/bin/oscap-ssh' -> `/home/user/oscap-ssh'
`usr/bin/scap-as-rpm' -> `/home/user/scap-as-rpm'

The above command provided to the rpmpeek utility copies all files from the /usr/bin/ directory recursively (-r) to the current user’s home directory.


Read more of my posts on my blog at https://blog.tinned-software.net/.

This entry was posted in Linux Administration and tagged , , , , , . Bookmark the permalink.