Chapter 33
RPM - The Red Hat Package Manager
|
|
|
|
|
![](gif/black.gif) |
In this chapter: |
|
|
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
An introduction to the Red Hat Package Manager (RPM)
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
RPM's capabilities
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
SuSE's integration of RPM
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
RPM in action -- installation, management, verification, and removal of packages
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Potential pitfalls with RPM on the SuSE Linux platform
|
|
|
|
![](gif/black.gif) |
|
Red Hat Package Manager (RPM) is the package management tool used by
the SuSE distribution. Historically, SuSE had a tight alignment with
the Slackware and Jurix distributions. When SuSE began to publish a
Linux distribution, it was basically a Slackware distribution with a
German installation and a couple of bug fixes. As the Linux business
grew, the need for a native SuSE distribution increased. That's when
SuSE decided to make Jurix the basis for its own SuSE Linux
distribution. SuSE chose the RPM (the Red Hat Package Manager) which
was about to become teh de facto standard at that time. While RPM does
contain Red Hat in the name, it is completely intended to be an open
packaging system available for anyone to use. Since SuSE uses RPM, it
contributed bug fixes to the code as it became involved in RPM's
development.
|
![NOTE](gif/icon_note.gif) |
Because of the different aspects of RPM, we need some convention for
referring to RPM. In this chapter we will use 'RPM' when we talk about
the package management tool in general and rpm to refer
to the tool itself.
|
|
The regular SuSE Linux user almost never actually sees the
rpm tool or has to call it manually. YaST acts as a
wrapper to it and hides RPM from the user. This chapter will give an
overview of RPM's main concepts. We will see practical examples on how
to use the rpm-tool in the chapters 35
and
36
.
RPM has two major modes of operation: package management and package
development. The package development aspect is discussed in chapter
35
and
36
. In this chapter we will learn how
to use rpm to manage RPM packages. We won't go into too
much detail here. RPM is another example of a tool which fills
an entire book on its own. In this case that book is 'Maximum RPM',
Red Hat Press, 1997 by Edward Bailey. The book is available online as
PostScript or LaTeX source at http://www.rpm.org. You'll
find a lot of useful information about RPM here. A good first point to
find out more about RPM is its man page rpm(8).
|
33.1 | Installing Packages |
|
RPM is most commonly used for package installation. The call to
install a package with rpm is:
|
| #rpm -i install-options package-list
|
|
As package-list, rpm takes a list of
files or URLs pointing to a file on an FTP server. For example, to
install the Secure Shell on your system, you could use the command:
|
| # rpm -i ftp://ftp.gwdg.de/pub/linux/suse/6.1/i386.de/suse/sec1/ssh.rpm
|
|
You can list as many package files as you want and mix local with FTP
files. There are two sources-FTP and local hard disk. You can use
local hard disk and/or FTP files. You are not obligated to use one or
the other. They can be used in any combination you chose. The install-options
are listed in table 34-1
. We'll discuss them a little bit later.
|
Table 33-1 |
RPM Options for Package Installation or Upgrade |
|
Option |
Meaning |
--relocate old=new |
relocate files from old to new path |
--badreloc |
relocate files even though the package doesn't allow it |
--prefix dir |
relocate the package to dir, if relocatable |
--dbpath dir |
use dir as the directory for the database |
--excludedocs |
do not install documentation |
--force |
short hand for --replacepkgs --replacefiles |
-h or --hash |
print hash marks as package installs (good with -v) |
--allfiles |
install all files, even configurations which might otherwise be skipped |
--ignorearch |
don't verify package architecture |
--ignoreos |
don't verify package operating system |
--includedocs |
install documentation |
--justdb |
update the database, but do not modify the filesystem |
--nodeps |
do not verify package dependencies |
--noorder |
do not reorder package installation to satisfy dependencies |
--noscripts |
don't execute any installation scripts |
--notriggers |
don't execute any scripts triggered by this package |
--percent |
print percentages as package installs |
--replacefiles |
install even if the package replaces installed files |
--replacepkgs |
reinstall if the package is already present |
--root dir |
use dir as the top level directory |
--test |
don't install, but tell if it would work or not |
--oldpackage |
upgrade to an old version of the package (--force on upgrades does this automatically) |
-v |
be verbose |
-vv |
print lots of ugly debugging information |
|
|
What does RPM do when it installs a package? If the task were simply
to unpack the archive, why would we need it anyway? Obviously, RPM
does a lot more than just copy files. It performs a number of tasks
during the package installation. Some of them take place before
anything is copied to the hard disk, some of them take care of post
installation issues. Let's look at those steps:
|
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Dependency checks
It's no secret that some, if not the most, packages require other
packages to be installed prior to their installation so that they can operate properly. RPM checks prior to the installation if all dependencies
listed in the package are resolved. It also checks if the new package
will cause dependency problems for packages that already exist.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Checking for Conflicts
The package you try to install may conflict with software already installed
on your system. You may have the package installed already,
and the installed version is newer then the one you are trying to
install. Or a file contained in the new package will overwrite a file of
another package. Things like this are checked prior to the actual
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Performing Pre-Installation Tasks
The package builder may have included commands or scripts to be
executed before the package is installed. We'll see later in
chapter 36
how to do this, when we actually create an RPM
package. Anyway, these tasks are performed by the rpm-tool.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Handling configuration files
RPM allows the packager to mark files as configuration files. These are handled in
a special way to ensure that customizations don't get lost when a
package is upgraded. We will see how this is done in the next section
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Copying the files from the archive to the hard drive
This is the actual installation. The package files are copied
to the hard drive. Their owner, group, and permission attributes are
set accordingly.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Performing Post-Installation Tasks
Lots of packages require certain tasks to take place after they
have been installed. This may be an additional entry in
/etc/rc.config, the customization of the window manager menus,
etc. Like the pre-install tasks, this actions are specified by the
package builder and we will see examples how to do this in
chapter 36
.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Updating the Package Database
RPM keeps track of all of its action in this database. The database
contains information about all files installed. This includes which package
they are contained in, the type of file (documentation, configuration,
etc.), the installation date, checksums, and so on. It uses this
information to find out about conflicts and to check
dependencies. We'll see in the section about package maintenance how
to query this database.
|
|
|
As an example of how RPM works, we will use the package
dosemu.rpm. This package is part of the SuSE Linux
distribution, so you could use YaST to install it, but hey, we need
something to play with. Assuming the RPM file is
/tmp/dosemu.rpm, we can install the package simply by
executing the command:
|
| # rpm -i /tmp/dosemu.rpm
|
|
Not very exiting. To get more out of it, we can tell rpm to be
verbose by adding the -v switch:
|
| # rpm -i -v /tmp/dosemu.rpm
Installing dosemu.rpm
|
|
At least we get some output now. To see exactly what's going on, use
the -vv option instead of -v:
|
| Maggie:/tmp # rpm -i -vv dosemu.rpm
D: counting packages to install
D: found 1 packages
D: looking for packages to download
D: retrieved 0 packages
D: finding source and binary packages
D: New Header signature
D: Signature size: 68
D: Signature pad : 4
D: sigsize : 72
D: Header + Archive: 1397497
D: expected size : 1397497
D: found 0 source and 1 binary packages
D: opening database mode: 0102
D: opening database in //var/lib/rpm/
D: dependencies: looking for mtools
D: dependencies: looking for binutils
D: dependencies: looking for /bin/sh
D: dependencies: looking for /bin/bash
D: dependencies: looking for /bin/sh
D: installing binary packages
Installing dosemu.rpm
D: New Header signature
D: Signature size: 68
D: Signature pad : 4
D: sigsize : 72
D: Header + Archive: 1397497
D: expected size : 1397497
D: package: dosemu-0.98.6-3 files test = 0
D: running preinstall script (if any)
D: running postinstall script (if any)
+ cd var/lib/dosemu
+ ../../../usr/bin/mkfatimage16 -b dosC/boot.bin -p -f hdimage.test -l DOSEMU dosC/ipl.sys
dosC/kernel.exe dosC/command.com commands/aspi.sys commands/autoexec.bat
commands/bootoff.com commands/booton.com commands/cdrom.sys commands/cmdline.exe
commands/config.sys commands/dosdbg.exe commands/dumpconf.sys commands/ecpuoff.com
commands/ecpuon.com commands/eject.com commands/ems.sys commands/emufs.sys
commands/emumouse.exe commands/exitemu.com commands/ezedit.com commands/ezedit.doc
commands/fossil.com commands/isemu.com commands/lredir.exe commands/mgarrot.com
commands/speed.com commands/system.com commands/uchdir.com commands/ugetcwd.com
commands/unix.exe commands/vgaoff.com commands/vgaon.com commands/xmode.exe
|
|
Ok, here we go. This may be more information than we really wanted to
have. Another nice switch is -h. This way, you get a hash
sign (#) for every two percent of the
installation. Combined with -v, you get the output you
ordinarily get when YaST installs packages (in fact, YaST uses these
options):
|
| # rpm -i -h -v dosemu.rpm
dosemu ##################################################
|
|
These are probably the most oft-used options for installing
packages. Sometimes, you may need to use some of the more
advanced options from table 33-1. We won't explain all of
them here, just the ones used most frequently:
|
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
--test: Perform tests, but don't install
As the headline says, this option assigns rpm to do all the
checks and tell you the action it would perform. This
option us useful if you want to see if an installation would be successful, or to check
for unresolved dependencies before preceding.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
--replacepkgs: Install package even if it is installed already
If you need to fix a package that is already installed, you can use this
option to install a new copy of the package without removing the old
one. This way you can make sure that none of the files that belong to
this package are damaged.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
--replacefiles: Install even when existing files are overwritten
While RPM usually prohibits one package from overwriting files of
another package, you can bypass this restriction by specifying the option
--replacefiles.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
--nodeps: Ignore dependencies
This switch disables RPM's dependency checking. With this switch
packages will be installed even when RPM recognizes unresolved
dependencies.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
--force: Do it anyway
With this switch enabled, the only thing that will stop RPM from
installing the package are unresolved dependencies. Entering
--force on the command line is like telling RPM that you're not
interested in any conflict with existing packages. Combining it with
--nodeps guarantees that the package will be installed. Whether
it'll work or not is another matter.
|
|
|
|
![NOTE](gif/icon_note.gif) |
Despite the fact that RPM has a dependency mechanism, SuSE
doesn't make extensive use of it. YaST has its own dependency
database and uses this instead of the RPM features. In fact, SuSE's
dependency mechanism allows for more flexibility than RPM. The
downside of this is that if you try to install a package file using
RPM on the command line, you may get errors that dependencies are not
resolved. YaST uses the options --nodeps --force to install
packages. If you run into trouble give this a try. There is a slight chance that it will work.
|
|
So much about using RPM to install new packages. My recommendation is
that you not use it for this task. YaST allows you to do almost everything
you need to do with plain old rpm. Sometimes the command line is
just the fastest way to get things done.
|
33.2 | Upgrading Packages |
|
One of the reasons SuSE decided to use RPM is because of the package
database and how it enables RPM to upgrade packages. One would think
upgrading a package is the same as removing the old version and
installing the new one. It's not quite that simple. Most software has
some kind of configuration data stored in a configuration file. If you
do the upgrade as instructed, the configuration will be lost. This is
in especially painful if you invested time in customizing the
installation.
In terms of the rpm command line, upgrading follows
almost the same syntax as installing a new package. The only
difference is that instead of using the switch -i for
installation, you use -U for upgrade. The options listed
in table 33-1 are valid for both modes, installation and
upgrade.
Back to the configuration file issue. How does RPM handle this?
First of all, it knows which files are configuration files. The package
builder marked these files. When the package is installed for the
first time, a checksum (MD5) is generated for each file contained in
the package. Using this checksum RPM can decide if any modifications
have taken place.
In fact, there are three versions of any configuration file involved
in a package upgrade. A checksum for each file is calculated and used
in the upgrade procedure:
|
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
The Original File
This is the file that came from the original (the very first)
installation of the package.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
The Current Filee
By this I mean the file as it is just prior to the upgrade,
including all changes you may have made to it.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
The New Filee
As we are performing an upgrade, the new version of the package
probably includes a new version of the configuration file too (it
should). This version is what we are referring to as the new
file.
|
|
|
This leads us to several combinations of checksums for these three
files and to referring actions which have to take place for each of
these combinations. Let's walk through the possible scenarios.
We'll use the letters X, Y, Z
in place of the lengthy MD5 checksums:
|
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Original = X, Current = X, New = X
All three files are the same. RPM takes the file from the new package
and installs it over the old copy. It does this to make sure that
changes in ownership or permissions which may possibly exist in the
new package are taken care of.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Original = X, Current = X, New = Y
The new file is different form the original, but the original
configuration hasn't been changed. RPM does the same as in the first
case. It takes the file from the new package and installs it over the
original file. This makes total sense. No customization is lost since
nobody changed the original. The new version may include bug fixes or
other improvements, so it's a wise decision to use this one for the
upgraded version of the package.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Original = X, Current = Y, New = X
The new file is identical to the original, but the original has been
changed. The existing file will stay in place. RPM makes the
assumption that as the original equals the new version of the file,
the modifications made to this file should be valid for the new
version of the package too.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Original = X, Current = Y, New = Y
The original file was changed, but the changes reflect the new
version. These modification may have fixed a bug and the same bug fix
was incorporated into the new version. RPM uses the new version in
this case. The same philosophy applies as in the first scenario since
permission and user flags may have changed. And as the file contents
are the same (MD5 guarantees this) it doesn't really make a difference
anyway.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Original = X, Current = Y, New = Z
Here we come to the more interesting cases. The original has been
modified at some point, and the new version is different from the
original and the current file.
This case is difficult to handle. RPM can't analyze the file
contents. So it goes the safe route. It creates a backup
copy of the current version and then installs the new version of the
file. The backup copy has the same name as the original (and the new)
file, with the extension .rpmsave added to it.
This is a reasonable approach. RPM knows that the original and the new
version are different. It's reasonable to assume that extensive changes have taken place.
It also knows that the new version works
with the new package. This can't be guaranteed for the original
file. However, someone took the effort to change the original. Maybe
those changes are still useful and can easily be applied to the new
configuration, so saving those changes is a good idea.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Original = ??, Current = X, New = y
We know nothing about the original, and the current and the new file
are different. This scenario can't happen when the original was
installed with RPM. If this was the case, there would be a checksum
for this file in the RPM database. But as RPM is a friendly tool, it
handles this case anyway.
As there is no checksum for the original, the checksum for the current
version doesn't tell us a whole lot either, so we don't know if it has
changed or not. RPM reacts to this scenario in a similar way as
described in the last section. It uses the new file and creates a
backup copy of the current version. In this case the extension
.rpmorig will be added to the filename. This way you can
distinguish between files RPM knew of and files RPM saw for the
first time during the upgrade.
|
|
|
As you see, RPM is capable of taking care of your configuration. If it
creates backup files it'll print out a warning to inform that there is
something you should be aware of. If you do a lot of upgrades in one
batch, it may be easier to search for .rpmsave and
.rpmorig files after the batch is finished, rather than
watching the job and look out for warning messages.
|
33.3 | Querying Package Information |
|
RPM's usefulness doesn't end with the package installation. We
learned that rpm uses the RPM database for certain tasks, but
this database is not only of interest to RPM. Since it contains
complete information on what is installed on your system and where did it
came from, it holds valuable information for the system administration
in its human form factor as well. But that's not all. You can also use RPM to
gain information about packages you have not yet installed. This may be even more
interesting, as you may want to know what you put on your system prior
to installing it.
The tables 34-2
and
34-3
list the options
for rpm used for queries either on the database or on a
package file. You see we divided the options in two parts. One to list
option used to select the package or packages we want to get
information about. And the second one with options to select the kind
of information we are interested in.
|
33.3.1 | Package Selection |
|
First let's see how we tell rpm which package(s) we want
to get information about. The first choice is do we want to know
something about a package that has already been installed, or do we
want to have a sneak peek into a package file? The latter case is the
easiest one, so we'll discuss it first.
|
| Query a Specific RPM Package File |
|
As you can see in table 34-2
, the switch -p
allows you to specify a package file as the query's target. Combined
with the query switch -q, it will tell you which package
is contained in this file:
|
| # rpm -qp dosemu.rpm
dosemu-0.98.6-3
|
|
You see the file dosemu.rpm contains the package
dosemu-0.98.6-3. The package label is not related in any
way to the filename. It's contained in the package itself. This means
even when you rename the file, the package name will remain the same:
|
| # mv dosemu.rpm DosEmulation.rpm-package
# rpm -qp DosEmulation.rpm-package
dosemu-0.98.6-3
|
|
|
![NOTE](gif/icon_note.gif) |
A package label is composed of three parts. The name of the packaged
software (dosemu), the version of the packaged software
(0.98.6), and the package's release number
(3). This is important to know when we issue queries on
the RPM database. To specify a package within the RPM database, we
have to be aware of this labeling scheme.
|
|
|
Table 33-2 |
RPM Query Package Specification Options |
|
Option |
Meaning |
-a |
query all packages |
-f files |
query package owning file |
-p packagefiles |
query (uninstalled) package packagefile |
--triggeredby pkg |
query packages triggered by pkg |
--whatprovides cap |
query packages which provide cap capability |
--whatrequires cap |
query packages which require cap capability |
|
|
|
| Querying the RPM Database |
|
Assuming that the dosemu package is installed, we can
select it within the RPM database by addressing it by either by its
name, the name and the version number, or by giving the full label
including name, version number and release number:
|
| # rpm -q dosemu
dosemu-0.98.6-3
# rpm -q dosemu-0.98.6
dosemu-0.98.6-3
# rpm -q dosemu-0.98.6-3
dosemu-0.98.6-3
|
|
The result in all cases is the full label.
|
![CAUTION](gif/icon_caution.gif) |
rpm is case sensitive and doesn't match partial
names. Here are examples for queries that don't work:
|
| # rpm -q DosEmu
package DosEmu is not installed
# rpm -q "dos*"
package dos* is not installed
# rpm -q dos
package dos is not installed
# rpm -q dosemu-0.98
package dosemu-0.98 is not installed
|
|
|
|
You see this mechanism isn't very powerful if you don't know the exact
name of the package you are looking for. But there are ways to get the
exact name if you have a faint idea of what it is. You can get a list
of all installed packages using the -a option:
|
| # rpm -qa
aaa_base-99.4.19-0
aaa_dir-99.4.19-0
aaa_skel-99.4.9-0
at-3.1.8-54
base-99.4.9-1
bash-2.02.1-38
bash1-1.14.7-59
bdflush-1.5-61
compress-4.2.4-58
[...]
|
|
|
![TIP](gif/icon_tip.gif) |
If you only have part of the name, you can pipe this output to grep and easily find a package's full name:
|
| # rpm -qa | grep -i "Dos"
mkdosfs-0.4-56
dosemu-0.98.6-3
|
|
|
|
|
| Query Package Containing a Specific File |
|
If you have a file and you want to know the package it belongs to,
you can use the -f switch to find out about this:
|
| # rpm -qf /etc/inittab
aaa_base-99.4.19-0
|
|
If you ask for a file that wasn't installed by RPM, it will tell you
this too:
|
| # rpm -qf /etc/lilo.conf
file /etc/lilo.conf is not owned by any package
|
|
|
![CAUTION](gif/icon_caution.gif) |
There is a tricky detail about these kinds of queries. Beware of
links. Let's say you want to know the package of the file
/usr/X11/bin/xterm. You'll probably get a surprising
result -- it's not contained in any package:
|
| # rpm -qf /usr/X11/bin/xterm
file /usr/X11/bin/xterm is not owned by any package
|
|
The puzzle is how this can be since it had to come from somewhere. The
answer is that /usr/X11 is a soft-link to
/usr/X11R6. When you ask for /usr/X11R6/bin/xterm
you'll get the reply that it's a part of xf86-3.3.3.1-20:
|
| # rpm -qf /usr/X11R6/bin/xterm
xf86-3.3.3.1-20
|
|
How to avoid those trapdoors? Unfortunately, there is no specific answer.
One piece of advice is to use the utility namei, which follows a
pathname until a terminal point is found. In our example you would
see very quickly that there is a soft link in the path to
xterm as we first indicated:
|
| >namei /usr/X11/bin/xterm
f: /usr/X11/bin/xterm
d /
d usr
l X11 -> X11R6
d X11R6
d bin
- xterm
|
|
For more information on namei refer to it's man page
namei(1).
|
|
|
![NOTE](gif/icon_note.gif) |
RPM supports a few more selection mechanisms. You can place queries
based on requirements of packages, on what a package provides, or on
the group a package belongs to. These features however are not used by
SuSE, so using them doesn't make a whole lot of sense. SuSE doesn't
make very much use of the provide/require mechanism RPM offers. YaST
has its own database of requirements which exceeds RPM's abilities.
YaST also takes care of grouping the packages into series. The RPM
group SuSE choose to put packages in is the same for all package
files: unsorted.
|
|
|
33.3.2 | Information Selection |
|
So far the only results we got from a query were package labels. Not
very exciting. But the examples given in the last section were intended
to demonstrate how to focus the query on certain packages. This
section will show us which information RPM can provide about those
packages. Table 34-3
gives a short overview of the
options used to select the desired information.
|
Table 33-3 |
RPM Query Information Selection Options |
|
Option |
Meaning |
-i |
display package information |
--changelog |
display the package's change log |
-l |
display package file list |
-s |
show file states (implies -l) |
-d |
list only documentation files (implies -l) |
-c |
list only configuration files (implies -l) |
--dump |
show all verifiable information for each file (must be used with -l, -c, or -d) |
--provides |
list capabilities package provides |
--requires or -R |
list package dependencies |
--scripts |
print the various (un)install scripts |
--triggers |
show the trigger scripts contained in the package |
-V or -y or--pipe cmd |
send stdout to cmd |
--verify |
verify a package installation using the same same package specification options as -q |
--nodeps |
do not verify package dependencies |
--nomd5 |
do not verify file md5 checksums |
--nofiles |
do not verify file attributes |
|
|
|
| General Package Information |
|
Adding -i to rpm -q tells RPM to give you
general package information contained in the package file. Look at the
package rxvt as an example:
|
| # rpm -qi rxvt
Name : rxvt Distribution: SuSE Linux 6.1 (i386)
Version : 2.4.7 Vendor: SuSE GmbH, Nuernberg, Germany
Release : 28 Build Date: Thu Apr 15 00:26:33 1999
Install date: Mon Jun 14 23:08:19 1999 Build Host: Fenchel.suse.de
Group : unsorted Source RPM: rxvt-2.4.7-28.src.rpm
Size : 417457 License: 1999 - not specified
Packager : feedback@suse.de
Summary : The 'other' X-Terminal.
Description :
rxvt is as small as xterm. That's why many people like it.
This package also includes rclock - it is now included in the rxvt source
package.
Authors:
--------
Mark Olesen <olesen@me.QueensU.CA>
Robert Nation <nation@rocket.sanders.lockheed.com>
|
|
The above information is pretty obvious, so I won't go into details
here. Note that the version number and the release number are listed
separately. The release number is used to distinguish between separate
packages which contain the same version of the software. This may
sound confusing, but it makes sense when you think about it. Assume a
package has been built and released on the SuSE Linux
distribution. Then a bug is found and a patch becomes available. At
this point SuSE often decides to make an update available as an RPM
package on its FTP server. Now what if the original author of the
package didn't incorporate the fix yet and the software has still the
same version number? It would be hard to distinguish between the
package with the bug fix and the old one without the fix. This is
often the situation when the release number gets incremented. Now you
can see which package is the newer on. Usually the release number is
zero (0) for the initial build of the package. It is
incremented with every release of the same software version. Every
time the version of the software changes, the release number is reset
to zero.
|
| The Package's File List |
|
Another very interesting part of the package is the list of files
it contains. You get a full file list with the -l switch:
|
| # rpm -ql rxvt
/usr/X11R6/bin/rclock
/usr/X11R6/bin/rxvt
[...]
/usr/doc/packages/rxvt/rxvtRef.txt
/usr/doc/packages/rxvt/xterm.seq
|
|
If you add -v to rpm -ql, than the list includes the
file attributes:
|
| # rpm -qlv rxvt
-rwxr-xr-x root root 34376 Apr 15 00:26 /usr/X11R6/bin/rclock
-rwxr-xr-x root tty 104572 Apr 15 00:26 /usr/X11R6/bin/rxvt
[...]
-rw-r--r-- root root 26150 Aug 27 17:13 /usr/doc/packages/rxvt/rxvtRef.txt
-rw-r--r-- root root 16051 Apr 19 1998 /usr/doc/packages/rxvt/xterm.seq
|
|
We saw that RPM distinguishes between regular, configuration, and
documentation files. Since those files are marked as such within the
RPM package file, you can get them listed separately. The option
-c selects configuration files, and with -d
you get documentation files:
|
| # rpm -qc rxvt
/usr/X11R6/lib/X11/app-defaults/Rxvt
# rpm -qd rxvt
/usr/X11R6/man/man1/rclock.1.gz
/usr/X11R6/man/man1/rxvt.1.gz
/usr/doc/packages/rxvt/BUGS
/usr/doc/packages/rxvt/FAQ
/usr/doc/packages/rxvt/README.SuSE
/usr/doc/packages/rxvt/README.greek
/usr/doc/packages/rxvt/README.menu
/usr/doc/packages/rxvt/README.xvt
/usr/doc/packages/rxvt/TODO
/usr/doc/packages/rxvt/menu/example.menu
/usr/doc/packages/rxvt/menu/jedmenu.sl
/usr/doc/packages/rxvt/menu/menu
/usr/doc/packages/rxvt/menu/rxvt.menu
/usr/doc/packages/rxvt/menu/terminal.menu
/usr/doc/packages/rxvt/rxvt.html
/usr/doc/packages/rxvt/rxvtRef-frame.html
/usr/doc/packages/rxvt/rxvtRef-toc.html
/usr/doc/packages/rxvt/rxvtRef.html
/usr/doc/packages/rxvt/rxvtRef.txt
/usr/doc/packages/rxvt/xterm.seq
|
|
The configuration files are especially interesting. The combination of
-a to select all packages and -c to specify
the configuration files gives you an easy way to list all
configuration files in the system that RPM knows about:
|
| # rpm -qac
/etc/DIR_COLORS
/etc/conf.modules
/etc/csh.cshrc
/etc/csh.login
/etc/inittab
/etc/inputrc
/etc/issue
/etc/issue.net
[...]
|
|
There are many more ways to use RPM for requests on package files or
the package database. But getting the file list and the general
package information are by far the most used ones. Refer to the
sources given at the beginning of this chapter for more query options.
|
33.4 | Verification of installed packages |
|
Sometimes its handy to have an easy way to verify that an installed
packages is still 'OK'. RPM's verification function is a nice tool
that supports you with this task. It can alert you to changes made to
any of the files installed by RPM. The command rpm -V
verifies an installed package. The selection of the package is made
the same way as we have seen it in the last section for queries on the
RPM database. The options in table 33-2 work the same
way with the -V switch. Table 34-4
lists
additional options for package validation.
|
Table 33-4 |
RPM Verification Options |
|
Option |
Meaning |
--nomd5 |
do not verify file md5 checksums |
--nodeps |
do not verify package dependencies |
--nofiles |
do not verify file attributes |
|
|
In the list of options, you'll see that they are meant to switch on
certain checks. But which checks are performed by default? RPM
verifies that package dependencies are resolved, that all the files
listed for the package in the RPM database are present in the system,
and it verifies the following attributes for each file of the package:
|
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
File owner and group,
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
File permissions (mode),
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
MD5 checksum,
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
File size,
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
File major and minor number (for special device files),
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Symbolic link string (if file is a soft link), and
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
File modification time.
|
|
|
|
![NOTE](gif/icon_note.gif) |
A word on the MD5 checksums. They came up a couple of times
before without a full explanation. The MD5 checksum of a file
is a 128-bit number derived from the file's content. The algorithm was
designed by Ron Rovest, the 'R' in the popular RSA algorithm for
encryption. 'MD' stands for Message Digest, but unlike
literary digests, the MD5 checksum conveys no information about the
file's contents. However it guarantees that any change in the file
results in a change to the MD5 checksum. So MD5 checksums are a
perfect way to see if a file has changed since the checksum has been
calculated the last time. RPM stores MD5 checksums for every file it
installed in its database. So it's an easy task to find modified files
using RPM.
|
|
So much about the theory, let's get practical again. To verify the
contents of an installed package, just call rpm -V
package-label. For example, to check the package
rxvt do the following:
|
| # rpm -V rxvt
.M...... /usr/X11R6/bin/rxvt
|
|
RPM reports only those files where it found differences in the values
of the attributes stored in its database. You see the file
/usr/X11R6/bin/rxvt has been changed. Each file reported
is preceded by a nine digit string. This string tells you which
modifications have been found:
|
| SM5DLUGT
||||||||
|||||||+- Modification Time
||||||+-- Group
|||||+--- Owner (User)
||||+---- Symbolic Link String
|||+----- Major/Minor Number
||+------ MD5 Checksum
|+------- Permissions (Mode)
+-------- Size
|
|
For our rxvt example this means that the permissions have been
changed. To make the example complete, we will do an RPM query to see
how the permissions should be set by referring to the RPM database and how
they are for the actual file. So we can see what exactly has been
modified:
|
| # rpm -qflv /usr/X11R6/bin/rxvt | grep "/usr/X11R6/bin/rxvt"
-rwxr-xr-x root tty 104572 Apr 15 00:26 /usr/X11R6/bin/rxvt
-rwxr-xr-x root root 108244 Apr 15 00:26 /usr/X11R6/bin/rxvt.xpm
# ls -l /usr/X11R6/bin/rxvt
-rwsr-xr-x 1 root tty 104572 Apr 15 00:26 /usr/X11R6/bin/rxvt
|
|
You see the set-user-id bit has been set for this binary. If this
happened in the real world, and you didn't know who changed this, it
would be an alert to check the whole system for a possible intruder?
(refer to part IV to see more about security issues).
|
![NOTE](gif/icon_note.gif) |
In this case everything is OK. The permissions have been changed by
SuSE, which is why we picked this example. It demonstrates that the
RPM database can't be used as a reliable reference on a SuSE
system. As explained in chapter 24, SuSE has its own
lists of permissions in /etc/permissions*. If you look in
/etc/permissions.easy, you will see that the set-user-id
flag for the rxvt binary is turned on in there. That's
why the flag changed and RPM reported this file. So no security alert,
everything is fine. Sometimes it's good to beware of 'the SuSE
way'. SuSE used RPM as package manager, but a lot of RPM features
interfere with native SuSE mechanisms.
|
|
|
33.5 | Removing Packages |
|
RPM would be a poor example of package management if it wouldn't
support the uninstallation of installed software. But of course it
covers this aspect of package management too. With rpm -e
(e like erase), you can remove installed
packages. As usual there are additional flags to this command which
are listed in table 34-5
.
|
Table 33-5 |
RPM Erase Options |
|
Option |
Meaning |
--allmatches |
remove all packages which match |
--justdb |
update the database, but do not modify the file system |
--nodeps |
do not verify package dependencies |
--noorder |
do not reorder package installation to satisfy dependencies |
--noscripts |
do not execute any package specific scripts |
--notriggers |
don't execute any scripts triggered by this package |
|
|
There is not very much more to say about this. The steps RPM performs
to remove a package are:
|
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Check if any other package relies on the package that you want to
remove. If so, RPM won't remove the package and will print an error
message.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Execute pre-uninstall scripts if those exist for this package.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Check if any configuration file of the package has been
changed. If so, copies of these files will be saved.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Delete all files of the package which are not part of any other package.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Execute post-uninstall scripts if those exist for this package.
|
![*](gif/bullet.gif) ![](gif/clear.gif) |
Remove all traces of the package from the RPM database.
|
|
|
You see RPM does pretty much what you probably expect it to do. No
surprises here. To see a short example, remove the package
dosemu that we installed at the beginning of this chapter:
|
| # rpm -e dosemu
cannot remove /var/lib/dosemu - directory not empty
|
|
You see there is a warning message that the directory
/var/lib/dosemu, which is expected to be empty, can not
be removed because there are still files in it. If you look into this
directory you'll find the file hdimage.test, which was
created by the post-install script of the dosemu
package. One can argue if this file should have been removed by the
pre-uninstall script or not. It certainly would make the package
removal cleaner. This is an issue to discuss with package builder, and
not a topic for this chapter.
|
![](gif/black.gif) |
Summary: |
|
In this chapter we learned how to use RPM, the Red Hat package
manager, for daily administrative tasks. We saw how we can install
and uninstall packages, how to use the RPM database to keep track of the
packages installed on the system, and how to use RPM to ensure that the
actually installed files are consistent with the records of the RPM database.
|
![](gif/black.gif) |