-#! /bin/sh -e
-###
-### Fetch native versions of tools for insertion into foreign chroots
-###
-### (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@@@
-
-###--------------------------------------------------------------------------
-### Utilities.
-
-chase_link () {
- p=$1 d=
- ## Copy an absolute path P from the donor tree `$root/' into the
- ## cross-tools tree `$crossnew/'. If resolving P involves traversing a
- ## symbolic link, then ensure that the pieces of filesystem it directs us
- ## to are also copied.
-
- ## Work through the remaining components of the path.
- while :; do
-
- ## Analyse the first remaining component of the path P.
- case $p in
-
- ## It's empty. We're done.
- "") break ;;
-
- ## A redundant `/' or `./'. Skip it.
- "/"*) p=${p#/} ;;
- "./"*) p=${p#./} ;;
-
- ## A `../'. Strip off the trailing component of D.
- "../"*)
- p=${p#../}
- case $d in */*) d=${d%/*} ;; *) d= ;; esac
- ;;
-
- ## Something else. Transfer the component name to D.
- *)
- case $p in */*) f=${p%%/*} p=${p#*/} ;; *) f=$p p="" ;; esac
- d=${d:+$d/}$f
- ;;
- esac
-
- ## If D doesn't refer to a file in the cross-tools tree, then maybe it
- ## refers to something in the donor tree. Find out what, and copy it
- ## into the cross-tools tree.
- if ! [ -e "$crossnew$d" ] && ! [ -L "$crossnew$d" ]; then
- if [ -d "$root/$d" ] && ! [ -L "$root/$d" ]; then
- mkdir "$crossnew$d"
- else
- echo >&2 "$0: copy /$d to satisfy symlinks"
- rsync -aHR $root/./$d $crossnew
- fi
- fi
-
- ## If D refers to a symbolic link, then append the link target to P, so
- ## that we can make sure we copy the target.
- if [ -L "$crossnew$d" ]; then
- t=$(readlink "$crossnew$d")
- case $t in /*) t=${t#/} d= ;; esac
- case $d in */*) d=${d%/*} ;; *) d= ;; esac
- p=$t${p:+/$p}
- fi
- done
-}
-
-###--------------------------------------------------------------------------
-### Main program.
-
-## Parse the command line.
-badp=nil
-case $# in 2) ;; *) badp=t ;; esac
-case $badp in t) echo >&2 "usage: $0 DIST MYARCH"; exit 2 ;; esac
-d=$1 myarch=$2
-
-## Keep track of our original stdout.
-exec 3>&1
-
-## Figure out derived architecture names.
-mymulti=$(dpkg-architecture -a$myarch -qDEB_HOST_MULTIARCH)
-
-## First, set `cross_archs' as a list of GNUish names for our supported
-## foreign architectures.
-cross_archs="arm-linux-gnueabi arm-linux-gnueabihf aarch64-linux-gnu"
-
-## Make a list of extra packages we'll need to install to obtain our tools.
-cross_pkgs="
- apt bash ccache coreutils dash eatmydata fakeroot findutils
- gpgv gzip m4 make mawk qemu-user-static sed tar xz-utils"
-for a in $cross_archs; do
- for i in gcc g++ binutils; do
- cross_pkgs="$cross_pkgs $i-$a"
- done
-done
-cross_pkgs=$(echo $cross_pkgs)
-
-## Make an enormous shopping list of paths.
-##
-## The `wanted' list consists of two kinds of items: an absolute path names a
-## prefix (not necessarily a directory name) to be attached to the following
-## relative names, up to the end of the list or the next absolute path.
-wanted="
- /usr/bin/ apt apt-cache apt-config apt-get apt-key apt-mark
- /usr/lib/apt/ methods/ solvers/
-
- /bin/ cat chgrp chown cp date dd df dir echo false ln ls mkdir
- mknod mktemp mv pwd readlink rm rmdir sleep stty sync touch
- true uname vdir
- /usr/bin/ [ arch b2sum base32 base64 basename chcon cksum comm
- csplit cut dircolors dirname du env expand expr factor fmt
- fold groups head hostid id install join link logname md5sum
- mkfifo nice nl nohup nproc numfmt od paste pathchk pinky pr
- printenv printf ptx realpath runcon seq sha1sum sha224sum
- sha256sum sha384sum sha512sum shred shuf sort split stat
- stdbuf sum tac tail tee test timeout tr truncate tsort tty
- unexpand uniq unlink users wc who whoami yes
- /usr/lib/$mymulti/ coreutils/
-
- /lib/$mymulti/ libnss_*.so.*
-
- /usr/bin/ gpgv
-
- /usr/bin/ qemu-*-static
-
- /bin/ bash dash gzip sed tar
- /usr/bin/ ccache find m4 make mawk xargs xz
- /usr/lib/$mymulti/ libeatmydata.so* libfakeroot/
-
- /etc/ld.so.conf.d/ $mymulti.conf fakeroot*.conf"
-
-for a in $cross_archs; do
- wanted="$wanted
-
- /usr/bin/$a- addr2line ar as c++filt dwp elfedit gprof ld ld.*
- nm objcopy objdump ranlib readelf size strings strip
-
- /usr/bin/$a- cpp gcc g++ gcov gcov-dump gcov-tool gprof
- gcc-ar gcc-nm gcc-ranlib
- /usr/lib/gcc-cross/$a/ ..."
-done
-wanted=$(echo $wanted)
-
-## Figure out how to recognize dynamic executables.
-case $myarch in
- i386) elfsig=7f454c46010101??0000000000000000????0300 ;;
- amd64) elfsig=7f454c46020101??0000000000000000????3e00 ;;
- *) echo >&2 "$0: unsupported local arch \`$myarch'"; exit 2 ;;
-esac
-
-## Open a session to the donor chroot.
-echo >&2 "$0: create $d snapshot"
-sess=$(schroot -bc$LVPREFIX$d-$myarch 3>&-)
-
-## Make sure the donor tree is up-to-date, and install the extra packages we
-## need.
-schroot -uroot -rc$sess -- eatmydata sh -ec "
- apt-get update
- apt-get -y upgrade
- apt-get -y install $cross_pkgs"
-
-## Establish some pathnames. Prepare a place for our cross-tools tree.
-crossdir=$LOCAL/cross/$d-$myarch/
-crossold=${crossdir%/}.old/ crossnew=${crossdir%/}.new/
-root=/schroot/$sess/fs
-rm -rf $crossnew; mkdir -p $crossnew
-
-## Work through the shopping list, copying the things it names into the
-## cross-tools tree.
-dir=/
-for i in $wanted; do
- case $i in
- /*)
- dir=$i
- ;;
- *)
- case $i in ...) f=$dir ;; *) f=$dir$i ;; esac
- echo >&2 "$0: copy $f"
- rsync -aHR $root/.$f $crossnew
- ;;
- esac
-done
-
-## Chase links in the new tree, copying extra stuff that we'll need.
-find $crossnew -xtype l -print | while read i; do
- chase_link ${i#$crossnew}
-done
-
-## Search the new tree for ELF binaries, and build a list of them in
-## `QUEUE.in'.
-find $crossnew -type f -print | while read i; do
- sig=$(head -c20 "$i" | bincode -e -m0 -flowerc hex)
- case $sig in $elfsig) echo "$i" ;; esac
-done >$root/private/QUEUE.in
-
-while [ -s $root/private/QUEUE.in ]; do
- ## Work through the ELF binaries in `QUEUE.in', determining which shared
- ## libraries they'll need. Write the list of dependencies to `QUEUE.out'
- schroot -uroot -rc$sess -- eatmydata sh -ec '
- prog=$1
- while read i; do
- echo >&2 "$prog: scanning binary $i"
- ldd "$i" | while read a b c d; do
- case $a:$b:$c:$d in
- not:a:dynamic:executable) ;;
- statically:linked::) ;;
- /*) echo "$a" ;;
- *:=\>:/*) echo "$c" ;;
- linux-*) ;;
- *) echo >&2 "$i: unable to find $a"; exit 2 ;;
- esac
- done
- done </private/QUEUE.in >/private/QUEUE.out' - "$0"
-
- ## Work through the shared libraries in `QUEUE.out', copying them to the
- ## cross-tools tree if they're not there already. Add the new ones to a
- ## new `QUEUE.in' file to scan them in turn.
- while read i; do
- if [ -e "$crossnew$i" ] || [ -L "$crossnew$i" ]
- then continue; fi
- if [ -d "$root$i" ]; then continue; fi
- echo >&2 "$0: copy $i"
- rsync -aHR $root/.$i $crossnew >&3
- chase_link $i >&3
- sig=$(head -c20 $crossnew$i | bincode -e -m0 -flowerc hex)
- case $sig in $elfsig) echo "$i" ;; esac
- done <$root/private/QUEUE.out >$root/private/QUEUE.in
-done
-
-## Set up the cross-compiler. This is rather hairy.
-echo >&2 "$0: establish TOOLCHAIN"
-for a in $cross_archs; do
- tooldir=$crossnew/TOOLCHAIN/$a
- mkdir -p $tooldir
- for i in $crossnew/usr/bin/$a-*; do
- t=${i#$crossnew/usr/bin/}
- mv $i $tooldir/$t
- ln -s $t $tooldir/${t#$a-}
- done
-done
-mkdir $crossnew/TOOLCHAIN/lib
-ln -s ../../usr/lib/gcc-cross $crossnew/TOOLCHAIN/lib/
-
-## Set up the emulator.
-echo >&2 "$0: establish QEMU"
-mkdir $crossnew/QEMU
-mv $crossnew/usr/bin/qemu-*-static $crossnew/QEMU/
-
-## We're done. Remove the snapshot, and replace the old cross-tools tree
-## with our new one.
-echo >&2 "$0: remove snapshot"
-schroot -ec$sess 3>&-
-if [ -d $crossdir ]; then mv $crossdir $crossold; fi
-mv $crossnew $crossdir; rm -rf $crossold
-echo >&2 "$0: committed $crossdir"
-
-###----- That's all, folkd --------------------------------------------------