Integrate source code patches into RPM packages

Rcently I packaged the software scponly for Enterprise Linux using rpmbuild and stumbled upon an error message:

 1$ cd ~/rpmbuild/SPECS
 2$ rpmbuild -ba scponly.spec
 3checking for libgiertz...
 4...
 5/usr/bin/install -c -o 0 -g 0 scponly /home/cstan/rpmbuild/BUILDROOT/scponly-4.8-1.el7.centos.x86_64/usr/bin/scponly
 6/usr/bin/install: cannot change ownership of '/home/cstan/rpmbuild/BUILDROOT/scponly-4.8-1.el7.centos.x86_64/usr/bin/scponly': Operation not permitted
 7make: *** [install] Error 1
 8error: Bad exit status from /var/tmp/rpm-tmp.Zx3wsc (%install)
 9
10RPM build errors:
11    Bad exit status from /var/tmp/rpm-tmp.Zx3wsc (%install)

During the "installation" of compiled files within the RPM package changing the file owner fails - but why? Having a look at the Makefile should help. Runtime data of previous compiling processes can be found inside the  BUILD folder:

 1$ cd ../BUILD/scponly-3xxx
 2$ less Makefile.in
 3...
 4        ${INSTALL} -o 0 -g 0 scponly ${DESTDIR}${bindir}/scponly
 5        ${INSTALL} -o 0 -g 0 -m 0644 scponly.8 ${DESTDIR}${mandir}/man8/scponly.8
 6        ${INSTALL} -o 0 -g 0 -m 0644 debuglevel ${DESTDIR}${DEBUGFILE}
 7        if test "x${CHROOTED_NAME}" != "x"; then
 8                ${INSTALL} -d ${DESTDIR}${sbindir};
 9                rm -f ${DESTDIR}${sbindir}/${CHROOTED_NAME};
10                cp scponly ${CHROOTED_NAME};
11                ${INSTALL} -o 0 -g 0 -m 4755 ${CHROOTED_NAME} ${DESTDIR}${sbindir}/${CHROOTED_NAME};

When having a look at the Makefile I discovered the install parameters -o and -g. They are used to set a particular user or group - 0 represents the root user or group in this case. Defining root as user or group during the RPM package creation is unnecessary as it is the default anyway.

When manually compiling the software I figured out that the process finishes if the parameters mentioned above are removed. So - the software source code needs to be patched in order to build the RPM package without any issues.

First of all, a copy of the appropriate folder needs to be created - ensure that you are in the BUILD folder:

1$ cd ..
2$ mkdir scponly-3xxx-revised
3$ cp -R scponly-3xxx scponly-3xxx-revised

Aferwards the affected file - Makefile in this scenario - is edited:

 1$ vi scponly-3xxx-revised/Makefile.in
 2...
 3        ${INSTALL} scponly ${DESTDIR}${bindir}/scponly
 4        ${INSTALL} -m 0644 scponly.8 ${DESTDIR}${mandir}/man8/scponly.8
 5        ${INSTALL} -m 0644 debuglevel ${DESTDIR}${DEBUGFILE}
 6        if test "x${CHROOTED_NAME}" != "x"; then                        
 7                ${INSTALL} -d ${DESTDIR}${sbindir};                             
 8                rm -f ${DESTDIR}${sbindir}/${CHROOTED_NAME};                    
 9                cp scponly ${CHROOTED_NAME};                            
10                ${INSTALL} -m 4755 ${CHROOTED_NAME} ${DESTDIR}${sbindir}/${CHROOTED_NAME};
11ESC ZZ

Afterwards the two directories are compared using diff - changes are documented in a patch file. It is a good idea to store this file in the SOURCES folder where also the software source code is stored. This is essential to enable referencing the patch within the RPM spec file!

1$ diff -urN scponly-3xxx scponly-3xxx-revised > ../SOURCES/scponly-3xxx-makefile.patch

In the RPM Spec file a Patch line including the patch file name is added right after the Source line. In the %prep section, a new line for patching the source code is added right after the %setup line: %patch0 -p1.

Of course it is also possible to reference multiple patches - the lines contain a continuous number. In this scenario the first patch was referenced - as a result, the keywords are Patch0 and %patch0:

 1$ cd ../SPECS
 2$ vi scponly.spec
 3...
 4Source0:        https://github.com/scponly/scponly/archive/3xxx.zip
 5Patch0:         scponly-3xxx-makefile.patch
 6...
 7%prep
 8%setup -q -n scponly-3xxx
 9%patch0 -p1
10...
11
12ESC ZZ

Afterwards, the RPM package creation succeeded:

1$ rpmbuild -ba scponly.spec
2...
3Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.jchHSk
4+ umask 022
5+ cd /home/cstan/rpmbuild/BUILD
6+ cd scponly-3xxx
7+ /usr/bin/rm -rf /home/cstan/rpmbuild/BUILDROOT/scponly-4.8-1.el7.centos.x86_64
8+ exit 0

If you have a look inside the RPM package (e.g. using cpio or Midnight Commander), you will see, that the files belong to root. So there is no interference after applying the patch:

1-rw-r--r-- 1 root    root                        2 Jun 30 18:22 /etc/scponly/debuglevel
2-rwxr-xr-x    1 root    root                    24720 Jun 30 18:22 /usr/bin/scponly
3-rwxr-xr-x    1 root    root                    24720 Jun 30 18:22 /usr/sbin/scponlyc
4-rw-r--r-- 1 root    root                     2534 Jun 30 18:22 /usr/share/man/man8/scponly.8.gz

Feel free to use my RPM spec file and the patch for reproducing the issue.

Translations: