Commit | Line | Data |
---|---|---|
3e5b03e2 MW |
1 | #! /bin/sh -e |
2 | ### | |
3 | ### Replace common tools in foreign chroots with native versions | |
4 | ### | |
5 | ### (c) 2018 Mark Wooding | |
6 | ### | |
7 | ||
8 | ###----- Licensing notice --------------------------------------------------- | |
9 | ### | |
10 | ### This file is part of the distorted.org.uk chroot maintenance tools. | |
11 | ### | |
12 | ### distorted-chroot is free software: you can redistribute it and/or | |
13 | ### modify it under the terms of the GNU General Public License as | |
14 | ### published by the Free Software Foundation; either version 2 of the | |
15 | ### License, or (at your option) any later version. | |
16 | ### | |
17 | ### distorted-chroot is distributed in the hope that it will be useful, | |
18 | ### but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | ### General Public License for more details. | |
21 | ### | |
22 | ### You should have received a copy of the GNU General Public License | |
23 | ### along with distorted-chroot. If not, write to the Free Software | |
24 | ### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
25 | ### USA. | |
26 | ||
27 | . state/config.sh # @@@config@@@ | |
28 | ||
29 | ## Parse the command-line. | |
30 | badp=nil | |
31 | case $# in 2) ;; *) badp=t ;; esac | |
32 | case $badp in t) echo >&2 "usage: $0 DIST ARCH"; exit 2 ;; esac | |
33 | d=$1 a=$2 | |
34 | ||
35 | ## Figure out of all the architecture names. | |
36 | mymulti=$(dpkg-architecture -a$TOOLSARCH -qDEB_HOST_MULTIARCH) | |
37 | gnuarch=$(dpkg-architecture -A$a -qDEB_TARGET_GNU_TYPE) | |
38 | qarch=nil qhost=nil | |
39 | for fa in $FOREIGN_ARCHS; do | |
40 | case $fa in | |
41 | "$a") | |
42 | eval qarch=\$${a}_QEMUARCH qhost=\$${a}_QEMUHOST | |
43 | break ;; | |
44 | esac | |
45 | done | |
46 | case $qarch,$qhost in | |
47 | nil,* | *,nil) echo >&2 "$0: not a foreign architecture"; exit 2 ;; | |
48 | esac | |
49 | ||
50 | ## Make sure we have the tools we need. | |
51 | crossdir=/usr/local.schroot/cross/$d-$TOOLSARCH | |
52 | my_crossdir=$LOCAL/${crossdir#/usr/local.schroot/} | |
53 | qemudir=/usr/local.schroot/cross/$d-$qhost/QEMU | |
54 | my_qemudir=$LOCAL/${qemudir#/usr/local.schroot/} | |
55 | if ! [ -d $my_crossdir ]; then | |
56 | echo 2>&1 "$0: no tree for \`$d-$TOOLSARCH'"; exit 2 | |
57 | fi | |
58 | if ! [ -d $my_qemudir ]; then | |
59 | echo 2>&1 "$0: no tree for \`$d-$qhost'"; exit 2 | |
60 | fi | |
61 | ||
62 | ## Open a session to the target chroot. | |
63 | sess=$(schroot -bcsource:$LVPREFIX$d-$a) | |
64 | root=/schroot/$sess/fs | |
65 | ||
66 | ## Abuse `/mnt/' as a temporary staging area. This saves us from clobbering | |
67 | ## the chroot with weird directories. | |
68 | schroot -uroot -rc$sess -- sh -ec ' | |
69 | if ! mountpoint -q /mnt; then | |
70 | mount -ttmpfs -omode=700,uid=0,gid=0 private /mnt | |
71 | fi' | |
72 | ||
73 | ## Work through all of the tools we're interested in, to decide what we need | |
74 | ## to do with it. Make lists: | |
75 | ## | |
76 | ## * `DIVERT.want' lists all of the filenames which need dpkg diversions to | |
77 | ## prevent foreign versions of the tools from clobbering our native | |
78 | ## versions. | |
79 | ## | |
80 | ## * `LINK'.want' lists all of the paths which need symbolic links into the | |
81 | ## cross-tools trees, together with the link destinations. | |
82 | { echo $qemudir/qemu-$qarch-static | |
83 | echo $crossdir/lib/$mymulti | |
84 | echo $crossdir/usr/lib/$mymulti | |
85 | echo $crossdir/usr/lib/gcc-cross | |
86 | find $my_crossdir $my_crossdir/TOOLCHAIN/$gnuarch \ | |
87 | \( \( -path "*/QEMU" -o -path "*/TOOLCHAIN" -o \ | |
88 | -path "*/lib/$mymulti" -o \ | |
89 | -path "*/lib/gcc-cross" \) -prune \) -o \ | |
90 | \( ! -type d -print \) | |
91 | } | sed "s\a^$LOCAL/\a/usr/local.schroot/\a" | while read t; do | |
92 | case $t in | |
93 | $qemudir/*) | |
94 | s=/usr/bin/${t#$qemudir/} ;; | |
95 | $crossdir/TOOLCHAIN/$gnuarch/*) | |
96 | s=/usr/bin/${t#$crossdir/TOOLCHAIN/$gnuarch/} ;; | |
97 | *) | |
98 | s=${t#$crossdir} ;; | |
99 | esac | |
100 | if [ -L $t ]; then t=$(readlink $t); fi | |
101 | if [ -d $t ]; then act=LINK; else act=DIVERT; fi | |
102 | echo $act $s $t | |
103 | done >$root/mnt/ALL.want | |
104 | sed -n '/^DIVERT \(.*\) .*$/s//\1/p' $root/mnt/ALL.want | \ | |
105 | sort >$root/mnt/DIVERT.want | |
106 | sed -n '/^\(DIVERT\|LINK\) /s///p' $root/mnt/ALL.want | \ | |
107 | sort >$root/mnt/LINK.want | |
108 | ||
109 | ## Make a list, `DIVERT.have', of paths which already have diversions, and a | |
110 | ## list `LINK.have' of symbolic links into the cross-tools trees. The | |
111 | ## layouts of these files match the `.want' files we just made. | |
112 | schroot -uroot -rc$sess -- sh -ec ' | |
113 | dpkg-divert --list | | |
114 | sed -n "/^diversion of \(.*\) to .* by install-cross-tools\$/s//\1/p" | \ | |
115 | sort >/mnt/DIVERT.have | |
116 | { find / -xdev -lname "/usr/local.schroot/cross/*" -printf "%p %l\n" | |
117 | while read s _; do | |
118 | if ! [ -L "$s" ]; then continue; fi | |
119 | t=$(readlink $s) | |
120 | case $t in /usr/local.schroot/cross/*) continue ;; esac | |
121 | echo "$s $t" | |
122 | done </mnt/LINK.want | |
123 | } | sort >/mnt/LINK.have' | |
124 | ||
125 | ## Add diversions for the paths which need one, but don't have one. There's | |
126 | ## a hack here because the `--no-rename' option was required in the same | |
127 | ## version in which is was introduced, so there's no single incantation that | |
128 | ## will work across the boundary. | |
129 | schroot -uroot -rc$sess -- sh -ec ' | |
130 | a=$1 | |
131 | ||
132 | if dpkg-divert >/dev/null 2>&1 --no-rename --help | |
133 | then no_rename=--no-rename | |
134 | else no_rename= | |
135 | fi | |
136 | ||
137 | comm -13 /mnt/DIVERT.have /mnt/DIVERT.want | while read i; do | |
138 | dpkg-divert --package "install-cross-tools" $no_rename \ | |
139 | --divert "$i.$a" --add "$i" | |
140 | done' - $a | |
141 | ||
142 | ## Go through each diverted tool, and, if it hasn't been moved aside, then | |
143 | ## /link/ it across now. If we rename it, then the chroot will stop working | |
144 | ## -- which is why we didn't allow `dpkg-divert' to do the rename. We can | |
145 | ## tell a tool that hasn't been moved, because it's a symlink into one of the | |
146 | ## cross trees. | |
147 | while read i; do | |
148 | if [ -e $root$i ] && ! [ -e $root$i.$a ]; then | |
149 | if [ -L $root$i ]; then | |
150 | t=$(readlink $root$i) | |
151 | case $t in | |
152 | $crossdir/* | $qemudir/* | /usr/local.schroot/qemu/*) continue ;; | |
153 | esac | |
154 | if [ -L $crossdir$i ]; then | |
155 | u=$(readlink $crossdir$i) | |
156 | case $t in "$u") continue ;; esac | |
157 | fi | |
158 | fi | |
159 | echo >&2 "$0: preserve old $i" | |
160 | ln $root$i $root$i.$a | |
161 | fi | |
162 | done <$root/mnt/DIVERT.want | |
163 | ||
164 | ## Update all of the symbolic links which are currently wrong: add links | |
165 | ## which are missing, delete ones which are obsolete, and update ones which | |
166 | ## have the wrong target. | |
167 | join -j1 -a1 -a2 -e- -o"0 1.2 2.2" \ | |
168 | $root/mnt/LINK.have $root/mnt/LINK.want | | |
169 | while read s t0 t1; do | |
170 | case $t1 in | |
171 | "$t0") | |
172 | continue | |
173 | ;; | |
174 | -) | |
175 | echo >&2 "$0: remove obsolete link $s -> $t0" | |
176 | rm -f $root$s | |
177 | ;; | |
178 | *) | |
179 | case $s in */*) mkdir -p $root${s%/*} ;; esac | |
180 | rm -f $root$s.new | |
181 | ln -s $t1 $root$s.new | |
182 | echo >&2 "$0: link $s -> $t1" | |
183 | mv -T $root$s.new $root$s | |
184 | ;; | |
185 | esac | |
186 | done | |
187 | ||
188 | ## Remove diversions from paths which don't need them any more. Here it's | |
189 | ## safe to rename, because either the tool isn't there, in which case it | |
190 | ## obviously wasn't important, or it is, and `dpkg-divert' will atomically | |
191 | ## replace our link with the foreign version. | |
192 | schroot -uroot -rc$sess -- sh -ec ' | |
193 | a=$1 | |
194 | comm -23 /mnt/DIVERT.have /mnt/DIVERT.want | while read i; do | |
195 | dpkg-divert --package "install-cross-tools" --rename \ | |
196 | --divert "$i.$a" --remove "$i" | |
197 | done' - $a | |
198 | ||
199 | ## Close the session. | |
200 | schroot -ec$sess | |
201 | ||
202 | ###----- That's all, folks -------------------------------------------------- |