URPMI and RPM Tutorial

The aim of this tutorial is to show the new RPM user (who may or may not be a new Linux user) how to use URPMI and RPM for their own package management, and to help dispel the elitist view that RPMs suck (they don't).

Mandriva/Mandrake URPMI

If you've ever used Debian, you'll know that the killer feature is apt-get, which makes software installation and upgrades amazingly easy. There is a common perception that this solves all the nasty dependency problems that RPM-based distributions suffer from, and therefore RPM sucks.

This isn't quite the case. Would a Debian user typically use dpkg manually to do installation? Of course not. There is nothing inherently wrong with RPM as a package format, which is more or less comparable to dpkg. What we need is a tool built on top of RPM that does all the automatic dependency stuff for you like apt does.

The Mandriva distribution contains just such a tool: URPMI. This is probably Mandriva's most under-advertised feature, and easily the most important feature. With it, RPM package management is as easy as apt-get under Debian.

Setting up URPMI sources

Before you can use URPMI productively, you need to set up some package sources. Each URPMI repository contains a whole bunch of packages and an index file; URPMI needs to know where both are.

For the "usual" Mandriva sources, there is the helpful command generator at EasyURPMI that will tell you exactly what command to type in to add a source. If you just want to add the usual sources and be done with it, you need look no further. What follows is helpful if you want to understand a bit better what is going on under the hood and exactly what those magical incantations do.

As an example, let's add a source for the Mandrake contribs for 9.2. One location is at ftp://ftp.phys.ttu.edu/pub/mandrake/9.2/contrib/i586 and the hdlist is in the same place. We wish to name this source "contrib-ttu" The command is:

urpmi.addmedia contrib-ttu ftp://ftp.phys.ttu.edu/pub/mandrake/9.2/contrib/i586 with hdlist.cz

Most commands will look just like the above, with different ftp/http locations and possibly different paths. There are a few interesting but less commonly used options:

--distrib
Add all media from an installation medium
--update
Add an "update" medium (for MandrakeUpdate)
--from url
Use the url for a mirror list of possible locations

If you browse (via ftp or otherwise) some repository that you'd like to add, but you're not sure what command you need to type in, it's pretty easy to figure out what goes where:

  1. Look for the directory that contains a whole bunch of packages. This is the location
  2. Look for the corresponding hdlist file(s). These have names like hdlist.cz or similar. Typically this is in the same directory or reasonably nearby. The path must be a relative path. This is the hdlist
  3. Issue the command (as root):
    urpmi.addmedia mysource location with hdlist

Sometimes you have to hunt a level up or so in the tree to find a matching hdlist; the location for the updates hdlist is usually at ../base/hdlist.cz

The corresponding urpmi.removemedia command removes media.

Sources You Should Add

Every Mandriva/Mandrake user should have at least the following sources:

  • Original Installation CDs
    These should have been added automatically
  • Updates
    MandrakeUpdate should have added this for you
  • Mandriva/Mandrake Contribs
    This contains extra user-contributed packages and goodies. Most mirrors will carry contribs as well
  • PLF
    PLF contains various packages that were not included in Mandrake for various stupid legal reasons, such as DVD decryption (necessary for watching store-bought DVDs).
  • MandrivaClub Commercial
    If you are a member of MandrivaClub, you should also add the commercial software repository, for commercial products like Acrobat Reader.

Querying URPMI

With the right incantations, you can ask URPMI about your packages. The urpmq command lets you query the RPM database. The most useful commands are the following:

urpmq packagename
Asks whether URPMI has ever heard of packagename
urpmq --fuzzy name
Lists all known packages that sound vaguely like name
urpmq -i packagename
Displays summary and description of packagename
urpmq --list-media
Lists all known media

Installing Things

This is the easiest part: to install mypackage, we type:

urpmi mypackage

URPMI will automatically download and install mypackage, as well as anything that mypackage depends on. This is roughly equivalent to apt-get install mypackage

There are a number of advanced options worth knowing:

--update
Use only update media. Usually used for restricting the upgrades to security updates and the like.
--auto
Automatically installs dependencies without asking
--auto-select
Automatically upgrade all packages for which there are newer versions. In conjunction with --auto and --update, this allows you to automatically apply patches nightly and whatnot.
--noclean
Do not flush the RPM cache. You will find the RPMs in /var/cache/urpmi/rpms/
--allow-nodeps, --allow-force
If a dependency cannot be filled or there is a conflict, ask the user if he wants to shoot himself in the foot instead of refusing to go along with the insanity.
--fuzzy
Allow fuzzy search on the package name. If I mistype the package name, try to guess what I meant and ask me.

Keeping in Sync

URPMI works by maintaining a local index of all packages available on remote locations. This local list can get out of date and should be refreshed periodically by redownloading the remote list. This is easy:

urpmi.update -a

This will query every remote source and fetch the new lists if necessary.

Using RPM

You will probably use RPM itself very rarely, as URPMI is so much nicer. There are a few commands that I use when playing with downloaded packages and the like:

rpm -Uvh packages...
Install/upgrade packages, and let me know what happens
rpm -Uvh --force packages...
Install packages despite any warnings about dependencies or conflicts. Unless you know what you are doing, this tends to do bad things to your install. The warnings are there for a reason!
rpm -qi packagename
Tell me all about packagename, which is already installed.
rpm -qpi packagename-1.0mdk.i586.rpm
Tell me all about the package contained in packagename-1.0mdk.i586.rpm, which doesn't have to be installed.
rpm -q --changelog packagename
Display the changelog for the installed package packagename.
rpm -qa
List ALL packages installed on my system. Tends to produce a lot of output (which you can grep for what you want)

Safe and Sane RPM Usage

Why should you try to use RPM for everything? The simple answer is that for an RPM-based distribution, not using RPM consistently can leave the system confused about what is installed where.

For safe, sane RPM usage, keep in mind:

  • Packages from other distributions might do strange things. Every distribution has different ways of doing things, and a package meant for one distribution might behave strangely under another distribution. For example, you should not install packages from the Red Hat CDs onto your Mandriva system, especially since the naming conventions may be different and you might have a perfectly good version of the same thing on your Mandriva CDs.
  • Installing a program from source for which there is already an official package can do really weird things. The generic source tarballs usually install files to different places than the distribution-supplied packages, and really bad things can happen if the source version overwrites part (but not all) of the original distribution version, leaving an unholy (and probably un-working) hybrid. There IS a way to install from "source" and still keep everything sane; see below about SRPMs.
  • Furthermore, if you install using non-RPM methods, RPM doesn't know that the install occurred, and can't use that for dependencies. For example, if you decide to roll your own libwraster, and then try to install WindowMaker (which requires libwraster) via RPM, it'll think that libwraster isn't installed and refuse. Forcing the issue doesn't always help, because you might have put the files for libwraster in a different place than the WindowMaker RPM expects (this is only a hypothetical example).

Keeping your RPM database sane gives you the benefit of consistent package management, free of conflicts, and easy to query and update in an automated manner.

A Quick SRPM Tutorial

Since Linux is all about free software and open-source, you can find source RPMs (SRPMs) for every non-commercial package on your system. This gives you the source code in a form that, if you recompiled without modifications, gives you a new package rebuilt with exactly the same options and everything as the official binary.

Let's walk through a case of using SRPMs to make modifications to a package (this example is a little dated, as Mandrake is now Mandriva, but you'll get the idea). In this example, there is a bug in libwnck that causes the Gnome 2.4 Workspace Switcher applet to do really strange things if you are using the Sawfish window manager. The fix is easy, but we don't want to wait for an official version.

