#! /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 gnupg 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/ gpg gpgv gpgconf kbxutil watchgnupg /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.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 --------------------------------------------------