#! /bin/sh -e ### ### Replace common tools in foreign chroots with native versions ### ### (c) 2018 Mark Wooding ### ###----- Licensing notice --------------------------------------------------- ### ### This file is part of the distorted.org.uk chroot maintenance tools. ### ### distorted-chroot is free software: you can redistribute it and/or ### modify it under the terms of the GNU General Public License as ### published by the Free Software Foundation; either version 2 of the ### License, or (at your option) any later version. ### ### distorted-chroot is distributed in the hope that it will be useful, ### but WITHOUT ANY WARRANTY; without even the implied warranty of ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ### General Public License for more details. ### ### You should have received a copy of the GNU General Public License ### along with distorted-chroot. If not, write to the Free Software ### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ### USA. . state/config.sh # @@@config@@@ ## Parse the command-line. badp=nil case $# in 2) ;; *) badp=t ;; esac case $badp in t) echo >&2 "usage: $0 DIST ARCH"; exit 2 ;; esac d=$1 a=$2 ## Figure out of all the architecture names. mymulti=$(dpkg-architecture -a$TOOLSARCH -qDEB_HOST_MULTIARCH) gnuarch=$(dpkg-architecture -A$a -qDEB_TARGET_GNU_TYPE) qarch=nil qhost=nil for fa in $FOREIGN_ARCHS; do case $fa in "$a") eval qarch=\$${a}_QEMUARCH qhost=\$${a}_QEMUHOST break ;; esac done case $qarch,$qhost in nil,* | *,nil) echo >&2 "$0: not a foreign architecture"; exit 2 ;; esac ## Make sure we have the tools we need. crossdir=/usr/local.schroot/cross/$d-$TOOLSARCH my_crossdir=$LOCAL/${crossdir#/usr/local.schroot/} qemudir=/usr/local.schroot/cross/$d-$qhost/QEMU my_qemudir=$LOCAL/${qemudir#/usr/local.schroot/} if ! [ -d $my_crossdir ]; then echo 2>&1 "$0: no tree for \`$d-$TOOLSARCH'"; exit 2 fi if ! [ -d $my_qemudir ]; then echo 2>&1 "$0: no tree for \`$d-$qhost'"; exit 2 fi ## Open a session to the target chroot. sess=$(schroot -bcsource:$LVPREFIX$d-$a) root=/schroot/$sess/fs ## Abuse `/mnt/' as a temporary staging area. This saves us from clobbering ## the chroot with weird directories. schroot -uroot -rc$sess -- sh -ec ' if ! mountpoint -q /mnt; then mount -ttmpfs -omode=700,uid=0,gid=0 private /mnt fi' ## Work through all of the tools we're interested in, to decide what we need ## to do with it. Make lists: ## ## * `DIVERT.want' lists all of the filenames which need dpkg diversions to ## prevent foreign versions of the tools from clobbering our native ## versions. ## ## * `LINK'.want' lists all of the paths which need symbolic links into the ## cross-tools trees, together with the link destinations. { echo $qemudir/qemu-$qarch-static echo $crossdir/lib/$mymulti echo $crossdir/usr/lib/$mymulti echo $crossdir/usr/lib/gcc-cross find $my_crossdir $my_crossdir/TOOLCHAIN/$gnuarch \ \( \( -path "*/QEMU" -o -path "*/TOOLCHAIN" -o \ -path "*/lib/$mymulti" -o \ -path "*/lib/gcc-cross" \) -prune \) -o \ \( ! -type d -print \) } | sed "s^$LOCAL//usr/local.schroot/" | while read t; do case $t in $qemudir/*) s=/usr/bin/${t#$qemudir/} ;; $crossdir/TOOLCHAIN/$gnuarch/*) s=/usr/bin/${t#$crossdir/TOOLCHAIN/$gnuarch/} ;; *) s=${t#$crossdir} ;; esac if [ -L $t ]; then t=$(readlink $t); fi if [ -d $t ]; then act=LINK; else act=DIVERT; fi echo $act $s $t done >$root/mnt/ALL.want sed -n '/^DIVERT \(.*\) .*$/s//\1/p' $root/mnt/ALL.want | \ sort >$root/mnt/DIVERT.want sed -n '/^\(DIVERT\|LINK\) /s///p' $root/mnt/ALL.want | \ sort >$root/mnt/LINK.want ## Make a list, `DIVERT.have', of paths which already have diversions, and a ## list `LINK.have' of symbolic links into the cross-tools trees. The ## layouts of these files match the `.want' files we just made. schroot -uroot -rc$sess -- sh -ec ' dpkg-divert --list | sed -n "/^diversion of \(.*\) to .* by install-cross-tools\$/s//\1/p" | \ sort >/mnt/DIVERT.have { find / -xdev -lname "/usr/local.schroot/cross/*" -printf "%p %l\n" while read s _; do if ! [ -L "$s" ]; then continue; fi t=$(readlink $s) case $t in /usr/local.schroot/cross/*) continue ;; esac echo "$s $t" done /mnt/LINK.have' ## Add diversions for the paths which need one, but don't have one. There's ## a hack here because the `--no-rename' option was required in the same ## version in which is was introduced, so there's no single incantation that ## will work across the boundary. schroot -uroot -rc$sess -- sh -ec ' a=$1 if dpkg-divert >/dev/null 2>&1 --no-rename --help then no_rename=--no-rename else no_rename= fi comm -13 /mnt/DIVERT.have /mnt/DIVERT.want | while read i; do dpkg-divert --package "install-cross-tools" $no_rename \ --divert "$i.$a" --add "$i" done' - $a ## Go through each diverted tool, and, if it hasn't been moved aside, then ## /link/ it across now. If we rename it, then the chroot will stop working ## -- which is why we didn't allow `dpkg-divert' to do the rename. We can ## tell a tool that hasn't been moved, because it's a symlink into one of the ## cross trees. while read i; do if [ -e $root$i ] && ! [ -e $root$i.$a ]; then if [ -L $root$i ]; then t=$(readlink $root$i) case $t in $crossdir/* | $qemudir/* | /usr/local.schroot/qemu/*) continue ;; esac if [ -L $crossdir$i ]; then u=$(readlink $crossdir$i) case $t in "$u") continue ;; esac fi fi echo >&2 "$0: preserve old $i" ln $root$i $root$i.$a fi done <$root/mnt/DIVERT.want ## Update all of the symbolic links which are currently wrong: add links ## which are missing, delete ones which are obsolete, and update ones which ## have the wrong target. join -j1 -a1 -a2 -e- -o"0 1.2 2.2" \ $root/mnt/LINK.have $root/mnt/LINK.want | while read s t0 t1; do case $t1 in "$t0") continue ;; -) echo >&2 "$0: remove obsolete link $s -> $t0" rm -f $root$s ;; *) case $s in */*) mkdir -p $root${s%/*} ;; esac rm -f $root$s.new ln -s $t1 $root$s.new echo >&2 "$0: link $s -> $t1" mv -T $root$s.new $root$s ;; esac done ## Remove diversions from paths which don't need them any more. Here it's ## safe to rename, because either the tool isn't there, in which case it ## obviously wasn't important, or it is, and `dpkg-divert' will atomically ## replace our link with the foreign version. schroot -uroot -rc$sess -- sh -ec ' a=$1 comm -23 /mnt/DIVERT.have /mnt/DIVERT.want | while read i; do dpkg-divert --package "install-cross-tools" --rename \ --divert "$i.$a" --remove "$i" done' - $a ## Close the session. schroot -ec$sess ###----- That's all, folks --------------------------------------------------