First, your system should be set up to build SRPMs. This step is unnecessary if you are doing this as root, but you really shouldn't do this as root (if anything goes wrong, you could hose your install). You need to create the directory structure under your home directory:

  • rpm
    • BUILD
    • RPMS
      • i586
      • noarch
    • SOURCES
    • SPECS
    • SRPMS
    • tmp

Also create the files ~/.rpmrc and ~/rpmmacros, containing the following:

~/.rpmrc
buildarchtranslate: i386: i586
buildarchtranslate: i486: i586
buildarchtranslate: i586: i586
buildarchtranslate: i686: i586
~/.rpmmacros
%_topdir               MY_HOME_DIR/rpm
%_tmppath              MY_HOME_DIR/rpm/tmp

%_signature            gpg
%_gpg_name             Mandrake Linux
%_gpg_path             ~/.gnupg
%distribution          Mandrake Linux
%vendor                MandrakeSoft

Obviously, MY_HOME_DIR should be wherever your actual home directory is. The buildarchtranslate stuff tells it to build all x86 stuff as i586. You can set this to i686 or something else, if you prefer, but i586 is the baseline for Mandrake. You are now ready to build!

First I download the original SRPM that the Mandrake folks used to build the original version: libwnck-2.4.0.1-1mdk.src.rpm. I expand the source tree with:

[walter@persephone walter]# rpm -ivh libwnck-2.4.0.1-1mdk.src.rpm
warning: user fcrozat does not exist - using root
warning: group fcrozat does not exist - using root
warning: user fcrozat does not exist - using root
warning: group fcrozat does not exist - using root
   1:libwnck                ########################################### [100%]
[walter@persephone walter]#

The warnings are there because the user fcrozat (the guy who originally built this RPM) does not exist on my computer. Not a big deal.

I find that there are all sorts of goodies now in ~/rpm/:

[walter@persephone walter]# cd ~/rpm/
[walter@persephone rpm]# ls
BUILD/  RPMS/  SOURCES/  SPECS/  SRPMS/
[walter@persephone rpm]#

The finished RPMs go in RPMS, the source code lives in SOURCES, and the spec files (which describes the package) is in SPECS.

[walter@persephone rpm]# cd SOURCES/
[walter@persephone SOURCES]# ls
libwnck-2.4.0.1.tar.bz2
[walter@persephone SOURCES]# tar xjvf libwnck-2.4.0.1.tar.bz2
many lines snipped...

I can now delete the old tar file and make my changes. In this case, I remove the call to wnck_screen_move_viewport on line 1158 of ~/rpm/SOURCES/libwnck-2.4.0.1/libwnck/pager.c

Now I should put everything back together. Starting from SOURCES, I do the following:

[walter@persephone SOURCES]# tar cjf libwnck-2.4.0.1.tar.bz2 libwnck-2.4.0.1
[walter@persephone SOURCES]# rpm -ba ../SPECS/libwnck.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.92973
+ umask 022
+ cd /usr/src/RPM/BUILD
...many lines skipped...
+ rm -rf /var/tmp/libwnck-2.4.0.1-buildroot
+ exit 0

The last step is to install my newly created custom RPMs. Since I didn't change the version number, if libwnck is already installed, RPM won't install it again, so I have to force the issue (yes, I do know what I'm doing). This will overwrite my existing libwnck installation with the one I just made. As root, I do:

[root@persephone SOURCES]# rpm -Uvh --force ../RPMS/i586/libwnck-*

And we're good to go! For more help, consult the official forums.