Sean’s Obsessions

Sean Walberg’s blog

RPM Is a Good Thing

This article over at Linux.com complains about combing RPM with custom code. I do it all the time, and if done properly, there should be no problems. In this example, I customize the Webalizer package while still maintaining the software under version control.

Webalizer has a feature that counts /index.* as /, since they usually produce the same output. The “index.” part is hardcoded in, though you can add additional names with the IndexAlias configuration directive. However, my RSS feed is index.rdf, and since it begins with index., webalizer counts requests to both http://ertw.com/blog/ and http://ertw.com/blog/index.rdf as one page. With this in force, there is no way for me to determine how many hits I get of people reading my blog vs people pulling it in with an RSS aggregator.

Grepping for “index” in the webalizer source showed me that it’s a single line causing my problem:

1
add_nlist("index.",&index_alias);

Commenting it out and reinstalling is needed, but since I already have it set up as an RPM, I may as well keep it as such. A binary RPM is a collection of files and scripts needed to install a package. With the information in the package, the system can determine if the necessary dependencies are present, and what files are associated with the package for later removal. RPM also differentiates between binaries, documentation, and configuration, so that if you upgrade a package, it will either back up or leave a config file alone, while replacing binaries. An RPM is made from a .spec file, “pristine sources”, and patches. The .spec file contains the instructions for unpacking, patching, configuring, and installing the software. Think of it as a script for building and installing software, ensuring it is done the same way time after time. Pristine sources are simply the tarballs obtained from vendors. Patches are changes to the pristine sources, either local modifications (such as what I’ll do here), or updates from the vendor (like the kernel does) Downloading the .srpm of webalizer from the fedora sources (and note I’m running RH 7.3, even though we’re dealing with RPM, we still have benefits of source code), it is installed with “rpm -i webalizer-2.01_10-14.src.rpm”. This puts all the source and patches in /usr/src/redhat/SOURCES, and the spec file in /usr/src/redhat/SPECS. Just to make sure I can build it, I try to generate a binary RPM of webalizer:

1
rpmbuild -ba webalizer.spec

(Another note here is that this requires db4, where RH7.3 only has db3. In the past I had to upgrade it anyway, by simply rebuilding the db4 rpm from RH9 in the same manner and upgrading. Again, the benefits of source with the benefits of RPM) So, it built fine. What I have to do now is fix the code, create a patch, and then rebuild. With a clean copy of the webalizer source in one directory, I make a copy:

1
2
cp -r webalizer-2.01-10/ webalizer-2.01-10.orig
vi webalizer-2.01-10/webalizer.c

I make my change to webalizer.c (ie commenting out the one line), then create a patch into the SOURCES directory:

1
diff -uNr webalizer-2.01-10.orig/ webalizer-2.01-10 > ../SOURCES/webalizer.indexalias.patch

(Read this for more information on diff and patch) Editing webalizer.spec, I make the following changes:

1
Version: %{ver}_%{patchlevel}Custom

this changes the package name to have “Custom” in the name. Then, tell RPM to apply the patch to the sources and strip off one directory (ie patch -p1)

1
2
3
4
#... by the Patch0 and Patch1 lines
Patch5: webalizer.indexalias.patch
#... by the other %patches
%patch5 -p1

After that, rebuild the rpm:

1
rpmbuild -ba webalizer.spec

Then upgrade the software:

1
rpm -Uvh /usr/src/redhat/RPMS/i386/webalizer-2.01_10Custom-14.i386.rpm

Now, I add

1
2
3
4
IndexAlias      index.htm
IndexAlias      index.php
GroupURL        /blog/index.rdf RSS Feed
HideURL         /blog/index.rdf

to /etc/webalizer.conf, and I’m tracking my RSS statistics separate from my normal page views.

It is well worth your while to make good use of RPM and specfiles. Almost anything I install, I try to build as an RPM. When patches need applying to the code, or when the software upgrades, I copy a couple of files and change some lines in the specfile. Since the specfile is a script, I ensure that the software is built consistently each time.

Comments

I’m trying something new here. Talk to me on Twitter with the button above, please.