Replacing binaries with dpkg-divert
Posted by Steve on Wed 6 Apr 2005 at 19:36
One of the strengths of the Debian system is the way in which it deals with having multiple similar packages installed, and allowing you to choose which one you use.
We already discussed one way in which Debian allows you to choose a specific package from a number of available options in the piece using the Debian alternatices system.
Another possibility is to replace a binary installed from a package with one of your own choosing, Debian allows this via the use of the dpkg-divert command.
The dpkg-divert command allows you to replace a binary installed upon the system, and have this replacement persist even if you upgrade packages.
One common reason to do this is if you're using a mailserver such as qmail, and you wish to replace the file /usr/lib/sendmail with the version from that package. In this case making a diversion is a good solution.
Another example where you might wish to replace a package's binary is in the case of the gcc, or g++, compiler commands.
Assuming that you were keen on rebuilding Debian packages and wished to ensure that some optimizations were applied. Rather than patch the Makefile, or build scripts you could just replace the compiler command to ensure that your options were applied globally.
(This is what the pentium-builder package does, incidently).
To replace a packages binary you have to:
- Rename the file that you're replacing.
- Add the diversion to the system.
Both these steps can be achieved with one command. For example assume we wish to replace the gcc command to cause it to add "-O2" to all compilation jobs we'd run the following command as root:
dpkg-divert --add --rename --divert /usr/bin/gcc.real /usr/bin/gcc
This adds a diversion to the file /usr/bin/gcc, causing that binary to be renamed to /usr/bin/gcc.real.
Now whenever we upgrade the gcc package the system will know that it shouldn't overwrite the gcc binary, instead the new package will have it's binary installed as gcc.real.
Now that we've done that we can create a simple shell script with the name gcc which will add our option, and invoke the real compiler:
#!/bin/sh /usr/bin/gcc.real -O2 $*
This script invokes the real compiler, with all the options we've been passed and the new option "-O2".
If we wish to remove this diversion at a future point in time we can use:
# Remove the script we added rm /usr/bin/gcc # Remove the diversion, renaming /usr/bin/gcc.real back to /usr/bin/gcc dpkg-divert --rename --remove /usr/bin/gcc
You can also list all the diversions which you have currently installed with: