[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

dpkg diverts

(For the benefit of Holger and the list, this is the log from a
discussion I had today with Wookey about issues arising from multistrap
creating cross-building chroots and foreign architecture root
filesystems where debootstrap simply cannot cope.)


dpkg-divert enforces a double stage installation of the base system
first so that the files exist to be diverted beforehand. This is
implemented in the maintainer scripts which means foreign chroots
cannot support dpkg-divert.

In native environments, dpkg --unpack is called which intersperses the
unpacking of the diverted package with execution of the maintainer
script to move the diverted files aside, then unpacks the diverting

A foreign environment means that dpkg --unpack is impossible, therefore
in multistrap, dpkg -X is used. Unpacking first and then configure
natively (after first boot for foreign).

Extracting a package being diverted and the diverting package at the
same time causes a race condition. Currently packages are sorted
alphabetically but could be in directory order or modification time
order or random.

Conceptually, a diverting package actually pre-depends on the package
being diverted. In practice, dpkg-divert does not fail (so this issue
does not generate bug reports) and diverting packages depend on the
packages being diverted and therefore can expect the current Debian
dual-stage install to ensure that the package being diverted already
exists on the filesystem. (i.e. debootstrap puts the Priority: required
packages in first and then adds packages that may use diverts.)

Without a declarative list, multistrap cannot determine which packages
use diverts (the maintainer scripts may call dpkg-divert explicitly or
may use variables and sub routines, can use shell or perl to call
dpkg-divert - it becomes impossible to parse). (I'm hoping that
piuparts may have the logs to indicate exactly which packages use
dpkg-divert and how, across the entire archive.)

For foreign chroot support, we need to remove the interleaving
requirement whereby binutils must be unpacked, then the
binutils-multiarch preinst executed (to move the diverted files aside),
then binutils-multiarch unpacked.

# dpkg -X binutils /
# dpkg-deb -e binutils-multiarch_foo_arch.deb /tmp
# /tmp/path/binutils-multiarch.preinst install
(files in binutils package are diverted using perl)
# dpkg -X binutils-multiarch

In reality, NONE of the diverted files are actually used because
dpkg-divert renames them and in order for any package to use the
$file.single or $file.diverted, that package must already depend on the
diverting package. i.e. packages don't call /usr/bin/objcopy.single -
packages work with /usr/bin/objcopy whether that is the binutils
version or the binutils-multiarch version.

Therefore, when a divert is used, the actual diversion is pointless as
the thing being diverted might just as well be removed/replaced. Hence a
Conflicts: Replaces: Provides: mechanism would seem more appropriate -
why is this not done?

Fixes for now:

Need a declarative list of dpkg-diverts including the name of the binary
package DIVERTED and the package calling dpkg-divert.

Enhance multistrap error handling to declare a conflict if both the
diverting and the diverted packages are requested.

New binutils equiv package just for /usr/bin/as

multistrap too ignore the package being diverted and only install the
diverting package.

fix dh_strip - alternative to installing binutils-multiarch

after squeeze: (NY)!

Seek removal of dpkg-diverts and replacements with Pre-Depends|
alternative depends|virtual package corner cases and other unexpected
situations where this won't work.

Attached is a real log from the experimental multiarch setup which
shows the issue - a normal package build fails because objcopy does not
exist, despite binutils and binutils-multiarch appearing to be properly
installed. The diversion has happened but because the diversion took
place AFTER both packages were unpacked, diverting the files actually
means that the original file has disappeared completely and which file
you get is essentially random.

# objcopy
bash: objcopy: command not found

Reinstalling both binutils and binutils-multiarch fixes the problem -
as long as either both are specified in the same command or binutils is
re-installed first.

What have I missed? (quite a lot probably!)


Neil Williams

Attachment: dpkg-divert.log.gz
Description: Binary data

Attachment: pgpWOYwezHQ2I.pgp
Description: PGP signature

Reply to: