Build Systems: Making RHEL5 Packages on RHEL6

In my cobbled together build system I’ve never been able to build RHEL 5 (much less RHEL 4) packages on my RHEL 6 host.  I knew this was because RHEL 6 uses newer file digest algorithms and compression algorithms in its version of RPM.  When Mock put together the RHEL 5 build chroot, the version of RPM there could not understand the source package built by the host.

The time came to stop working around this annoyance and fix it.  All one needs to do is define a couple extra defines when one calls RPM to assemble the source package.

--define "_source_filedigest_algorithm md5"
--define "_binary_filedigest_algorithm md5"

My make file simply checks if the dist I’m building for needs the use of these extra defines with the following code.

ifneq (, $(findstring $(DIST), "EL3 EL4 EL5"))
RPMDEFINES := $(RPMDEFINES) \
    --define "_source_filedigest_algorithm md5" \
    --define "_binary_filedigest_algorithm md5"
endif

 

Minor Annoynances

You know what really grinds my gears?  For the last 3 major versions of RHEL, Red Hat has changed how the redhat-release packages work.  So for each version I’ve had to write more code to deduce what version a specific RHEL/CentOS/Fedora machine is.

RHEL 4 has the AS/ES/WS flavors.  RHEL 5 has Client and Server flavors.  So the redhat-release package has a version like 5Client.  Okay extra code to deal with the Client and Server strings.  RHEL 6 (yet to be released) has moved the redhat-release packages to redhat-release-server and redhat-release-workstation.  There is no more Client flag.  So yet more code.  Deducing the version of Fedora has yet to change, however.

You know your packages contain redundant information when:

$ rpm -q --qf '%{epoch}:%{name}-%{version}-%{release}.%{arch}\n' \
   redhat-release-workstation
(none):redhat-release-workstation-5.90Workstation-6.0.0.32.el6.x86_64

Automated Expect Script to Sign RPMs

One of the most “interesting” things to do in a RPM package build system is handle (or NOT handle) automated signing of built packages.  RPM itself does not make this easy.  The key, however, is to redefine the

%__gpg_check_password_cmd

(the command run to validate the password you give RPM during signing) and the

%__gpg_sign_cmd

(the command used to actually sign packages) macros.  After that, you just need to deal with RPM’s usage of getpass(3) to grab the password from the controlling tty.

As much as we love Tcl, the expect tool works the best for this provided you can incant enough RPM macro foo into it.  I’ve written a messy expect script that takes several arguments to automatically sign packages.  The first is the GPG key ID which I normally use an email address in angle brackets.  The second argument is a file name that contains the pass phrase.  The rest of the arguments are the RPM packages to sign.

http://linuxczar.net/code/autosign.exp

Excepting patches.

Found in an RPM .spec

Found in a %pre section of a binary RPM.  Things that are so bad….they get special recognition.

get_package_file()
{
  local tmp_dir=$1
  shift
  rpm_pid=`ps -p $$ -o ppid=`
  rpm_pid=`echo $rpm_pid`      ## trim leading/trailing blanks
  rpm_pathname=`ps -p $rpm_pid -o cmd= | \
                 sed -rn "s:^.+[ ]+([^ ]*EvilPackageName[^ ]+).*$:\1:p"`
  if [ "$rpm_pathname" ]
  then
      if [ -d /proc/$rpm_pid ]
          then
          test -d $tmp_dir || mkdir $tmp_dir
          if [ -d /proc/$rpm_pid/cwd ]
              then
              (cd $tmp_dir
                  (cd /proc/$rpm_pid/cwd; rpm2cpio $rpm_pathname) | \
                      cpio --quiet -id --no-absolute-filenames $1)
              return 0
          fi
      fi
  fi
  return 1
}