|
1 |
############################################################### smallutils |
|
|
2 |
|
3 |
smallyes() { |
4 |
YES="${1-y}" |
5 |
while echo "$YES" 2>/dev/null ; do : ; done |
6 |
} |
7 |
|
8 |
############################################################### interaction |
9 |
|
10 |
error () { |
11 |
# <error code> <name> <string> <args> |
12 |
local err="$1" |
13 |
local name="$2" |
14 |
local fmt="$3" |
15 |
shift; shift; shift |
16 |
if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then |
17 |
(echo "E: $name" |
18 |
for x in "$@"; do echo "EA: $x"; done |
19 |
echo "EF: $fmt") >&4 |
20 |
else |
21 |
(printf "E: $fmt\n" "$@") >&4 |
22 |
fi |
23 |
exit $err |
24 |
} |
25 |
|
26 |
warning () { |
27 |
# <name> <string> <args> |
28 |
local name="$1" |
29 |
local fmt="$2" |
30 |
shift; shift |
31 |
if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then |
32 |
(echo "W: $name" |
33 |
for x in "$@"; do echo "WA: $x"; done |
34 |
echo "WF: $fmt") >&4 |
35 |
else |
36 |
printf "W: $fmt\n" "$@" >&4 |
37 |
fi |
38 |
} |
39 |
|
40 |
info () { |
41 |
# <name> <string> <args> |
42 |
local name="$1" |
43 |
local fmt="$2" |
44 |
shift; shift |
45 |
if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then |
46 |
(echo "I: $name" |
47 |
for x in "$@"; do echo "IA: $x"; done |
48 |
echo "IF: $fmt") >&4 |
49 |
else |
50 |
printf "I: $fmt\n" "$@" >&4 |
51 |
fi |
52 |
} |
53 |
|
54 |
PROGRESS_NOW=0 |
55 |
PROGRESS_END=0 |
56 |
PROGRESS_NEXT="" |
57 |
PROGRESS_WHAT="" |
58 |
|
59 |
progress_next () { |
60 |
PROGRESS_NEXT="$1" |
61 |
} |
62 |
|
63 |
wgetprogress () { |
64 |
[ ! "$verbose" ] && QSWITCH="-q" |
65 |
local ret=0 |
66 |
if [ "$USE_DEBIANINSTALLER_INTERACTION" ] && [ "$PROGRESS_NEXT" ]; then |
67 |
wget "$@" 2>&1 >/dev/null | $PKGDETAILS "WGET%" $PROGRESS_NOW $PROGRESS_NEXT $PROGRESS_END >&3 |
68 |
ret=$? |
69 |
elif [ "$USE_BOOTFLOPPIES_INTERACTION" ] && [ "$PROGRESS_NEXT" ]; then |
70 |
wget "$@" 2>&1 >/dev/null | $PKGDETAILS "WGET%" $PROGRESS_NOW $PROGRESS_NEXT $PROGRESS_END "$PROGRESS_WHAT" >&3 |
71 |
ret=$? |
72 |
else |
73 |
wget $QSWITCH "$@" |
74 |
ret=$? |
75 |
fi |
76 |
return $ret |
77 |
} |
78 |
|
79 |
progress () { |
80 |
# <now> <end> <name> <string> <args> |
81 |
local now="$1" |
82 |
local end="$2" |
83 |
local name="$3" |
84 |
local fmt="$4" |
85 |
shift; shift; shift; shift |
86 |
if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then |
87 |
PROGRESS_NOW="$now" |
88 |
PROGRESS_END="$end" |
89 |
PROGRESS_NEXT="" |
90 |
(echo "P: $now $end $name" |
91 |
for x in "$@"; do echo "PA: $x"; done |
92 |
echo "PF: $fmt") >&3 |
93 |
elif [ "$USE_BOOTFLOPPIES_INTERACTION" ]; then |
94 |
PROGRESS_NOW="$now" |
95 |
PROGRESS_END="$end" |
96 |
PROGRESS_WHAT="`printf "$fmt" "$@"`" |
97 |
PROGRESS_NEXT="" |
98 |
printf "P: %s %s %s\n" $now $end "$PROGRESS_WHAT" >&3 |
99 |
fi |
100 |
} |
101 |
|
102 |
dpkg_progress () { |
103 |
# <now> <end> <name> <desc> UNPACKING|CONFIGURING |
104 |
local now="$1" |
105 |
local end="$2" |
106 |
local name="$3" |
107 |
local desc="$4" |
108 |
local action="$5" |
109 |
local expect= |
110 |
|
111 |
if [ "$action" = UNPACKING ]; then |
112 |
expect=half-installed |
113 |
elif [ "$action" = CONFIGURING ]; then |
114 |
expect=half-configured |
115 |
fi |
116 |
|
117 |
dp () { |
118 |
now="$(($now + ${1:-1}))" |
119 |
} |
120 |
|
121 |
exitcode=0 |
122 |
while read status pkg qstate; do |
123 |
if [ "$status" = "EXITCODE" ]; then |
124 |
exitcode="$pkg" |
125 |
continue |
126 |
fi |
127 |
[ "$qstate" = "$expect" ] || continue |
128 |
case $qstate in |
129 |
half-installed) |
130 |
dp; progress "$now" "$end" "$name" "$desc" |
131 |
info "$action" "Unpacking %s..." "${pkg%:}" |
132 |
expect=unpacked |
133 |
;; |
134 |
unpacked) |
135 |
expect=half-installed |
136 |
;; |
137 |
half-configured) |
138 |
dp; progress "$now" "$end" "$name" "$desc" |
139 |
info "$action" "Configuring %s..." "${pkg%:}" |
140 |
expect=installed |
141 |
;; |
142 |
installed) |
143 |
expect=half-configured |
144 |
;; |
145 |
esac |
146 |
done |
147 |
return $exitcode |
148 |
} |
149 |
|
150 |
############################################################# set variables |
151 |
|
152 |
default_mirror () { |
153 |
DEF_MIRROR="$1" |
154 |
} |
155 |
|
156 |
FINDDEBS_NEEDS_INDICES=false |
157 |
finddebs_style () { |
158 |
case "$1" in |
159 |
hardcoded) |
160 |
;; |
161 |
from-indices) |
162 |
FINDDEBS_NEEDS_INDICES=true |
163 |
;; |
164 |
*) |
165 |
error 1 BADFINDDEBS "unknown finddebs style" |
166 |
;; |
167 |
esac |
168 |
} |
169 |
|
170 |
mk_download_dirs () { |
171 |
if [ $DLDEST = "apt_dest" ]; then |
172 |
mkdir -p "$TARGET/$APTSTATE/lists/partial" |
173 |
mkdir -p "$TARGET/var/cache/apt/archives/partial" |
174 |
fi |
175 |
} |
176 |
|
177 |
download_style () { |
178 |
case "$1" in |
179 |
apt) |
180 |
if [ "$2" = "var-state" ]; then |
181 |
APTSTATE=var/state/apt |
182 |
else |
183 |
APTSTATE=var/lib/apt |
184 |
fi |
185 |
DLDEST=apt_dest |
186 |
export APTSTATE DLDEST DEBFOR |
187 |
;; |
188 |
*) |
189 |
error 1 BADDLOAD "unknown download style" |
190 |
;; |
191 |
esac |
192 |
} |
193 |
|
194 |
########################################################## variant handling |
195 |
|
196 |
doing_variant () { |
197 |
if [ "$1" = "$VARIANT" ]; then return 0; fi |
198 |
if [ "$1" = "-" ] && [ "$VARIANT" = "" ]; then return 0; fi |
199 |
return 1 |
200 |
} |
201 |
|
202 |
SUPPORTED_VARIANTS="-" |
203 |
variants () { |
204 |
SUPPORTED_VARIANTS="$*" |
205 |
for v in $*; do |
206 |
if doing_variant "$v"; then return 0; fi |
207 |
done |
208 |
error 1 UNSUPPVARIANT "unsupported variant" |
209 |
} |
210 |
|
211 |
################################################# work out names for things |
212 |
|
213 |
mirror_style () { |
214 |
case "$1" in |
215 |
release) |
216 |
DOWNLOAD_INDICES=download_release_indices |
217 |
DOWNLOAD_DEBS=download_release |
218 |
;; |
219 |
main) |
220 |
DOWNLOAD_INDICES=download_main_indices |
221 |
DOWNLOAD_DEBS=download_main |
222 |
;; |
223 |
*) |
224 |
error 1 BADMIRROR "unknown mirror style" |
225 |
;; |
226 |
esac |
227 |
export DOWNLOAD_INDICES |
228 |
export DOWNLOAD_DEBS |
229 |
} |
230 |
|
231 |
check_md5 () { |
232 |
# args: dest md5 size |
233 |
local expmd5="$2" |
234 |
local expsize="$3" |
235 |
relmd5=`md5sum < "$1" | sed 's/ .*$//'` |
236 |
relsize=`wc -c < "$1"` |
237 |
if [ "$expsize" -ne "$relsize" ] || [ "$expmd5" != "$relmd5" ]; then |
238 |
return 1 |
239 |
fi |
240 |
return 0 |
241 |
} |
242 |
|
243 |
get () { |
244 |
# args: from dest 'nocache' |
245 |
# args: from dest [md5sum size] [alt {md5sum size type}] |
246 |
local displayname |
247 |
if [ "${2%.deb}" != "$2" ]; then |
248 |
displayname="$(echo "$2" | sed 's,^.*/,,;s,_.*$,,')" |
249 |
else |
250 |
displayname="$(echo "$1" | sed 's,^.*/,,')" |
251 |
fi |
252 |
|
253 |
if [ -e "$2" ]; then |
254 |
if [ -z "$3" ]; then |
255 |
return 0 |
256 |
elif [ "$3" = nocache ]; then |
257 |
rm -f "$2" |
258 |
else |
259 |
info VALIDATING "Validating %s" "$displayname" |
260 |
if check_md5 "$2" "$3" "$4"; then |
261 |
return 0 |
262 |
else |
263 |
rm -f "$2" |
264 |
fi |
265 |
fi |
266 |
fi |
267 |
# Drop 'nocache' option |
268 |
if [ "$3" = nocache ]; then |
269 |
set "$1" "$2" |
270 |
fi |
271 |
|
272 |
if [ "$#" -gt 5 ]; then |
273 |
local st=3 |
274 |
if [ "$5" = "-" ]; then st=6; fi |
275 |
local order="$(a=$st; while [ "$a" -le $# ]; do eval echo \"\${$(($a+1))}\" $a; |
276 |
a=$(($a + 3)); done | sort -n | sed 's/.* //')" |
277 |
else |
278 |
local order=3 |
279 |
fi |
280 |
for a in $order; do |
281 |
local md5="$(eval echo \${$a})" |
282 |
local siz="$(eval echo \${$(( $a+1 ))})" |
283 |
local typ="$(eval echo \${$(( $a+2 ))})" |
284 |
local from |
285 |
local dest |
286 |
|
287 |
case "$typ" in |
288 |
bz2) from="$1.bz2"; dest="$2.bz2" ;; |
289 |
gz) from="$1.gz"; dest="$2.gz" ;; |
290 |
*) from="$1"; dest="$2" ;; |
291 |
esac |
292 |
|
293 |
if [ "${dest#/}" = "$dest" ]; then |
294 |
dest="./$dest" |
295 |
fi |
296 |
local dest2="$dest" |
297 |
if [ -d "${dest2%/*}/partial" ]; then |
298 |
dest2="${dest2%/*}/partial/${dest2##*/}" |
299 |
fi |
300 |
|
301 |
info RETRIEVING "Retrieving %s" "$displayname" |
302 |
if ! just_get "$from" "$dest2"; then continue; fi |
303 |
if [ "$md5" != "" ]; then |
304 |
info VALIDATING "Validating %s" "$displayname" |
305 |
if check_md5 "$dest2" "$md5" "$siz"; then |
306 |
md5="" |
307 |
fi |
308 |
fi |
309 |
if [ -z "$md5" ]; then |
310 |
[ "$dest2" = "$dest" ] || mv "$dest2" "$dest" |
311 |
case "$typ" in |
312 |
gz) gunzip "$dest" ;; |
313 |
bz2) bunzip2 "$dest" ;; |
314 |
esac |
315 |
return 0 |
316 |
else |
317 |
warning CORRUPTFILE "%s was corrupt" "$from" |
318 |
fi |
319 |
done |
320 |
return 1 |
321 |
} |
322 |
|
323 |
just_get () { |
324 |
# args: from dest |
325 |
local from="$1" |
326 |
local dest="$2" |
327 |
mkdir -p "${dest%/*}" |
328 |
if [ "${from#null:}" != "$from" ]; then |
329 |
error 1 NOTPREDL "%s was not pre-downloaded" "${from#null:}" |
330 |
elif [ "${from#http://}" != "$from" ] || [ "${from#ftp://}" != "$from" ]; then |
331 |
# http/ftp mirror |
332 |
if wgetprogress -O "$dest" "$from"; then |
333 |
return 0 |
334 |
elif [ -s "$dest" ]; then |
335 |
local iters=0 |
336 |
while [ "$iters" -lt 3 ]; do |
337 |
warning RETRYING "Retrying failed download of %s" "$from" |
338 |
if wgetprogress -c -O "$dest" "$from"; then break; fi |
339 |
iters="$(($iters + 1))" |
340 |
done |
341 |
else |
342 |
rm -f "$dest" |
343 |
return 1 |
344 |
fi |
345 |
elif [ "${from#https://}" != "$from" ] ; then |
346 |
# http/ftp mirror |
347 |
if wgetprogress $CHECKCERTIF $CERTIFICATE $PRIVATEKEY -O "$dest" "$from"; then |
348 |
return 0 |
349 |
elif [ -s "$dest" ]; then |
350 |
local iters=0 |
351 |
while [ "$iters" -lt 3 ]; do |
352 |
warning RETRYING "Retrying failed download of %s" "$from" |
353 |
if wgetprogress $CHECKCERTIF $CERTIFICATE $PRIVATEKEY -c -O "$dest" "$from"; then break; fi |
354 |
iters="$(($iters + 1))" |
355 |
done |
356 |
else |
357 |
rm -f "$dest" |
358 |
return 1 |
359 |
fi |
360 |
elif [ "${from#file:}" != "$from" ]; then |
361 |
local base="${from#file:}" |
362 |
if [ "${base#//}" != "$base" ]; then |
363 |
base="/${from#file://*/}" |
364 |
fi |
365 |
if [ -e "$base" ]; then |
366 |
cp "$base" "$dest" |
367 |
return 0 |
368 |
else |
369 |
return 1 |
370 |
fi |
371 |
elif [ "${from#ssh:}" != "$from" ]; then |
372 |
local ssh_dest="$(echo $from | sed -e 's#ssh://##' -e 's#/#:/#')" |
373 |
if [ -n "$ssh_dest" ]; then |
374 |
scp "$ssh_dest" "$dest" |
375 |
return 0 |
376 |
else |
377 |
return 1 |
378 |
fi |
379 |
else |
380 |
error 1 UNKNOWNLOC "unknown location %s" "$from" |
381 |
fi |
382 |
} |
383 |
|
384 |
download () { |
385 |
mk_download_dirs |
386 |
"$DOWNLOAD_DEBS" $(echo "$@" | tr ' ' '\n' | sort) |
387 |
} |
388 |
|
389 |
download_indices () { |
390 |
mk_download_dirs |
391 |
"$DOWNLOAD_INDICES" $(echo "$@" | tr ' ' '\n' | sort) |
392 |
} |
393 |
|
394 |
debfor () { |
395 |
(while read pkg path; do |
396 |
for p in "$@"; do |
397 |
[ "$p" = "$pkg" ] || continue; |
398 |
echo "$path" |
399 |
done |
400 |
done <"$TARGET/debootstrap/debpaths" |
401 |
) |
402 |
} |
403 |
|
404 |
apt_dest () { |
405 |
# args: |
406 |
# deb package version arch mirror path |
407 |
# pkg suite component arch mirror path |
408 |
# rel suite mirror path |
409 |
case "$1" in |
410 |
deb) |
411 |
echo "/var/cache/apt/archives/${2}_${3}_${4}.deb" | sed 's/:/%3a/' |
412 |
;; |
413 |
pkg) |
414 |
local m="$5" |
415 |
m="debootstrap.invalid" |
416 |
#if [ "${m#http://}" != "$m" ]; then |
417 |
# m="${m#http://}" |
418 |
#elif [ "${m#file://}" != "$m" ]; then |
419 |
# m="file_localhost_${m#file://*/}" |
420 |
#elif [ "${m#file:/}" != "$m" ]; then |
421 |
# m="file_localhost_${m#file:/}" |
422 |
#fi |
423 |
|
424 |
printf "%s" "$APTSTATE/lists/" |
425 |
echo "${m}_$6" | sed 's/\//_/g' |
426 |
;; |
427 |
rel) |
428 |
local m="$3" |
429 |
m="debootstrap.invalid" |
430 |
#if [ "${m#http://}" != "$m" ]; then |
431 |
# m="${m#http://}" |
432 |
#elif [ "${m#file://}" != "$m" ]; then |
433 |
# m="file_localhost_${m#file://*/}" |
434 |
#elif [ "${m#file:/}" != "$m" ]; then |
435 |
# m="file_localhost_${m#file:/}" |
436 |
#fi |
437 |
printf "%s" "$APTSTATE/lists/" |
438 |
echo "${m}_$4" | sed 's/\//_/g' |
439 |
;; |
440 |
esac |
441 |
} |
442 |
|
443 |
################################################################## download |
444 |
|
445 |
get_release_md5 () { |
446 |
local reldest="$1" |
447 |
local path="$2" |
448 |
sed -n '/^[Mm][Dd]5[Ss][Uu][Mm]/,/^[^ ]/p' < "$reldest" | \ |
449 |
while read a b c; do |
450 |
if [ "$c" = "$path" ]; then echo "$a $b"; fi |
451 |
done | head -n 1 |
452 |
} |
453 |
|
454 |
download_release_sig () { |
455 |
local m1="$1" |
456 |
local reldest="$2" |
457 |
local relsigdest="$TARGET/$($DLDEST rel "$SUITE" "$m1" "dists/$SUITE/Release.gpg")" |
458 |
|
459 |
if [ -n "$KEYRING" ]; then |
460 |
progress 0 100 DOWNRELSIG "Downloading Release file signature" |
461 |
progress_next 50 |
462 |
get "$m1/dists/$SUITE/Release.gpg" "$relsigdest" nocache || |
463 |
error 1 NOGETRELSIG "Failed getting release signature file %s" \ |
464 |
"$m1/dists/$SUITE/Release.gpg" |
465 |
progress 50 100 DOWNRELSIG "Downloading Release file signature" |
466 |
|
467 |
info RELEASESIG "Checking Release signature" |
468 |
# Don't worry about the exit status from gpgv; parsing the output will |
469 |
# take care of that. |
470 |
(gpgv --status-fd 1 --keyring "$KEYRING" --ignore-time-conflict \ |
471 |
"$relsigdest" "$reldest" || true) | read_gpg_status |
472 |
progress 100 100 DOWNRELSIG "Downloading Release file signature" |
473 |
fi |
474 |
} |
475 |
|
476 |
download_release_indices () { |
477 |
local m1="${MIRRORS%% *}" |
478 |
local reldest="$TARGET/$($DLDEST rel "$SUITE" "$m1" "dists/$SUITE/Release")" |
479 |
progress 0 100 DOWNREL "Downloading Release file" |
480 |
progress_next 100 |
481 |
get "$m1/dists/$SUITE/Release" "$reldest" nocache || |
482 |
error 1 NOGETREL "Failed getting release file %s" "$m1/dists/$SUITE/Release" |
483 |
|
484 |
TMPCOMPONENTS="$(sed -n 's/Components: *//p' "$reldest")" |
485 |
for c in $TMPCOMPONENTS ; do |
486 |
eval " |
487 |
case \"\$c\" in |
488 |
$USE_COMPONENTS) |
489 |
COMPONENTS=\"\$COMPONENTS \$c\" |
490 |
;; |
491 |
esac |
492 |
" |
493 |
done |
494 |
COMPONENTS="$(echo $COMPONENTS)" |
495 |
|
496 |
if [ -z "$COMPONENTS" ]; then |
497 |
mv "$reldest" "$reldest.malformed" |
498 |
error 1 INVALIDREL "Invalid Release file, no valid components" |
499 |
fi |
500 |
progress 100 100 DOWNREL "Downloading Release file" |
501 |
|
502 |
download_release_sig "$m1" "$reldest" |
503 |
|
504 |
local totalpkgs=0 |
505 |
for c in $COMPONENTS; do |
506 |
local subpath="$c/binary-$ARCH/Packages" |
507 |
local bz2md="`get_release_md5 "$reldest" "$subpath.bz2"`" |
508 |
local gzmd="`get_release_md5 "$reldest" "$subpath.gz"`" |
509 |
local normmd="`get_release_md5 "$reldest" "$subpath"`" |
510 |
local md= |
511 |
if [ "$normmd" != "" ]; then |
512 |
md="$normmd" |
513 |
elif [ -x /bin/bunzip2 ] && [ "$bz2md" != "" ]; then |
514 |
md="$bz2md" |
515 |
elif [ -x /bin/gunzip ] && [ "$gzmd" != "" ]; then |
516 |
md="$gzmd" |
517 |
fi |
518 |
if [ "$md" != "" ]; then |
519 |
totalpkgs="$(( $totalpkgs + ${md#* } ))" |
520 |
else |
521 |
mv "$reldest" "$reldest.malformed" |
522 |
error 1 MISSINGRELENTRY "Invalid Release file, no entry for %s" "$subpath" |
523 |
fi |
524 |
done |
525 |
|
526 |
local donepkgs=0 |
527 |
local pkgdest |
528 |
progress 0 $totalpkgs DOWNPKGS "Downloading Packages files" |
529 |
for c in $COMPONENTS; do |
530 |
local subpath="$c/binary-$ARCH/Packages" |
531 |
local path="dists/$SUITE/$subpath" |
532 |
local bz2md="`get_release_md5 "$reldest" "$subpath.bz2"`" |
533 |
local gzmd="`get_release_md5 "$reldest" "$subpath.gz"`" |
534 |
local normmd="`get_release_md5 "$reldest" "$subpath"`" |
535 |
local ext= |
536 |
local md= |
537 |
if [ "$normmd" != "" ]; then |
538 |
ext="$ext $normmd ." |
539 |
md="$normmd" |
540 |
fi |
541 |
if [ -x /bin/bunzip2 ] && [ "$bz2md" != "" ]; then |
542 |
ext="$ext $bz2md bz2" |
543 |
md="${md:-$bz2md}" |
544 |
fi |
545 |
if [ -x /bin/gunzip ] && [ "$gzmd" != "" ]; then |
546 |
ext="$ext $gzmd gz" |
547 |
md="${md:-$gzmd}" |
548 |
fi |
549 |
progress_next "$(($donepkgs + ${md#* }))" |
550 |
for m in $MIRRORS; do |
551 |
pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")" |
552 |
if get "$m/$path" "$pkgdest" $ext; then break; fi |
553 |
done |
554 |
if [ ! -f "$pkgdest" ]; then |
555 |
error 1 COULDNTDL "Couldn't download %s" "$path" |
556 |
fi |
557 |
donepkgs="$(($donepkgs + ${md#* }))" |
558 |
progress $donepkgs $totalpkgs DOWNPKGS "Downloading Packages files" |
559 |
done |
560 |
} |
561 |
|
562 |
get_package_sizes () { |
563 |
# mirror pkgdest debs.. |
564 |
local m="$1"; shift |
565 |
local pkgdest="$1"; shift |
566 |
$PKGDETAILS PKGS "$m" "$pkgdest" "$@" | ( |
567 |
newleft="" |
568 |
totaldebs=0 |
569 |
countdebs=0 |
570 |
while read p details; do |
571 |
if [ "$details" = "-" ]; then |
572 |
newleft="$newleft $p" |
573 |
else |
574 |
size="${details##* }"; |
575 |
totaldebs="$(($totaldebs + $size))" |
576 |
countdebs="$(($countdebs + 1))" |
577 |
fi |
578 |
done |
579 |
echo "$countdebs $totaldebs$newleft" |
580 |
) |
581 |
} |
582 |
|
583 |
# note, leftovers come back on fd5 !! |
584 |
download_debs () { |
585 |
local m="$1" |
586 |
local pkgdest="$2" |
587 |
shift; shift |
588 |
|
589 |
$PKGDETAILS PKGS "$m" "$pkgdest" "$@" | ( |
590 |
leftover="" |
591 |
while read p ver arc mdup fil md5 size; do |
592 |
if [ "$ver" = "-" ]; then |
593 |
leftover="$leftover $p" |
594 |
else |
595 |
progress_next "$(($dloaddebs + $size))" |
596 |
local debdest="$($DLDEST deb "$p" "$ver" "$arc" "$m" "$fil")" |
597 |
if get "$m/$fil" "$TARGET/$debdest" "$md5" "$size"; then |
598 |
dloaddebs="$(($dloaddebs + $size))" |
599 |
echo >>$TARGET/debootstrap/debpaths "$p $debdest" |
600 |
else |
601 |
warning COULDNTDL "Couldn't download package %s" "$p" |
602 |
fi |
603 |
fi |
604 |
done |
605 |
echo >&5 ${leftover# } |
606 |
) |
607 |
} |
608 |
|
609 |
download_release () { |
610 |
local m1="${MIRRORS%% *}" |
611 |
|
612 |
local numdebs="$#" |
613 |
|
614 |
local countdebs=0 |
615 |
progress $countdebs $numdebs SIZEDEBS "Finding package sizes" |
616 |
|
617 |
local totaldebs=0 |
618 |
local leftoverdebs="$*" |
619 |
for c in $COMPONENTS; do |
620 |
if [ "$countdebs" -ge "$numdebs" ]; then break; fi |
621 |
|
622 |
local path="dists/$SUITE/$c/binary-$ARCH/Packages" |
623 |
local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")" |
624 |
if [ ! -e "$pkgdest" ]; then continue; fi |
625 |
|
626 |
info CHECKINGSIZES "Checking component %s on %s..." "$c" "$m1" |
627 |
|
628 |
leftoverdebs="$(get_package_sizes "$m1" "$pkgdest" $leftoverdebs)" |
629 |
|
630 |
countdebs=$(($countdebs + ${leftoverdebs%% *})) |
631 |
leftoverdebs=${leftoverdebs#* } |
632 |
|
633 |
totaldebs=${leftoverdebs%% *} |
634 |
leftoverdebs=${leftoverdebs#* } |
635 |
|
636 |
progress $countdebs $numdebs SIZEDEBS "Finding package sizes" |
637 |
done |
638 |
|
639 |
if [ "$countdebs" -ne "$numdebs" ]; then |
640 |
error 1 LEFTOVERDEBS "Couldn't find these debs: %s" "$leftoverdebs" |
641 |
fi |
642 |
|
643 |
local dloaddebs=0 |
644 |
|
645 |
progress $dloaddebs $totaldebs DOWNDEBS "Downloading packages" |
646 |
:>$TARGET/debootstrap/debpaths |
647 |
|
648 |
pkgs_to_get="$*" |
649 |
for c in $COMPONENTS; do |
650 |
local path="dists/$SUITE/$c/binary-$ARCH/Packages" |
651 |
for m in $MIRRORS; do |
652 |
local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")" |
653 |
if [ ! -e "$pkgdest" ]; then continue; fi |
654 |
pkgs_to_get="$(download_debs "$m" "$pkgdest" $pkgs_to_get 5>&1 1>&6)" |
655 |
if [ -z "$pkgs_to_get" ]; then break; fi |
656 |
done 6>&1 |
657 |
if [ -z "$pkgs_to_get" ]; then break; fi |
658 |
done |
659 |
progress $dloaddebs $totaldebs DOWNDEBS "Downloading packages" |
660 |
if [ "$pkgs_to_get" != "" ]; then |
661 |
error 1 COULDNTDLPKGS "Couldn't download packages: %s" "$pkgs_to_get" |
662 |
fi |
663 |
} |
664 |
|
665 |
download_main_indices () { |
666 |
local m1="${MIRRORS%% *}" |
667 |
local comp="${USE_COMPONENTS}" |
668 |
progress 0 100 DOWNMAINPKGS "Downloading Packages file" |
669 |
progress_next 100 |
670 |
|
671 |
if [ -z "$comp" ]; then comp=main; fi |
672 |
COMPONENTS="$(echo $comp | tr '|' ' ')" |
673 |
|
674 |
export COMPONENTS |
675 |
for m in $MIRRORS; do |
676 |
for c in $COMPONENTS; do |
677 |
local path="dists/$SUITE/$c/binary-$ARCH/Packages" |
678 |
local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")" |
679 |
if [ -x /bin/gunzip ] && get "$m/${path}.gz" "${pkgdest}.gz"; then |
680 |
rm -f "$pkgdest" |
681 |
gunzip "$pkgdest.gz" |
682 |
elif get "$m/$path" "$pkgdest"; then |
683 |
true |
684 |
fi |
685 |
done |
686 |
done |
687 |
progress 100 100 DOWNMAINPKGS "Downloading Packages file" |
688 |
} |
689 |
|
690 |
download_main () { |
691 |
local m1="${MIRRORS%% *}" |
692 |
|
693 |
:>$TARGET/debootstrap/debpaths |
694 |
for p in "$@"; do |
695 |
for c in $COMPONENTS; do |
696 |
local details="" |
697 |
for m in $MIRRORS; do |
698 |
local path="dists/$SUITE/$c/binary-$ARCH/Packages" |
699 |
local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")" |
700 |
if [ ! -e "$pkgdest" ]; then continue; fi |
701 |
details="$($PKGDETAILS PKGS "$m" "$pkgdest" "$p")" |
702 |
if [ "$details" = "$p -" ]; then |
703 |
details="" |
704 |
continue |
705 |
fi |
706 |
size="${details##* }"; details="${details% *}" |
707 |
md5="${details##* }"; details="${details% *}" |
708 |
local debdest="$($DLDEST deb $details)" |
709 |
if get "$m/${details##* }" "$TARGET/$debdest" "$md5" "$size"; then |
710 |
echo >>$TARGET/debootstrap/debpaths "$p $debdest" |
711 |
details="done" |
712 |
break |
713 |
fi |
714 |
done |
715 |
if [ "$details" != "" ]; then |
716 |
break |
717 |
fi |
718 |
done |
719 |
if [ "$details" != "done" ]; then |
720 |
error 1 COULDNTDL "Couldn't download %s" "$p" |
721 |
fi |
722 |
done |
723 |
} |
724 |
|
725 |
###################################################### deb choosing support |
726 |
|
727 |
get_debs () { |
728 |
local field="$1" |
729 |
shift |
730 |
local m1 c |
731 |
for m1 in $MIRRORS; do |
732 |
for c in $COMPONENTS; do |
733 |
local path="dists/$SUITE/$c/binary-$ARCH/Packages" |
734 |
local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")" |
735 |
echo $("$PKGDETAILS" FIELD "$field" "$m1" "$pkgdest" "$@" | sed 's/ .*//') |
736 |
done |
737 |
done |
738 |
} |
739 |
|
740 |
################################################################ extraction |
741 |
|
742 |
EXTRACTORS_SUPPORTED="dpkg-deb ar" |
743 |
|
744 |
# Native dpkg-deb based extractors |
745 |
extract_dpkg_deb_field () { |
746 |
local pkg="$1" |
747 |
local field="$2" |
748 |
|
749 |
dpkg-deb -f "$pkg" "$field" |
750 |
} |
751 |
|
752 |
extract_dpkg_deb_data () { |
753 |
local pkg="$1" |
754 |
|
755 |
dpkg-deb --fsys-tarfile "$pkg" | tar -xf - |
756 |
} |
757 |
|
758 |
# Raw .deb extractors |
759 |
extract_ar_deb_field () { |
760 |
local pkg="$1" |
761 |
local field="$2" |
762 |
|
763 |
ar -p "$pkg" control.tar.gz | zcat | |
764 |
tar -O -xf - control ./control 2>/dev/null | |
765 |
grep -i "^$field:" | sed -e 's/[^:]*: *//' | head -n 1 |
766 |
} |
767 |
|
768 |
extract_ar_deb_data () { |
769 |
local pkg="$1" |
770 |
local tarball=$(ar -t "$pkg" | grep "^data.tar.[bgx]z") |
771 |
|
772 |
case "$tarball" in |
773 |
data.tar.gz) cat_cmd=zcat ;; |
774 |
data.tar.bz2) cat_cmd=bzcat ;; |
775 |
data.tar.xz) cat_cmd=xzcat ;; |
776 |
*) error 1 UNKNOWNDATACOMP "Unknown compression type for %s in %s" "$tarball" "$pkg" ;; |
777 |
esac |
778 |
|
779 |
if type $cat_cmd >/dev/null 2>&1; then |
780 |
ar -p "$pkg" "$tarball" | $cat_cmd | tar -xf - |
781 |
else |
782 |
error 1 UNPACKCMDUNVL "The $cat_cmd is not available on the system" |
783 |
fi |
784 |
} |
785 |
|
786 |
valid_extractor () { |
787 |
local extractor="$1" |
788 |
|
789 |
for E in $EXTRACTORS_SUPPORTED; do |
790 |
if [ "$extractor" = "$E" ]; then |
791 |
return 0 |
792 |
fi |
793 |
done |
794 |
|
795 |
return 1 |
796 |
} |
797 |
|
798 |
choose_extractor () { |
799 |
local extractor |
800 |
|
801 |
if [ -n "$EXTRACTOR_OVERRIDE" ]; then |
802 |
extractor="$EXTRACTOR_OVERRIDE" |
803 |
elif type dpkg-deb >/dev/null 2>&1; then |
804 |
extractor="dpkg-deb" |
805 |
else |
806 |
extractor="ar" |
807 |
fi |
808 |
|
809 |
info CHOSENEXTRACTOR "Chosen extractor for .deb packages: %s" "$extractor" |
810 |
case "$extractor" in |
811 |
dpkg-deb) |
812 |
extract_deb_field () { extract_dpkg_deb_field "$@"; } |
813 |
extract_deb_data () { extract_dpkg_deb_data "$@"; } |
814 |
;; |
815 |
ar) |
816 |
extract_deb_field () { extract_ar_deb_field "$@"; } |
817 |
extract_deb_data () { extract_ar_deb_data "$@"; } |
818 |
;; |
819 |
esac |
820 |
} |
821 |
|
822 |
extract () { ( |
823 |
cd "$TARGET" |
824 |
local p=0 cat_cmd |
825 |
for pkg in $(debfor "$@"); do |
826 |
p="$(($p + 1))" |
827 |
progress "$p" "$#" EXTRACTPKGS "Extracting packages" |
828 |
packagename="$(echo "$pkg" | sed 's,^.*/,,;s,_.*$,,')" |
829 |
info EXTRACTING "Extracting %s..." "$packagename" |
830 |
extract_deb_data "./$pkg" |
831 |
done |
832 |
); } |
833 |
|
834 |
in_target_nofail () { |
835 |
if ! $CHROOT_CMD "$@" 2>/dev/null; then |
836 |
true |
837 |
fi |
838 |
return 0 |
839 |
} |
840 |
|
841 |
in_target_failmsg () { |
842 |
local code="$1" |
843 |
local msg="$2" |
844 |
local arg="$3" |
845 |
shift; shift; shift |
846 |
if ! $CHROOT_CMD "$@"; then |
847 |
warning "$code" "$msg" "$arg" |
848 |
return 1 |
849 |
fi |
850 |
return 0 |
851 |
} |
852 |
|
853 |
in_target () { |
854 |
in_target_failmsg IN_TARGET_FAIL "Failure trying to run: %s" "$CHROOT_CMD $*" "$@" |
855 |
} |
856 |
|
857 |
###################################################### standard setup stuff |
858 |
|
859 |
conditional_cp () { |
860 |
if [ ! -e "$2/$1" ]; then |
861 |
if [ -L "$1" ] && [ -e "$1" ]; then |
862 |
cat "$1" >"$2/$1" |
863 |
elif [ -e "$1" ]; then |
864 |
cp -a "$1" "$2/$1" |
865 |
fi |
866 |
fi |
867 |
} |
868 |
|
869 |
mv_invalid_to () { |
870 |
local m="$1" |
871 |
m="$(echo "${m#http://}" | tr '/' '_' | sed 's/_*//')" |
872 |
(cd "$TARGET/$APTSTATE/lists" |
873 |
for a in debootstrap.invalid_*; do |
874 |
mv "$a" "${m}_${a#*_}" |
875 |
done |
876 |
) |
877 |
} |
878 |
|
879 |
setup_apt_sources () { |
880 |
mkdir -p "$TARGET/etc/apt" |
881 |
for m in "$@"; do |
882 |
local cs="" |
883 |
for c in $COMPONENTS; do |
884 |
local path="dists/$SUITE/$c/binary-$ARCH/Packages" |
885 |
local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")" |
886 |
if [ -e "$pkgdest" ]; then cs="$cs $c"; fi |
887 |
done |
888 |
if [ "$cs" != "" ]; then echo "deb $m $SUITE$cs"; fi |
889 |
done > "$TARGET/etc/apt/sources.list" |
890 |
} |
891 |
|
892 |
setup_etc () { |
893 |
mkdir -p "$TARGET/etc" |
894 |
|
895 |
conditional_cp /etc/resolv.conf "$TARGET" |
896 |
conditional_cp /etc/hostname "$TARGET" |
897 |
|
898 |
if [ "$DLDEST" = apt_dest ] && [ ! -e "$TARGET/etc/apt/sources.list" ]; then |
899 |
setup_apt_sources "http://debootstrap.invalid/" |
900 |
fi |
901 |
} |
902 |
|
903 |
UMOUNT_DIRS= |
904 |
|
905 |
umount_exit_function () { |
906 |
for dir in $UMOUNT_DIRS; do |
907 |
umount "$TARGET/${dir#/}" || true |
908 |
done |
909 |
} |
910 |
|
911 |
umount_on_exit () { |
912 |
if [ "$UMOUNT_DIRS" ]; then |
913 |
UMOUNT_DIRS="$UMOUNT_DIRS $1" |
914 |
else |
915 |
UMOUNT_DIRS="$1" |
916 |
on_exit umount_exit_function |
917 |
fi |
918 |
} |
919 |
|
920 |
clear_mtab () { |
921 |
if [ -f "$TARGET/etc/mtab" ] && [ ! -h "$TARGET/etc/mtab" ]; then |
922 |
rm -f "$TARGET/etc/mtab" |
923 |
fi |
924 |
} |
925 |
|
926 |
setup_proc () { |
927 |
case "$ARCH" in |
928 |
kfreebsd-*) |
929 |
umount_on_exit /dev |
930 |
umount_on_exit /proc |
931 |
umount "$TARGET/proc" 2>/dev/null || true |
932 |
in_target mount -t linprocfs proc /proc |
933 |
;; |
934 |
hurd-*) |
935 |
;; |
936 |
*) |
937 |
umount_on_exit /dev/pts |
938 |
umount_on_exit /dev/shm |
939 |
umount_on_exit /proc/bus/usb |
940 |
umount_on_exit /proc |
941 |
umount "$TARGET/proc" 2>/dev/null || true |
942 |
in_target mount -t proc proc /proc |
943 |
if [ -d "$TARGET/sys" ] && \ |
944 |
grep -q '[[:space:]]sysfs' /proc/filesystems 2>/dev/null; then |
945 |
umount_on_exit /sys |
946 |
umount "$TARGET/sys" 2>/dev/null || true |
947 |
in_target mount -t sysfs sysfs /sys |
948 |
fi |
949 |
on_exit clear_mtab |
950 |
;; |
951 |
esac |
952 |
umount_on_exit /lib/init/rw |
953 |
} |
954 |
|
955 |
setup_proc_fakechroot () { |
956 |
rm -rf "$TARGET/proc" |
957 |
ln -s /proc "$TARGET" |
958 |
} |
959 |
|
960 |
setup_devices () { |
961 |
case "$ARCH" in |
962 |
kfreebsd-*) |
963 |
in_target mount -t devfs devfs /dev ;; |
964 |
hurd-*) |
965 |
setup_devices_hurd ;; |
966 |
*) |
967 |
if [ -e "$DEVICES_TARGZ" ]; then |
968 |
zcat "$DEVICES_TARGZ" | (cd "$TARGET"; tar -xf -) |
969 |
else |
970 |
if [ -e /dev/.devfsd ] ; then |
971 |
in_target mount -t devfs devfs /dev |
972 |
else |
973 |
error 1 NODEVTGZ "no %s. cannot create devices" "$DEVICES_TARGZ" |
974 |
fi |
975 |
fi |
976 |
;; |
977 |
esac |
978 |
} |
979 |
|
980 |
setup_devices_hurd () { |
981 |
mkdir -p "$TARGET/servers/socket" |
982 |
/bin/settrans -cfk "$TARGET/servers/socket/1" /hurd/pflocal |
983 |
/bin/settrans -cf "$TARGET/servers/socket/2" /hurd/pfinet |
984 |
/bin/settrans -cfk "$TARGET/servers/exec" /hurd/exec |
985 |
/bin/settrans -cf "$TARGET/servers/crash-suspend" /hurd/crash --suspend |
986 |
/bin/settrans -cf "$TARGET/servers/crash-kill" /hurd/crash --kill |
987 |
/bin/settrans -cf "$TARGET/servers/crash-dump-core" /hurd/crash --dump-core |
988 |
/bin/settrans -cf "$TARGET/servers/password" /hurd/password |
989 |
/bin/settrans -cf "$TARGET/servers/default-pager" /hurd/proxy-defpager |
990 |
ln -fs crash-kill "$TARGET/servers/crash" |
991 |
ln -fs 1 "$TARGET/servers/socket/local" |
992 |
ln -fs 2 "$TARGET/servers/socket/inet" |
993 |
(cd "$TARGET/dev"; /sbin/MAKEDEV fd std ptyp ptyq vcs tty1 tty2 tty3 tty4 tty5 tty6) |
994 |
} |
995 |
|
996 |
setup_devices_fakechroot () { |
997 |
rm -rf "$TARGET/dev" |
998 |
ln -s /dev "$TARGET" |
999 |
} |
1000 |
|
1001 |
setup_dselect_method () { |
1002 |
case "$1" in |
1003 |
apt) |
1004 |
mkdir -p "$TARGET/var/lib/dpkg" |
1005 |
echo "apt apt" > "$TARGET/var/lib/dpkg/cmethopt" |
1006 |
chmod 644 "$TARGET/var/lib/dpkg/cmethopt" |
1007 |
;; |
1008 |
*) |
1009 |
error 1 UNKNOWNDSELECT "unknown dselect method" |
1010 |
;; |
1011 |
esac |
1012 |
} |
1013 |
|
1014 |
################################################################ pkgdetails |
1015 |
|
1016 |
# NOTE |
1017 |
# For the debootstrap udeb, pkgdetails is provided by the bootstrap-base |
1018 |
# udeb, so the pkgdetails API needs to be kept in sync with that. |
1019 |
|
1020 |
if [ -x /usr/bin/perl ]; then |
1021 |
PKGDETAILS=pkgdetails_perl |
1022 |
|
1023 |
pkgdetails_field () { |
1024 |
# uniq field mirror Packages values... |
1025 |
perl -le ' |
1026 |
$unique = shift @ARGV; $field = lc(shift @ARGV); $mirror = shift @ARGV; |
1027 |
$cnt = length(@ARGV); |
1028 |
%fields = map { $_, 0 } @ARGV; |
1029 |
while (<STDIN>) { |
1030 |
chomp; |
1031 |
next if (/^ /); |
1032 |
if (/^([^:]*:)\s*(.*)$/) { |
1033 |
$f = lc($1); $v = $2; |
1034 |
$pkg = $v if ($f eq "package:"); |
1035 |
$ver = $v if ($f eq "version:"); |
1036 |
$arc = $v if ($f eq "architecture:"); |
1037 |
$fil = $v if ($f eq "filename:"); |
1038 |
$md5 = $v if ($f eq "md5sum:"); |
1039 |
$siz = $v if ($f eq "size:"); |
1040 |
$val = $v if ($f eq $field); |
1041 |
} elsif (/^$/) { |
1042 |
if (defined $val && defined $fields{$val}) { |
1043 |
$cnt++; |
1044 |
printf "%s %s %s %s %s %s %s\n", |
1045 |
$pkg, $ver, $arc, $mirror, $fil, $md5, $siz; |
1046 |
if ($unique) { |
1047 |
delete $fields{$val}; |
1048 |
last if (--$cnt <= 0); |
1049 |
} |
1050 |
} |
1051 |
undef $val; |
1052 |
} |
1053 |
} |
1054 |
for $v (keys %fields) { |
1055 |
printf ("%s -\n", $v) if ($unique); |
1056 |
} |
1057 |
' "$@" |
1058 |
} |
1059 |
|
1060 |
pkgdetails_perl () { |
1061 |
if [ "$1" = "WGET%" ]; then |
1062 |
shift; |
1063 |
perl -e ' |
1064 |
$v = 0; |
1065 |
while (read STDIN, $x, 1) { |
1066 |
if ($x =~ m/\d/) { |
1067 |
$v *= 10; |
1068 |
$v += $x; |
1069 |
} elsif ($x eq "%") { |
1070 |
printf "P: %d %d%s\n", int($v / 100.0 * ($ARGV[1] - $ARGV[0]) + $ARGV[0]), $ARGV[2], ($#ARGV == 3 ? " $ARGV[3]" : ""); |
1071 |
$v = 0; |
1072 |
} else { |
1073 |
$v = 0; |
1074 |
} |
1075 |
}' "$@" |
1076 |
elif [ "$1" = "GETDEPS" ]; then |
1077 |
local pkgdest="$2"; shift; shift |
1078 |
perl -e ' |
1079 |
while (<STDIN>) { |
1080 |
chomp; |
1081 |
$in = 1 if (/^Package: (.*)$/ && grep {$_ eq $1} @ARGV); |
1082 |
$in = 0 if (/^$/); |
1083 |
if ($in and (/^Depends: (.*)$/ or /^Pre-Depends: (.*)$/)) { |
1084 |
for $d (split /\s*,\s*/, $1) { |
1085 |
$d =~ s/\s*[|].*$//; |
1086 |
$d =~ s/\s*[(].*[)]\s*//; |
1087 |
print "$d\n"; |
1088 |
} |
1089 |
} |
1090 |
}' <"$pkgdest" "$@" | sort | uniq |
1091 |
elif [ "$1" = "PKGS" ]; then |
1092 |
local m="$2" |
1093 |
local p="$3" |
1094 |
shift; shift; shift |
1095 |
pkgdetails_field 1 Package: "$m" "$@" < "$p" |
1096 |
elif [ "$1" = "FIELD" ]; then |
1097 |
local f="$2" |
1098 |
local m="$3" |
1099 |
local p="$4" |
1100 |
shift; shift; shift; shift |
1101 |
pkgdetails_field 0 "$f" "$m" "$@" < "$p" |
1102 |
elif [ "$1" = "STANZAS" ]; then |
1103 |
local pkgdest="$2"; shift; shift |
1104 |
perl -e ' |
1105 |
my $accum = ""; |
1106 |
while (<STDIN>) { |
1107 |
$accum .= $_; |
1108 |
$in = 1 if (/^Package: (.*)$/ && grep {$_ eq $1} @ARGV); |
1109 |
if ($in and /^$/) { |
1110 |
print $accum; |
1111 |
if (substr($accum, -1) != "\n") { |
1112 |
print "\n\n"; |
1113 |
} elsif (substr($accum, -2, 1) != "\n") { |
1114 |
print "\n"; |
1115 |
} |
1116 |
$in = 0; |
1117 |
} |
1118 |
$accum = "" if /^$/; |
1119 |
}' <"$pkgdest" "$@" |
1120 |
fi |
1121 |
} |
1122 |
elif [ -e "/usr/lib/debootstrap/pkgdetails" ]; then |
1123 |
PKGDETAILS="/usr/lib/debootstrap/pkgdetails" |
1124 |
elif [ -e "$DEBOOTSTRAP_DIR/pkgdetails" ]; then |
1125 |
PKGDETAILS="$DEBOOTSTRAP_DIR/pkgdetails" |
1126 |
else |
1127 |
PKGDETAILS="" |
1128 |
fi |
1129 |
|
1130 |
##################################################### dependency resolution |
1131 |
|
1132 |
resolve_deps () { |
1133 |
local m1="${MIRRORS%% *}" |
1134 |
|
1135 |
# XXX: I can't think how to deal well with dependency resolution and |
1136 |
# lots of Packages files. -- aj 2005/06/12 |
1137 |
|
1138 |
c="${COMPONENTS%% *}" |
1139 |
local path="dists/$SUITE/$c/binary-$ARCH/Packages" |
1140 |
local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")" |
1141 |
|
1142 |
local PKGS="$*" |
1143 |
local ALLPKGS="$PKGS"; |
1144 |
local ALLPKGS2=""; |
1145 |
while [ "$PKGS" != "" ]; do |
1146 |
PKGS=$("$PKGDETAILS" GETDEPS "$pkgdest" $PKGS) |
1147 |
PKGS=$("$PKGDETAILS" PKGS REAL "$pkgdest" $PKGS | sed -n 's/ .*REAL.*$//p') |
1148 |
ALLPKGS2=$(echo "$PKGS $ALLPKGS" | tr ' ' '\n' | sort | uniq) |
1149 |
PKGS=$(without "$ALLPKGS2" "$ALLPKGS") |
1150 |
ALLPKGS="$ALLPKGS2" |
1151 |
done |
1152 |
echo $ALLPKGS |
1153 |
} |
1154 |
|
1155 |
setup_available () { |
1156 |
local m1="${MIRRORS%% *}" |
1157 |
|
1158 |
for c in $COMPONENTS; do |
1159 |
local path="dists/$SUITE/$c/binary-$ARCH/Packages" |
1160 |
local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")" |
1161 |
# XXX: What if a package is in more than one component? |
1162 |
# -- cjwatson 2009-07-29 |
1163 |
"$PKGDETAILS" STANZAS "$pkgdest" "$@" |
1164 |
done >"$TARGET/var/lib/dpkg/available" |
1165 |
|
1166 |
for pkg; do |
1167 |
echo "$pkg install" |
1168 |
done | in_target dpkg --set-selections |
1169 |
} |
1170 |
|
1171 |
get_next_predep () { |
1172 |
local stanza="$(in_target_nofail dpkg --predep-package)" |
1173 |
[ "$stanza" ] || return 1 |
1174 |
echo "$stanza" | grep '^Package:' | sed 's/^Package://; s/^ *//' |
1175 |
} |
1176 |
|
1177 |
################################################################### helpers |
1178 |
|
1179 |
# Return zero if it is possible to create devices and execute programs in |
1180 |
# this directory. (Both may be forbidden by mount options, e.g. nodev and |
1181 |
# noexec respectively.) |
1182 |
check_sane_mount () { |
1183 |
mkdir -p "$1" |
1184 |
|
1185 |
case "$ARCH" in |
1186 |
kfreebsd-*|hurd-*) |
1187 |
;; |
1188 |
*) |
1189 |
mknod "$1/test-dev-null" c 1 3 || return 1 |
1190 |
if ! echo test > "$1/test-dev-null"; then |
1191 |
rm -f "$1/test-dev-null" |
1192 |
return 1 |
1193 |
fi |
1194 |
rm -f "$1/test-dev-null" |
1195 |
;; |
1196 |
esac |
1197 |
|
1198 |
cat > "$1/test-exec" <<EOF |
1199 |
#! /bin/sh |
1200 |
: |
1201 |
EOF |
1202 |
chmod +x "$1/test-exec" |
1203 |
if ! "$1/test-exec"; then |
1204 |
rm -f "$1/test-exec" |
1205 |
return 1 |
1206 |
fi |
1207 |
rm -f "$1/test-exec" |
1208 |
|
1209 |
return 0 |
1210 |
} |
1211 |
|
1212 |
read_gpg_status () { |
1213 |
badsig= |
1214 |
unkkey= |
1215 |
validsig= |
1216 |
while read prefix keyword keyid rest; do |
1217 |
[ "$prefix" = '[GNUPG:]' ] || continue |
1218 |
case $keyword in |
1219 |
BADSIG) badsig="$keyid" ;; |
1220 |
NO_PUBKEY) unkkey="$keyid" ;; |
1221 |
VALIDSIG) validsig="$keyid" ;; |
1222 |
esac |
1223 |
done |
1224 |
if [ "$validsig" ]; then |
1225 |
info VALIDRELSIG "Valid Release signature (key id %s)" "$validsig" |
1226 |
elif [ "$badsig" ]; then |
1227 |
error 1 BADRELSIG "Invalid Release signature (key id %s)" "$badsig" |
1228 |
elif [ "$unkkey" ]; then |
1229 |
error 1 UNKNOWNRELSIG "Release signed by unknown key (key id %s)" "$unkkey" |
1230 |
else |
1231 |
error 1 SIGCHECK "Error executing gpgv to check Release signature" |
1232 |
fi |
1233 |
} |
1234 |
|
1235 |
without () { |
1236 |
# usage: without "a b c" "a d" -> "b" "c" |
1237 |
(echo $1 | tr ' ' '\n' | sort | uniq; |
1238 |
echo $2 $2 | tr ' ' '\n') | sort | uniq -u | tr '\n' ' ' |
1239 |
echo |
1240 |
} |
1241 |
|
1242 |
# Formerly called 'repeat', but that's a reserved word in zsh. |
1243 |
repeatn () { |
1244 |
local n="$1" |
1245 |
shift |
1246 |
while [ "$n" -gt 0 ]; do |
1247 |
if "$@"; then |
1248 |
break |
1249 |
else |
1250 |
n="$(( $n - 1 ))" |
1251 |
sleep 1 |
1252 |
fi |
1253 |
done |
1254 |
if [ "$n" -eq 0 ]; then return 1; fi |
1255 |
return 0 |
1256 |
} |
1257 |
|
1258 |
N_EXIT_THINGS=0 |
1259 |
exit_function () { |
1260 |
local n=0 |
1261 |
while [ "$n" -lt "$N_EXIT_THINGS" ]; do |
1262 |
(eval $(eval echo \${EXIT_THING_$n}) 2>/dev/null || true) |
1263 |
n="$(( $n + 1 ))" |
1264 |
done |
1265 |
N_EXIT_THINGS=0 |
1266 |
} |
1267 |
|
1268 |
trap "exit_function" 0 |
1269 |
trap "exit 129" 1 |
1270 |
trap "error 130 INTERRUPTED \"Interrupt caught ... exiting\"" 2 |
1271 |
trap "exit 131" 3 |
1272 |
trap "exit 143" 15 |
1273 |
|
1274 |
on_exit () { |
1275 |
eval `echo EXIT_THING_${N_EXIT_THINGS}=\"$1\"` |
1276 |
N_EXIT_THINGS="$(( $N_EXIT_THINGS + 1 ))" |
1277 |
} |
1278 |
|
1279 |
############################################################## fakechroot tools |
1280 |
|
1281 |
install_fakechroot_tools () { |
1282 |
mv "$TARGET/sbin/ldconfig" "$TARGET/sbin/ldconfig.REAL" |
1283 |
echo \ |
1284 |
"#!/bin/sh |
1285 |
echo |
1286 |
echo \"Warning: Fake ldconfig called, doing nothing\"" > "$TARGET/sbin/ldconfig" |
1287 |
chmod 755 "$TARGET/sbin/ldconfig" |
1288 |
|
1289 |
echo \ |
1290 |
"/sbin/ldconfig |
1291 |
/sbin/ldconfig.REAL |
1292 |
fakechroot" >> "$TARGET/var/lib/dpkg/diversions" |
1293 |
|
1294 |
mv "$TARGET/usr/bin/ldd" "$TARGET/usr/bin/ldd.REAL" |
1295 |
cat << 'END' > "$TARGET/usr/bin/ldd" |
1296 |
#!/usr/bin/perl |
1297 |
|
1298 |
# fakeldd |
1299 |
# |
1300 |
# Replacement for ldd with usage of objdump |
1301 |
# |
1302 |
# (c) 2003-2005 Piotr Roszatycki <dexter@debian.org>, BSD |
1303 |
|
1304 |
|
1305 |
my %libs = (); |
1306 |
|
1307 |
my $status = 0; |
1308 |
my $dynamic = 0; |
1309 |
my $biarch = 0; |
1310 |
|
1311 |
my $ldlinuxsodir = "/lib"; |
1312 |
my @ld_library_path = qw(/usr/lib /lib); |
1313 |
|
1314 |
|
1315 |
sub ldso($) { |
1316 |
my ($lib) = @_; |
1317 |
my @files = (); |
1318 |
|
1319 |
if ($lib =~ /^\//) { |
1320 |
$libs{$lib} = $lib; |
1321 |
push @files, $lib; |
1322 |
} else { |
1323 |
foreach my $ld_path (@ld_library_path) { |
1324 |
next unless -f "$ld_path/$lib"; |
1325 |
my $badformat = 0; |
1326 |
open OBJDUMP, "objdump -p $ld_path/$lib 2>/dev/null |"; |
1327 |
while (my $line = <OBJDUMP>) { |
1328 |
if ($line =~ /file format (\S*)$/) { |
1329 |
$badformat = 1 unless $format eq $1; |
1330 |
last; |
1331 |
} |
1332 |
} |
1333 |
close OBJDUMP; |
1334 |
next if $badformat; |
1335 |
$libs{$lib} = "$ld_path/$lib"; |
1336 |
push @files, "$ld_path/$lib"; |
1337 |
} |
1338 |
objdump(@files); |
1339 |
} |
1340 |
} |
1341 |
|
1342 |
|
1343 |
sub objdump(@) { |
1344 |
my (@files) = @_; |
1345 |
my @libs = (); |
1346 |
|
1347 |
foreach my $file (@files) { |
1348 |
open OBJDUMP, "objdump -p $file 2>/dev/null |"; |
1349 |
while (my $line = <OBJDUMP>) { |
1350 |
$line =~ s/^\s+//; |
1351 |
my @f = split (/\s+/, $line); |
1352 |
if ($line =~ /file format (\S*)$/) { |
1353 |
if (not $format) { |
1354 |
$format = $1; |
1355 |
if ($unamearch eq "x86_64" and $format eq "elf32-i386") { |
1356 |
my $link = readlink "/lib/ld-linux.so.2"; |
1357 |
if ($link =~ /^\/emul\/ia32-linux\//) { |
1358 |
$ld_library_path[-2] = "/emul/ia32-linux/usr/lib"; |
1359 |
$ld_library_path[-1] = "/emul/ia32-linux/lib"; |
1360 |
} |
1361 |
} elsif ($unamearch =~ /^(sparc|sparc64)$/ and $format eq "elf64-sparc") { |
1362 |
$ldlinuxsodir = "/lib64"; |
1363 |
$ld_library_path[-2] = "/usr/lib64"; |
1364 |
$ld_library_path[-1] = "/lib64"; |
1365 |
} |
1366 |
} else { |
1367 |
next unless $format eq $1; |
1368 |
} |
1369 |
} |
1370 |
if (not $dynamic and $f[0] eq "Dynamic") { |
1371 |
$dynamic = 1; |
1372 |
} |
1373 |
next unless $f[0] eq "NEEDED"; |
1374 |
if ($f[1] =~ /^ld-linux(\.|-)/) { |
1375 |
$f[1] = "$ldlinuxsodir/" . $f[1]; |
1376 |
} |
1377 |
if (not defined $libs{$f[1]}) { |
1378 |
$libs{$f[1]} = undef; |
1379 |
push @libs, $f[1]; |
1380 |
} |
1381 |
} |
1382 |
close OBJDUMP; |
1383 |
} |
1384 |
|
1385 |
foreach my $lib (@libs) { |
1386 |
ldso($lib); |
1387 |
} |
1388 |
} |
1389 |
|
1390 |
|
1391 |
if ($#ARGV < 0) { |
1392 |
print STDERR "fakeldd: missing file arguments\n"; |
1393 |
exit 1; |
1394 |
} |
1395 |
|
1396 |
while ($ARGV[0] =~ /^-/) { |
1397 |
my $arg = $ARGV[0]; |
1398 |
shift @ARGV; |
1399 |
last if $arg eq "--"; |
1400 |
} |
1401 |
|
1402 |
open LD_SO_CONF, "/etc/ld.so.conf"; |
1403 |
while ($line = <LD_SO_CONF>) { |
1404 |
chomp $line; |
1405 |
unshift @ld_library_path, $line; |
1406 |
} |
1407 |
close LD_SO_CONF; |
1408 |
|
1409 |
unshift @ld_library_path, split(/:/, $ENV{LD_LIBRARY_PATH}); |
1410 |
|
1411 |
$unamearch = `/bin/uname -m`; |
1412 |
chomp $unamearch; |
1413 |
|
1414 |
foreach my $file (@ARGV) { |
1415 |
my $address; |
1416 |
%libs = (); |
1417 |
$dynamic = 0; |
1418 |
|
1419 |
if ($#ARGV > 0) { |
1420 |
print "$file:\n"; |
1421 |
} |
1422 |
|
1423 |
if (not -f $file) { |
1424 |
print STDERR "ldd: $file: No such file or directory\n"; |
1425 |
$status = 1; |
1426 |
next; |
1427 |
} |
1428 |
|
1429 |
objdump($file); |
1430 |
|
1431 |
if ($dynamic == 0) { |
1432 |
print "\tnot a dynamic executable\n"; |
1433 |
$status = 1; |
1434 |
} elsif (scalar %libs eq "0") { |
1435 |
print "\tstatically linked\n"; |
1436 |
} |
1437 |
|
1438 |
if ($format =~ /^elf64-/) { |
1439 |
$address = "0x0000000000000000"; |
1440 |
} else { |
1441 |
$address = "0x00000000"; |
1442 |
} |
1443 |
|
1444 |
foreach $lib (keys %libs) { |
1445 |
if ($libs{$lib}) { |
1446 |
printf "\t%s => %s (%s)\n", $lib, $libs{$lib}, $address; |
1447 |
} else { |
1448 |
printf "\t%s => not found\n", $lib; |
1449 |
} |
1450 |
} |
1451 |
} |
1452 |
|
1453 |
exit $status; |
1454 |
END |
1455 |
chmod 755 "$TARGET/usr/bin/ldd" |
1456 |
|
1457 |
echo \ |
1458 |
"/usr/bin/ldd |
1459 |
/usr/bin/ldd.REAL |
1460 |
fakechroot" >> "$TARGET/var/lib/dpkg/diversions" |
1461 |
|
1462 |
} |