While making some custom RPMs and then remaking them with altered build steps, I stumbled across the behaviour that rpm will let you install updated packages even when an older package is already installed, provided that none of the files in the new package have changed.
Here’s a demonstration using a simple spec file (Listing 1) for an RPM package that installs a README
file in /tmp/rpmtest/
. Note the %install
process creates the README
file with some text in it.
Build the RPM package from the spec file:
$ rpmbuild -bb rpmtest.spec
and install it:
$ sudo rpm -i /scratch/RPM/RPMS/x86_64/rpmtest-1-1.x86_64.rpm
Now, the single README
file is installed:
$ ls -l /tmp/rpmtest/README
-rw-r--r-- 1 cdaily cdaily 10 Nov 14 16:39 /tmp/rpmtest/README
Now we’ll update the rpmtest.spec
file to build Version 1, Release 2. Then we change the rpm’s install process but not the README
contents. For example, in the rpmtest.spec
change the defattr, line 22, from
%defattr(-, %(%{__id_u} -n), %(%{__id_u} -n), -)
to
%defattr(-, root, root)
and change the spec file’s Release
to
Release: 2
(line 4).
The generated README
file will be the same, only the file ownership changes between releases.
Build as before and try to install.
$ sudo rpm -ivh /scratch/RPM/RPMS/x86_64/rpmtest-1-2.x86_64.rpm
That worked. I’m able to install Version 1, Release 2 and it does not conflict with Release 1.
The README
is now owned by root.
$ ls -l /tmp/rpmtest/README
-rw-r--r-- 1 root root 10 Nov 14 16:47 /tmp/rpmtest/README
I have both packages installed:
$ rpm -qa rpmtest
rpmtest-1-1
rpmtest-1-2
And the README
is owned by both packages:
$ rpm -qf /tmp/rpmtest/README
rpmtest-1-1
rpmtest-1-2
The same happens if you increment the Version. As long as the checksums for all the package files are unchanged, the rpm install will proceed.
Remove them both:
$ sudo rpm -e rpmtest-1-1 rpmtest-1-2
Let’s see what happens when the change a package file. In the rpmtest.spec
file, change line 16
echo "This is a readme" > $RPM_BUILD_ROOT/tmp/rpmtest/README
to
echo VERSION %{version} RELEASE %{release} > $RPM_BUILD_ROOT/tmp/rpmtest/README
That is, the README
contents will now have the version and release numbers and so will change with each release.
After building and installing Release 1, then building Release 2, I am unable to install Release 2.
$ sudo rpm -i /scratch/RPM/RPMS/x86_64/rpmtest-1-2.x86_64.rpm
file /tmp/rpmtest/README from install of rpmtest-1-2.x86_64 conflicts with file from package rpmtest-1-1.x86_64
This time because the README
has changed between releases, rpm reports a conflict.
In contrast to installing, upgrading a package release (rpm -U rpmtest-1-2.x86_64.rpm
) will replace Release 1 with Release 2 even when no files have changed. The upgrade option will also install the rpm if an earlier version/release is not already installed, so if you routinely use the upgrade command instead of the install, you don’t have to be concerned with ending up with multiple package release installations.
In summary, rpm only reports install conflicts if files change, it doesn’t make any comparisons of Version or Release numbers.
This seemed odd to me at first but the flexibility it provides does make sense after I thought about it more. So what if multiple packages own the same file? It happens. One common case is with packages for multiple architectures. Consider the neon library as a random example. I have versions installed for both the i386 and x86_64 architectures. The documentation is the same between the two, only the libneon.so shared objects differ and these are installed in different directories so there’s no conflict.
On the other hand, the observation that a second package installation can change file ownership and permissions of the first package could conceivably be a problem.
Related:
Maximum RPM
Read the rest of this entry »