| 1 | #! /bin/sh -e |
| 2 | |
| 3 | badp=nil |
| 4 | myarch=$(dpkg-architecture -qDEB_HOST_ARCH) |
| 5 | while getopts "a:" opt; do |
| 6 | case $opt in |
| 7 | a) myarch=$OPTARG ;; |
| 8 | *) badp=t ;; |
| 9 | esac |
| 10 | done |
| 11 | shift $(( $OPTIND - 1 )) |
| 12 | case $# in 0) badp=t ;; esac |
| 13 | case $badp in |
| 14 | t) |
| 15 | cat >&2 <<EOF |
| 16 | usage: $0 [-a MYARCH] DIST ... |
| 17 | EOF |
| 18 | exit 1 |
| 19 | ;; |
| 20 | esac |
| 21 | for arg in "$@"; do |
| 22 | case $arg in *-*) echo >&2 "$0: bad arch name \`$arg'"; exit 1 ;; esac |
| 23 | done |
| 24 | mymulti=$(dpkg-architecture -a$myarch -qDEB_HOST_MULTIARCH) |
| 25 | |
| 26 | cross_archs="arm-linux-gnueabi arm-linux-gnueabihf aarch64-linux-gnu" |
| 27 | cross_pkgs=" |
| 28 | apt bash ccache coreutils dash eatmydata fakeroot findutils |
| 29 | gnupg gpgv gzip m4 make mawk qemu-user-static sed tar xz-utils" |
| 30 | for a in $cross_archs; do |
| 31 | for i in gcc g++ binutils; do |
| 32 | cross_pkgs="$cross_pkgs $i-$a" |
| 33 | done |
| 34 | done |
| 35 | cross_pkgs=$(echo $cross_pkgs) |
| 36 | |
| 37 | wanted=" |
| 38 | /usr/bin/ apt apt-cache apt-config apt-get apt-key apt-mark |
| 39 | /usr/lib/apt/ methods/ solvers/ |
| 40 | |
| 41 | /bin/ cat chgrp chown cp date dd df dir echo false ln ls mkdir |
| 42 | mknod mktemp mv pwd readlink rm rmdir sleep stty sync touch |
| 43 | true uname vdir |
| 44 | /usr/bin/ [ arch b2sum base32 base64 basename chcon cksum comm |
| 45 | csplit cut dircolors dirname du env expand expr factor fmt |
| 46 | fold groups head hostid id install join link logname md5sum |
| 47 | mkfifo nice nl nohup nproc numfmt od paste pathchk pinky pr |
| 48 | printenv printf ptx realpath runcon seq sha1sum sha224sum |
| 49 | sha256sum sha384sum sha512sum shred shuf sort split stat |
| 50 | stdbuf sum tac tail tee test timeout tr truncate tsort tty |
| 51 | unexpand uniq unlink users wc who whoami yes |
| 52 | /usr/lib/$mymulti/ coreutils/ |
| 53 | |
| 54 | /lib/$mymulti/ libnss_*.so.* |
| 55 | |
| 56 | /usr/bin/ gpg gpgv gpgconf kbxutil watchgnupg |
| 57 | |
| 58 | /usr/bin/ qemu-*-static |
| 59 | |
| 60 | /bin/ bash dash gzip sed tar |
| 61 | /usr/bin/ ccache find m4 make mawk xargs xz |
| 62 | /usr/lib/$mymulti/ libeatmydata.so* libfakeroot/ |
| 63 | |
| 64 | /etc/ld.so.conf.d/ $mymulti.conf fakeroot*.conf" |
| 65 | |
| 66 | for a in $cross_archs; do |
| 67 | wanted="$wanted |
| 68 | |
| 69 | /usr/bin/$a- addr2line ar as c++filt dwp elfedit gprof ld ld.* |
| 70 | nm objcopy objdump ranlib readelf size strings strip |
| 71 | |
| 72 | /usr/bin/$a- cpp gcc g++ gcov gcov-dump gcov-tool gprof |
| 73 | gcc-ar gcc-nm gcc-ranlib |
| 74 | /usr/lib/gcc-cross/$a/ ..." |
| 75 | done |
| 76 | wanted=$(echo $wanted) |
| 77 | |
| 78 | case $myarch in |
| 79 | i386) elfsig=7f454c46010101??0000000000000000????0300 ;; |
| 80 | amd64) elfsig=7f454c46020101??0000000000000000????3e00 ;; |
| 81 | *) echo >&2 "$0: unsupported local arch \`$myarch'"; exit 1 ;; |
| 82 | esac |
| 83 | |
| 84 | chase_link () { |
| 85 | p=$1 d= |
| 86 | while :; do |
| 87 | case $p in |
| 88 | "") break ;; |
| 89 | "/"*) p=${p#/} ;; |
| 90 | "./"*) p=${p#./} ;; |
| 91 | "../"*) |
| 92 | p=${p#../} |
| 93 | case $d in */*) d=${d%/*} ;; *) d= ;; esac |
| 94 | ;; |
| 95 | *) |
| 96 | case $p in */*) f=${p%%/*} p=${p#*/} ;; *) f=$p p="" ;; esac |
| 97 | d=${d:+$d/}$f |
| 98 | ;; |
| 99 | esac |
| 100 | if ! [ -e "$crossnew$d" ] && ! [ -L "$crossnew$d" ]; then |
| 101 | if [ -d "$root/$d" ] && ! [ -L "$root/$d" ]; then |
| 102 | mkdir "$crossnew$d" |
| 103 | else |
| 104 | echo >&2 "$0: copy /$d to satisfy symlinks" |
| 105 | rsync -aHR $root/./$d $crossnew |
| 106 | fi |
| 107 | fi |
| 108 | if [ -L "$crossnew$d" ]; then |
| 109 | t=$(readlink "$crossnew$d") |
| 110 | case $t in /*) t=${t#/} d= ;; esac |
| 111 | case $d in */*) d=${d%/*} ;; *) d= ;; esac |
| 112 | p=$t${p:+/$p} |
| 113 | fi |
| 114 | done |
| 115 | } |
| 116 | |
| 117 | exec 3>&1 |
| 118 | for d in "$@"; do |
| 119 | echo >&2 "$0: create $d snapshot" |
| 120 | sess=$(schroot -bc$d-$myarch 3>&-) |
| 121 | schroot -uroot -rc$sess -- eatmydata sh -ec " |
| 122 | apt-get update |
| 123 | apt-get -y upgrade |
| 124 | apt-get -y install $cross_pkgs" |
| 125 | crossdir=/usr/local.schroot/cross/$d-$myarch/ |
| 126 | crossold=${crossdir%/}.old/ crossnew=${crossdir%/}.new/ |
| 127 | rm -rf $crossnew; mkdir -p $crossnew |
| 128 | |
| 129 | root=/schroot/$sess/fs; dir=/ |
| 130 | for i in $wanted; do |
| 131 | case $i in |
| 132 | /*) |
| 133 | dir=$i |
| 134 | ;; |
| 135 | *) |
| 136 | case $i in ...) f=$dir ;; *) f=$dir$i ;; esac |
| 137 | echo >&2 "$0: copy $f" |
| 138 | rsync -aHR $root/.$f $crossnew |
| 139 | ;; |
| 140 | esac |
| 141 | done |
| 142 | |
| 143 | find $crossnew -xtype l -print | while read i; do |
| 144 | chase_link ${i#$crossnew} |
| 145 | done |
| 146 | |
| 147 | find $crossnew -type f -print | while read i; do |
| 148 | sig=$(head -c20 "$i" | bincode -e -m0 -flowerc hex) |
| 149 | case $sig in $elfsig) echo "$i" ;; esac |
| 150 | done >$root/private/QUEUE.in |
| 151 | |
| 152 | counter=0 |
| 153 | cp $root/private/QUEUE.in /tmp/mdw/queue.in.$counter |
| 154 | |
| 155 | while [ -s $root/private/QUEUE.in ]; do |
| 156 | schroot -uroot -rc$sess -- eatmydata sh -ec ' |
| 157 | prog=$1 |
| 158 | while read i; do |
| 159 | echo >&2 "$prog: scanning binary $i" |
| 160 | ldd "$i" | while read a b c d; do |
| 161 | case $a:$b:$c:$d in |
| 162 | not:a:dynamic:executable) ;; |
| 163 | statically:linked::) ;; |
| 164 | /*) echo "$a" ;; |
| 165 | *:=\>:/*) echo "$c" ;; |
| 166 | linux-*) ;; |
| 167 | *) echo >&2 "$i: unable to find $a"; exit 2 ;; |
| 168 | esac |
| 169 | done |
| 170 | done </private/QUEUE.in >/private/QUEUE.out' - "$0" |
| 171 | |
| 172 | cp $root/private/QUEUE.out /tmp/mdw/queue.out.$counter |
| 173 | counter=$(( $counter + 1 )) |
| 174 | |
| 175 | while read i; do |
| 176 | if [ -e "$crossnew$i" ] || [ -L "$crossnew$i" ] |
| 177 | then continue; fi |
| 178 | if [ -d "$root$i" ]; then continue; fi |
| 179 | echo >&2 "$0: copy $i" |
| 180 | rsync -aHR $root/.$i $crossnew >&3 |
| 181 | chase_link $i >&3 |
| 182 | sig=$(head -c20 $crossnew$i | bincode -e -m0 -flowerc hex) |
| 183 | case $sig in $elfsig) echo "$i" ;; esac |
| 184 | done <$root/private/QUEUE.out >$root/private/QUEUE.in |
| 185 | |
| 186 | cp $root/private/QUEUE.in /tmp/mdw/queue.in.$counter |
| 187 | |
| 188 | done |
| 189 | |
| 190 | echo >&2 "$0: establish TOOLCHAIN" |
| 191 | for a in $cross_archs; do |
| 192 | tooldir=$crossnew/TOOLCHAIN/$a |
| 193 | mkdir -p $tooldir |
| 194 | for i in $crossnew/usr/bin/$a-*; do |
| 195 | t=${i#$crossnew/usr/bin/} |
| 196 | mv $i $tooldir/$t |
| 197 | ln -s $t $tooldir/${t#$a-} |
| 198 | done |
| 199 | done |
| 200 | mkdir $crossnew/TOOLCHAIN/lib |
| 201 | ln -s ../../usr/lib/gcc-cross $crossnew/TOOLCHAIN/lib/ |
| 202 | |
| 203 | echo >&2 "$0: establish QEMU" |
| 204 | mkdir $crossnew/QEMU |
| 205 | mv $crossnew/usr/bin/qemu-*-static $crossnew/QEMU/ |
| 206 | |
| 207 | echo >&2 "$0: remove snapshot" |
| 208 | schroot -ec$sess 3>&- |
| 209 | if [ -d $crossdir ]; then mv $crossdir $crossold; fi |
| 210 | mv $crossnew $crossdir; rm -rf $crossold |
| 211 | echo >&2 "$0: committed $crossdir" |
| 212 | done |